/* * Copyright 2007-2008 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 "ItemEffect.h" // Pokemod includes #include "MapWildList.h" #include "Pokemod.h" const QStringList ItemEffect::EffectStr = QStringList() << "HP Cure" << "Revive" << "Cure Status" << "Level Boost" << "Stat Boost" << "Flinch" << "Go First" << "Keep Alive" << "Modify Stat (Battle Only)" << "Shield (Battle Only)" << "Run (Battle Only)" << "PP Boost" << "Type Boost" << "PP Restore" << "Experience Share" << "Fishing Rod" << "Repel" << "Escape" << "TM" << "HM" << "Map" << "Ball" << "Itemfinder" << "Bike" << "Scope" << "Coin" << "Coin Case" << "Berry" << "Acorn"; const QStringList ItemEffect::RelativeStr = QStringList() << "Absolute" << "Relative"; const QStringList ItemEffect::EscapeStr = QStringList() << "Anywhere" << "Dungeon"; const QStringList ItemEffect::RepelStr = QStringList() << "First" << "Max" << "All"; const QStringList ItemEffect::AmountStr = QStringList() << "All" << "One"; const QStringList ItemEffect::SpecialPhysicalStr = QStringList() << "Special" << "Physical"; const QStringList ItemEffect::BallTypeStr = QStringList() << "Regular" << "Master" << "Level" << "Love" << "Area" << "Time" << "Battle" << "Friend" << "Stat" << "Type" << "Weight"; const QStringList ItemEffect::BerryTypeStr = QStringList() << "HP Cure" << "Status Cure"; ItemEffect::ItemEffect(const ItemEffect& effect) : Object("ItemEffect", effect.parent(), effect.id()) { *this = effect; } ItemEffect::ItemEffect(const Object* parent, const int id) : Object("ItemEffect", parent, id), m_overworld(false), m_battle(false), m_held(false), m_effect(INT_MAX), m_value1(INT_MAX), m_value2(INT_MAX), m_value3(INT_MAX), m_value4(1, 1) { } ItemEffect::ItemEffect(const ItemEffect& effect, const Object* parent, const int id) : Object("ItemEffect", parent, id) { *this = effect; } ItemEffect::ItemEffect(const QDomElement& xml, const Object* parent, const int id) : Object("ItemEffect", parent, id) { load(xml, id); } bool ItemEffect::validate() const { // TODO: validate // bool valid = true; // static_cast(pokemod())->validationMsg(QString("------Effect with id %1---").arg(id()), Pokemod::V_Msg); // switch (m_effect) // { // case E_Revive: // case E_LevelBoost: // case E_StatBoost: // case E_PPBoost: // case E_Fish: // case E_Repel: // case E_Escape: // case E_TM: // case E_HM: // case E_Map: // case E_Itemfinder: // case E_Bike: // case E_Scope: // case E_Coin: // case E_CoinCase: // case E_Acorn: // case E_Evolution: // if (!m_overworld) // { // static_cast(pokemod())->validationMsg("Effect only works in the overworld"); // valid = false; // } // break; // case E_Flinch: // case E_First: // case E_KeepAlive: // case E_ModifyStatBattle: // case E_ShieldBattle: // case E_RunBattle: // case E_TypeBoost: // case E_ExpShare: // case E_Ball: // case E_Berry: // if (m_overworld) // { // valid = false; // static_cast(pokemod())->validationMsg("Effect cannot work in the overworld"); // } // break; // } // if (m_effect < E_End) // { // bool ok = true; // switch (m_effect) // { // case E_HPCure: // case E_Revive: // if ((m_value4 != R_Absolute) || !m_value1) // ok = false; // break; // case E_LevelBoost: // case E_ShieldBattle: // case E_PPBoost: // case E_Repel: // if (!m_value1) // ok = false; // break; // case E_StatBoost: // case E_Acorn: // if ((m_value1 < 0) || (65536 <= m_value1)) // ok = false; // break; // case E_ModifyStatBattle: // if ((m_value1 < -12) || (12 < m_value1)) // ok = false; // break; // case E_Ball: // switch (m_value2) // { // case B_Regular: // if (256 <= m_value1) // ok = false; // break; // case B_Level: // if (static_cast(pokemod())->rules()->maxLevel() < m_value1) // ok = false; // break; // case B_Master: // case B_Love: // case B_Area: // case B_Time: // case B_Battle: // case B_Friend: // case B_Stat: // case B_Type: // case B_Weight: // break; // default: // ok = false; // break; // } // break; // } // if (!ok) // { // static_cast(pokemod())->validationMsg("Invalid value 1"); // valid = false; // ok = true; // } // switch (m_effect) // { // case E_HPCure: // case E_Revive: // if (R_End <= m_value2) // ok = false; // break; // case E_CureStatus: // if (Pokemod::STS_End <= m_value2) // ok = false; // break; // case E_StatBoost: // if ((m_value2 <= 0) || (65536 <= m_value2)) // ok = false; // break; // case E_ModifyStatBattle: // if (Pokemod::ST_End_Battle <= m_value2) // ok = false; // break; // case E_ShieldBattle: // if (SP_End <= m_value2) // ok = false; // break; // case E_TypeBoost: // if (static_cast(pokemod())->typeIndex(m_value2) == INT_MAX) // ok = false; // break; // case E_PPRestore: // if (A_End <= m_value2) // ok = false; // break; // case E_Repel: // if (RP_End <= m_value2) // ok = false; // break; // case E_Escape: // if (ES_End <= m_value2) // ok = false; // break; // case E_TM: // case E_HM: // if (static_cast(pokemod())->moveIndex(m_value2) == INT_MAX) // ok = false; // break; // case E_Ball: // if (B_End <= m_value2) // ok = false; // break; // case E_Berry: // if (B2_End <= m_value2) // ok = false; // break; // case E_Coin: // case E_CoinCase: // if (m_value2 <= 0) // ok = false; // break; // case E_Acorn: // if (static_cast(pokemod())->itemIndex(m_value2) == INT_MAX) // ok = false; // break; // } // if (!ok) // { // static_cast(pokemod())->validationMsg("Invalid value 2"); // valid = false; // ok = true; // } // switch (m_effect) // { // case E_StatBoost: // if ((static_cast(pokemod())->rules()->specialSplit() ? Pokemod::ST_End_GSC : Pokemod::ST_End_RBY) <= m_value3) // ok = false; // break; // case E_Ball: // switch (m_value2) // { // case B_Regular: // case B_Master: // case B_Level: // case B_Love: // case B_Battle: // case B_Friend: // case B_Weight: // break; // case B_Area: // if (MapWildList::End <= m_value3) // ok = false; // break; // case B_Time: // if (static_cast(pokemod())->timeIndex(m_value3) == INT_MAX) // ok = false; // break; // case B_Stat: // if ((static_cast(pokemod())->rules()->specialSplit() ? Pokemod::ST_End_GSC : Pokemod::ST_End_RBY) <= m_value3) // ok = false; // break; // case B_Type: // if (static_cast(pokemod())->typeIndex(m_value3) == INT_MAX) // ok = false; // break; // } // break; // case E_Berry: // switch (m_value2) // { // case B2_HPCure: // if (Pokemod::REL_End <= m_value3) // ok = false; // break; // case B2_StatusCure: // if (Pokemod::STS_End <= m_value3) // ok = false; // break; // default: // ok = false; // break; // } // break; // } // if (!ok) // { // static_cast(pokemod())->validationMsg("Invalid value 3"); // valid = false; // } // } // else // { // static_cast(pokemod())->validationMsg("Invalid effect"); // valid = false; // } // return valid; } void ItemEffect::load(const QDomElement& xml, int id) { LOAD_ID(); LOAD(bool, overworld); LOAD(bool, battle); LOAD(bool, held); LOAD(int, effect); LOAD(int, value1); LOAD(int, value2); LOAD(int, value3); LOAD(Fraction, value4); } QDomElement ItemEffect::save() const { SAVE_CREATE(); SAVE(bool, overworld); SAVE(bool, battle); SAVE(bool, held); SAVE(int, effect); SAVE(int, value1); SAVE(int, value2); SAVE(int, value3); SAVE(Fraction, value4); return xml; } void ItemEffect::setOverworld(const bool overworld) throw(Exception) { switch (m_effect) { case E_Revive: case E_LevelBoost: case E_StatBoost: case E_PPBoost: case E_Fish: case E_Repel: case E_Escape: case E_TM: case E_HM: case E_Map: case E_Itemfinder: case E_Bike: case E_Scope: case E_Coin: case E_CoinCase: case E_Acorn: case E_Evolution: if (!overworld) throw(Exception(className(), "overworld mismatch")); break; case E_Flinch: case E_First: case E_KeepAlive: case E_ModifyStatBattle: case E_ShieldBattle: case E_RunBattle: case E_TypeBoost: case E_ExpShare: case E_Ball: case E_Berry: if (overworld) throw(Exception(className(), "overworld mismatch")); break; } m_overworld = overworld; } void ItemEffect::setBattle(const bool battle) { m_battle = battle; } void ItemEffect::setHeld(const bool held) { m_held = held; } void ItemEffect::setEffect(const int effect) throw(Exception) { if (E_End <= effect) throw(BoundsException(className(), "effect out-of-bounds")); switch (effect) { case E_Revive: case E_LevelBoost: case E_StatBoost: case E_PPBoost: case E_Fish: case E_Repel: case E_Escape: case E_TM: case E_HM: case E_Map: case E_Itemfinder: case E_Bike: case E_Scope: case E_Coin: case E_CoinCase: case E_Acorn: case E_Evolution: m_overworld = true; break; case E_Flinch: case E_First: case E_KeepAlive: case E_ModifyStatBattle: case E_ShieldBattle: case E_RunBattle: case E_TypeBoost: case E_ExpShare: case E_Ball: case E_Berry: m_overworld = false; break; } m_effect = effect; m_value1 = 0; m_value2 = INT_MAX; m_value3 = INT_MAX; m_value4.set(1, 1); } void ItemEffect::setValue1(const int value1) throw(Exception) { switch (m_effect) { case E_HPCure: case E_Revive: if ((m_value4 != R_Absolute) || !value1) error("value1"); break; case E_LevelBoost: case E_ShieldBattle: case E_PPBoost: case E_Repel: if (!value1) error("value1"); break; case E_StatBoost: case E_Acorn: if ((value1 < 0) || (65536 <= value1)) error("value1"); break; case E_ModifyStatBattle: if ((value1 < -12) || (12 < value1)) error("value1"); break; case E_Fish: case E_Coin: case E_CoinCase: break; case E_Ball: switch (m_value2) { case B_Regular: if (256 <= value1) error("value1"); break; case B_Level: if (static_cast(pokemod())->rules()->maxLevel() < value1) error("value1"); break; case B_Master: case B_Love: case B_Area: case B_Time: case B_Battle: case B_Friend: case B_Stat: case B_Type: case B_Weight: break; default: error("value1"); } break; default: error("value1"); break; } m_value1 = value1; } void ItemEffect::setValue2(const int value2) throw(Exception) { switch (m_effect) { case E_HPCure: case E_Revive: if (R_End <= value2) error("value2"); break; case E_CureStatus: if (Pokemod::STS_End <= value2) error("value2"); break; case E_StatBoost: if ((value2 <= 0) || (65536 <= value2)) error("value2"); break; case E_ModifyStatBattle: if (Pokemod::ST_End_Battle <= value2) error("value2"); break; case E_ShieldBattle: if (SP_End <= value2) error("value2"); break; case E_TypeBoost: if (static_cast(pokemod())->typeIndex(value2) == INT_MAX) error("value2"); break; case E_PPRestore: if (A_End <= value2) error("value2"); break; case E_Repel: if (RP_End <= value2) error("value2"); break; case E_Escape: if (ES_End <= value2) error("value2"); break; case E_TM: case E_HM: if (static_cast(pokemod())->moveIndex(value2) == INT_MAX) error("value2"); break; case E_Ball: if (B_End <= value2) error("value2"); break; case E_Scope: break; case E_Berry: if (B2_End <= value2) error("value2"); break; case E_Coin: case E_CoinCase: if (value2 <= 0) error("value2"); break; case E_Acorn: if (static_cast(pokemod())->itemIndex(value2) == INT_MAX) error("value2"); break; default: error("value2"); break; } m_value2 = value2; } void ItemEffect::setValue3(const int value3) throw(Exception) { switch (m_effect) { case E_StatBoost: if ((static_cast(pokemod())->rules()->specialSplit() ? Pokemod::ST_End_GSC : Pokemod::ST_End_RBY) <= value3) error("value3"); break; case E_Ball: switch (m_value2) { case B_Level: case B_Friend: case B_Weight: break; case B_Area: if (MapWildList::End <= value3) error("value3"); break; case B_Time: if (static_cast(pokemod())->timeIndex(value3) == INT_MAX) error("value3"); break; case B_Stat: if ((static_cast(pokemod())->rules()->specialSplit() ? Pokemod::ST_End_GSC : Pokemod::ST_End_RBY) <= value3) error("value3"); break; case B_Type: if (static_cast(pokemod())->typeIndex(value3) == INT_MAX) error("value3"); break; case B_Regular: case B_Master: case B_Love: case B_Battle: error("value3"); break; } break; case E_Berry: switch (m_value2) { case B2_HPCure: if (Pokemod::REL_End <= value3) error("value3"); break; case B2_StatusCure: if (Pokemod::STS_End <= value3) error("value3"); break; default: error("value3"); break; } break; default: error("value3"); break; } m_value3 = value3; } void ItemEffect::setValue4(const Fraction& value4) throw(Exception) { if ((E_TypeBoost == m_effect) || (E_PPBoost == m_effect)) { if (value4 < 1) error("value4"); } else if (1 < value4) error("value4"); switch (m_effect) { case E_CureStatus: case E_LevelBoost: case E_StatBoost: case E_ModifyStatBattle: case E_Fish: case E_Escape: case E_TM: case E_HM: case E_Map: case E_Itemfinder: case E_Bike: case E_Scope: case E_Coin: case E_CoinCase: case E_Acorn: case E_Evolution: error("value4"); case E_Ball: if (m_value2 == B_Master) error("value4"); break; case E_Berry: if (m_value2 != B2_HPCure) error("value4"); break; } m_value4 = value4; } bool ItemEffect::overworld() const { return m_overworld; } bool ItemEffect::battle() const { return m_battle; } bool ItemEffect::held() const { return m_held; } int ItemEffect::effect() const { return m_effect; } int ItemEffect::value1() const { return m_value1; } int ItemEffect::value2() const { return m_value2; } int ItemEffect::value3() const { return m_value3; } Fraction ItemEffect::value4() const { return m_value4; } ItemEffect& ItemEffect::operator=(const ItemEffect& rhs) { if (this == &rhs) return *this; COPY(overworld); COPY(battle); COPY(held); COPY(effect); COPY(value1); COPY(value2); COPY(value3); COPY(value4); return *this; }