/* * Copyright 2007-2009 Ben Boeckel * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ // Header include #include "TeamMember.h" // Sigencore includes #include "Arena.h" #include "Containment.h" #include "Overworld.h" #include "Player.h" #include "RunScript.h" #include "Team.h" // Sigscript includes #include #include #include #include #include #include #include #include #include // Sigcore includes #include // KDE includes #include #include #include // Qt includes #include // C includes #include using namespace Sigcore; using namespace Sigmod; using namespace Sigscript; using namespace Sigencore; int Sigencore::actionPriority(TeamMember* teamMember, const TeamMember::Action& action) { int priority = INT_MAX; switch (action.first) { case TeamMember::Attack: { const QString move = action.second.first.toString(); const QString tag = QString("move-priority-%1").arg(move); priority = teamMember->game()->move(move)->priority(); if (teamMember->valueOfType(tag, &priority)) teamMember->removeValue(tag); break; } case TeamMember::Item: priority = INT_MIN / 4; break; case TeamMember::Switch: priority = INT_MIN / 2; break; case TeamMember::Run: priority = 3 * (INT_MIN / 4); break; case TeamMember::Timeout: priority = INT_MAX; break; default: { bool ok; ObjectMap objects; objects["owner"] = teamMember; objects["game"] = teamMember->game(); Kross::Action* kaction = globalScript(teamMember->game(), QString("battleaction-priority-%1").arg(action.first), QUuid::createUuid().toString(), objects, Kross::Manager::self().actionCollection()); priority = kaction->callFunction("priority").toInt(&ok); if (!ok) priority = 0; break; } } return priority; } TeamMember::TeamMember(SpeciesWrapper* species, const int level, Team* team, const bool suppressInitialization) : Creature(species, level, team, suppressInitialization), m_team(team), m_arena(NULL) { for (int i = 0; i < (ST_SpecialDefense - ST_Attack + 1); ++i) m_stages[i] = 0; } TeamMember::~TeamMember() { if (m_arena) exitArena(); // TODO: Clean up scripts } bool TeamMember::setContainment(Containment* containment) { Team* team = qobject_cast(containment); if (team) return setTeam(team); if (m_containment && !m_containment->removeMember(this)) return false; m_containment = containment; return true; } bool TeamMember::setTeam(Team* team) { if (m_team && !m_team->removeTeamMember(this)) return false; m_team = team; m_containment = team; return true; } Team* TeamMember::team() const { return m_team; } bool TeamMember::setStatStage(const Stat stat, const int stage) { if (stat == ST_HP) return false; if ((m_game->rules()->maxStages() < 0) || (m_game->rules()->maxStages() < qAbs(stage))) return false; m_stages[stat - ST_Attack] = stage; emit(statStageChanged(stat, stage)); return true; } bool TeamMember::giveStatStages(const Stat stat, const int stages) { if (stat == ST_HP) return false; return setStatStage(stat, m_stages[stat - ST_Attack] + stages); } int TeamMember::statStage(const Stat stat) const { int stages; if (stat == ST_HP) return 0; if (valueOfType(QString("stat-stages-%1").arg((m_game->rules()->specialSplit() ? StatGSCStr : StatRBYStr)[stat]), &stages) && ((m_game->rules()->maxStages() < 0) || (qAbs(stages) <= m_game->rules()->maxStages()))) return stages; return m_stages[stat - ST_Attack]; } int TeamMember::statValue(const Stat stat) const { Fraction multiplier; const int stage = statStage(stat); if (0 < stage) multiplier *= Fraction(stage + 2, 2); else if (stage < 0) multiplier *= Fraction(2, stage + 2); return multiplier * Creature::statValue(stat); } bool TeamMember::addAbility(AbilityWrapper* ability) { if ((m_abilities.size() < m_game->rules()->maxAbilities()) && !m_abilities.contains(ability)) { Team* team = qobject_cast(m_containment); if (team) { ObjectMap worldObjects; worldObjects["ability"] = ability; worldObjects["owner"] = this; worldObjects["client"] = team->player(); worldObjects["game"] = m_game; worldObjects["world"] = team->player()->world(); Kross::Action* worldAction = runScript(QUuid::createUuid(), ability->worldScript(), worldObjects, m_abilityWorldScripts); m_abilityWorldScriptsMap[ability] = worldAction; worldAction->trigger(); if (m_arena) { ObjectMap arenaObjects; arenaObjects["ability"] = ability; arenaObjects["owner"] = this; arenaObjects["client"] = team->player(); arenaObjects["game"] = m_game; arenaObjects["arena"] = m_arena; Kross::Action* battleAction = runScript(QUuid::createUuid(), ability->battleScript(), arenaObjects, m_abilityBattleScripts); m_abilityWorldScriptsMap[ability] = battleAction; battleAction->trigger(); } } m_abilities.append(ability); emit(abilityAdded(ability)); return true; } return false; } bool TeamMember::removeAbility(AbilityWrapper* ability) { if (m_abilities.contains(ability)) { delete m_abilityBattleScriptsMap[ability]; m_abilityBattleScriptsMap.remove(ability); delete m_abilityWorldScriptsMap[ability]; m_abilityWorldScriptsMap.remove(ability); m_abilities.removeOne(ability); emit(abilityRemoved(ability)); return true; } return false; } bool TeamMember::addItems(ItemWrapper* item, const int count, const bool allOrNothing) { // TODO: Handle scripts } bool TeamMember::addMove(MoveWrapper* move) { bool canLearn = false; for (int i = 0; !canLearn && (i < m_species->moveCount()); ++i) { if (m_species->move(i)->move() == move) canLearn = true; } if (canLearn && (m_moves.size() < m_game->rules()->maxMoves()) && !m_moves.contains(move)) { Team* team = qobject_cast(m_containment); if (team) { ObjectMap worldObjects; worldObjects["move"] = move; worldObjects["owner"] = this; worldObjects["client"] = team->player(); worldObjects["game"] = m_game; worldObjects["world"] = team->player()->world(); Kross::Action* worldAction = runScript(QUuid::createUuid(), move->worldScript(), worldObjects, m_moveWorldScripts); m_moveWorldScriptsMap[move] = worldAction; worldAction->trigger(); } m_moves.append(move); emit(moveAdded(move)); return true; } return false; } bool TeamMember::removeMove(MoveWrapper* move) { if (m_moves.contains(move) && (1 < m_moves.size())) { delete m_moveBattleScriptsMap[move]; m_moveBattleScriptsMap.remove(move); delete m_moveWorldScriptsMap[move]; m_moveWorldScriptsMap.remove(move); m_moves.removeOne(move); emit(moveRemoved(move)); return true; } return false; } bool TeamMember::addNature(NatureWrapper* nature) { if ((m_natures.size() < m_game->rules()->maxNatures()) && !m_natures.contains(nature)) { m_natures.append(nature); emit(natureAdded(nature)); return true; } return false; } bool TeamMember::removeNature(NatureWrapper* nature) { if (m_natures.contains(nature)) { m_natures.removeOne(nature); emit(natureRemoved(nature)); return true; } return false; } bool TeamMember::addStatus(StatusWrapper* status) { if (!m_status.contains(status)) { Team* team = qobject_cast(m_containment); if (team) { ObjectMap worldObjects; worldObjects["status"] = status; worldObjects["owner"] = this; worldObjects["client"] = team->player(); worldObjects["game"] = m_game; worldObjects["world"] = team->player()->world(); Kross::Action* worldAction = runScript(QUuid::createUuid(), status->worldScript(), worldObjects, m_statusWorldScripts); m_statusWorldScriptsMap[status] = worldAction; worldAction->trigger(); if (m_arena) { ObjectMap arenaObjects; arenaObjects["status"] = status; arenaObjects["owner"] = this; arenaObjects["client"] = team->player(); arenaObjects["game"] = m_game; arenaObjects["arena"] = m_arena; Kross::Action* battleAction = runScript(QUuid::createUuid(), status->battleScript(), arenaObjects, m_statusBattleScripts); m_statusWorldScriptsMap[status] = battleAction; battleAction->trigger(); } } m_status.append(status); emit(statusAdded(status)); return true; } return false; } bool TeamMember::removeStatus(StatusWrapper* status) { if (m_status.contains(status)) { delete m_statusBattleScriptsMap[status]; m_statusBattleScriptsMap.remove(status); delete m_statusWorldScriptsMap[status]; m_statusWorldScriptsMap.remove(status); m_status.removeOne(status); emit(statusRemoved(status)); return true; } return false; } void TeamMember::makeActive(Arena* arena) { // TODO Team* team = qobject_cast(this->containment()); foreach (StatusWrapper* status, m_status) { const Script script = status->battleScript(); if (!script.script().isEmpty()) { ObjectMap objects; objects["arena"] = arena; objects["game"] = m_game; if (team) objects["client"] = team->player(); objects["owner"] = this; Kross::Action* action = runScript(QUuid::createUuid().toString(), script, objects, Kross::Manager::self().actionCollection()->collection("status")); m_statusBattleScriptsMap[status] = action; action->trigger(); } } foreach (AbilityWrapper* ability, m_abilities) { const Script script = ability->battleScript(); if (!script.script().isEmpty()) { ObjectMap objects; objects["arena"] = arena; objects["game"] = m_game; if (team) objects["client"] = team->player(); objects["owner"] = this; Kross::Action* action = runScript(QUuid::createUuid().toString(), script, objects, Kross::Manager::self().actionCollection()->collection("ability")); m_abilityBattleScriptsMap[ability] = action; action->trigger(); } } m_arena = arena; } void TeamMember::exitArena() { qDeleteAll(m_statusBattleScriptsMap.values()); m_statusBattleScriptsMap.clear(); qDeleteAll(m_abilityBattleScriptsMap.values()); m_abilityBattleScriptsMap.clear(); for (int i = ST_Attack; i <= ST_Evasion; ++i) { const QString entry = QString("stat-stages-%1").arg((m_game->rules()->specialSplit() ? StatGSCStr : StatRBYStr)[i]); if (options(entry) & Temporary) removeValue(entry, false); } m_arena = NULL; } void TeamMember::makeConnections() { connect(this, SIGNAL(statStageChanged(Stat, int)), SLOT(recalcStat(Stat))); Creature::makeConnections(); }