/* * 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 "Species.h" // Sigmod includes #include "Macros.h" #include "Rules.h" #include "Sigmod.h" #include "SpeciesAbility.h" #include "SpeciesItem.h" #include "SpeciesMove.h" // Qt includes #include const QStringList Sigmod::Species::StyleStr = QStringList() << "Fluctuating" << "Fading" << "Slow" << "Normal" << "Fast" << "Erratic"; Sigmod::Species::Species(const Species& species) : Object(species.parent(), species.id()), m_baseStat(ST_SpecialDefense - ST_HP + 1), m_effortValue(ST_SpecialDefense - ST_HP + 1) { *this = species; } Sigmod::Species::Species(const Sigmod* parent, const int id) : Object(parent, id), m_name(""), m_baseStat(ST_SpecialDefense - ST_HP + 1), m_effortValue(ST_SpecialDefense - ST_HP + 1), m_growth(Normal), m_catchValue(0), m_maxHoldWeight(0), m_runChance(1, 1), m_fleeChance(1, 1), m_itemChance(1, 1), m_encyclopediaNumber(INT_MAX), m_weight(0), m_height(0), m_frontMaleSprite(-1), m_backMaleSprite(-1), m_frontFemaleSprite(-1), m_backFemaleSprite(-1), m_skin(-1), m_encyclopediaEntry(""), m_genderFactor(1, 1), m_eggSpecies(INT_MAX), m_eggSteps(0), m_evolution("", "") { for (int i = 0; i < m_baseStat.size(); ++i) m_baseStat[i] = 0; for (int i = 0; i < m_effortValue.size(); ++i) m_effortValue[i] = 0; } Sigmod::Species::Species(const Species& species, const Sigmod* parent, const int id) : Object(parent, id), m_baseStat(ST_SpecialDefense - ST_HP + 1), m_effortValue(ST_SpecialDefense - ST_HP + 1) { *this = species; } Sigmod::Species::Species(const QDomElement& xml, const Sigmod* parent, const int id) : Object(parent, id), m_baseStat(ST_SpecialDefense - ST_HP + 1), m_effortValue(ST_SpecialDefense - ST_HP + 1) { LOAD_ID(); load(xml); } Sigmod::Species::~Species() { clear(); } void Sigmod::Species::validate() { TEST_BEGIN(); if (m_name.isEmpty()) emit(error("Name is empty")); TEST_ARRAY_INDEX(baseStat, ST_HP); TEST_ARRAY_INDEX(baseStat, ST_Attack); TEST_ARRAY_INDEX(baseStat, ST_Defense); TEST_ARRAY_INDEX(baseStat, ST_Speed); if (sigmod()->rules()->specialSplit()) { TEST_ARRAY_INDEX(baseStat, ST_SpecialAttack); TEST_ARRAY_INDEX(baseStat, ST_SpecialDefense); } else TEST_ARRAY_INDEX(baseStat, ST_Special); TEST_ARRAY_INDEX(effortValue, ST_HP); TEST_ARRAY_INDEX(effortValue, ST_Attack); TEST_ARRAY_INDEX(effortValue, ST_Defense); TEST_ARRAY_INDEX(effortValue, ST_Speed); if (sigmod()->rules()->specialSplit()) { TEST_ARRAY_INDEX(effortValue, ST_SpecialAttack); TEST_ARRAY_INDEX(effortValue, ST_SpecialDefense); } else TEST_ARRAY_INDEX(effortValue, ST_Special); TEST(growth); TEST(experienceValue); TEST(maxHoldWeight); TEST(runChance); TEST(fleeChance); TEST(itemChance); TEST(encyclopediaNumber); TEST(weight); TEST(frontMaleSprite); TEST(backMaleSprite); TEST(frontFemaleSprite); TEST(backFemaleSprite); TEST(skin); if ((m_encyclopediaNumber != -1) && m_encyclopediaEntry.isEmpty()) emit(error("Encyclopedia entry is empty")); TEST(genderFactor); if (sigmod()->rules()->breedingAllowed()) { const Species* eggSpecies = sigmod()->speciesById(m_eggSpecies); if (!eggSpecies) emit(error(bounds("egg species", m_eggSpecies))); else { if (eggSpecies->growth() != m_growth) emit(error("Growth mismatch with egg species")); TEST(eggSteps); } } TEST_LIST(type); TEST_LIST(eggGroup); QSet idChecker; QSet valueChecker; if (abilityCount() < sigmod()->rules()->maxAbilities()) emit(warning("There are too few abilities")); TEST_SUB_BEGIN(SpeciesAbility, abilities); TEST_SUB("ability", id); TEST_SUB_RAW(value, "ability", ability); TEST_SUB_END(); idChecker.clear(); valueChecker.clear(); if (sigmod()->rules()->maxHeldItems() && !itemCount()) emit(warning("There are no items")); TEST_SUB_BEGIN(SpeciesItem, items); TEST_SUB("item", id); TEST_SUB_RAW(value, "item", item); TEST_SUB_END(); idChecker.clear(); valueChecker.clear(); if (!moveCount()) emit(error("There are no moves")); TEST_SUB_BEGIN(SpeciesMove, moves); TEST_SUB("move", id); TEST_SUB_RAW(value, "move", move); TEST_SUB_END(); TEST_END(); } void Sigmod::Species::load(const QDomElement& xml) { LOAD_BEGIN(); LOAD(name); LOAD_ARRAY(baseStat); LOAD_ARRAY(effortValue); LOAD(growth); LOAD(experienceValue); LOAD(catchValue); LOAD(maxHoldWeight); LOAD(runChance); LOAD(fleeChance); LOAD(itemChance); LOAD(encyclopediaNumber); LOAD(weight); LOAD(height); LOAD(frontMaleSprite); LOAD(backMaleSprite); LOAD(frontFemaleSprite); LOAD(backFemaleSprite); LOAD(skin); LOAD(encyclopediaEntry); LOAD(genderFactor); LOAD(eggSpecies); LOAD(eggSteps); LOAD_LIST(type); LOAD_LIST(eggGroup); LOAD(evolution); LOAD_SUB(newAbility, SpeciesAbility); LOAD_SUB(newItem, SpeciesItem); LOAD_SUB(newMove, SpeciesMove); } QDomElement Sigmod::Species::save() const { SAVE_CREATE(); SAVE(name); SAVE_ARRAY(baseStat); SAVE_ARRAY(effortValue); SAVE(growth); SAVE(experienceValue); SAVE(catchValue); SAVE(maxHoldWeight); SAVE(runChance); SAVE(fleeChance); SAVE(itemChance); SAVE(encyclopediaNumber); SAVE(weight); SAVE(height); SAVE(frontMaleSprite); SAVE(backMaleSprite); SAVE(frontFemaleSprite); SAVE(backFemaleSprite); SAVE(skin); SAVE(encyclopediaEntry); SAVE(genderFactor); SAVE(eggSpecies); SAVE(eggSteps); SAVE_LIST(type); SAVE_LIST(eggGroup); SAVE(evolution); SAVE_SUB(SpeciesAbility, abilities); SAVE_SUB(SpeciesItem, items); SAVE_SUB(SpeciesMove, moves); return xml; } SETTER(Species, QString&, Name, name) SETTER_ARRAY(Species, int, BaseStat, baseStat, baseStat, Stat, stat, ST_HP) SETTER_ARRAY(Species, int, EffortValue, effortValue, effortValue, Stat, stat, ST_HP) SETTER(Species, Style, Growth, growth) SETTER(Species, int, ExperienceValue, experienceValue) SETTER(Species, int, CatchValue, catchValue) SETTER(Species, int, MaxHoldWeight, maxHoldWeight) SETTER(Species, Sigcore::Fraction&, RunChance, runChance) SETTER(Species, Sigcore::Fraction&, FleeChance, fleeChance) SETTER(Species, Sigcore::Fraction&, ItemChance, itemChance) SETTER(Species, int, EncyclopediaNumber, encyclopediaNumber) SETTER(Species, int, Weight, weight) SETTER(Species, int, Height, height) SETTER(Species, int, FrontMaleSprite, frontMaleSprite) SETTER(Species, int, BackMaleSprite, backMaleSprite) SETTER(Species, int, FrontFemaleSprite, frontFemaleSprite) SETTER(Species, int, BackFemaleSprite, backFemaleSprite) SETTER(Species, int, Skin, skin) SETTER(Species, QString&, EncyclopediaEntry, encyclopediaEntry) SETTER(Species, Sigcore::Fraction&, GenderFactor, genderFactor) SETTER(Species, int, EggSpecies, eggSpecies) SETTER(Species, int, EggSteps, eggSteps) SETTER_LIST(Species, Type, type) SETTER_LIST(Species, EggGroup, eggGroup) SETTER(Species, Sigcore::Script&, Evolution, evolution) GETTER(Species, QString, name) GETTER_ARRAY(Species, int, baseStat, baseStat, Stat, stat, ST_HP) GETTER_ARRAY(Species, int, effortValue, effortValue, Stat, stat, ST_HP) GETTER(Species, Sigmod::Species::Style, growth) GETTER(Species, int, experienceValue) GETTER(Species, int, catchValue) GETTER(Species, int, maxHoldWeight) GETTER(Species, Sigcore::Fraction, runChance) GETTER(Species, Sigcore::Fraction, fleeChance) GETTER(Species, Sigcore::Fraction, itemChance) GETTER(Species, int, encyclopediaNumber) GETTER(Species, int, weight) GETTER(Species, int, height) GETTER(Species, int, frontMaleSprite) GETTER(Species, int, backMaleSprite) GETTER(Species, int, frontFemaleSprite) GETTER(Species, int, backFemaleSprite) GETTER(Species, int, skin) GETTER(Species, QString, encyclopediaEntry) GETTER(Species, Sigcore::Fraction, genderFactor) GETTER(Species, int, eggSpecies) GETTER(Species, int, eggSteps) GETTER_LIST(Species, type) GETTER_LIST(Species, eggGroup) GETTER(Species, Sigcore::Script, evolution) CHECK(Species, QString&, name) CHECK_BEGIN_ARRAY(Species, int, baseStat, baseStat, Stat, stat) switch (stat) { case ST_SpecialDefense: if (sigmod()->rules()->specialSplit()) case ST_HP ... ST_Special: break; default: EBOUNDS(stat, "HP", sigmod()->rules()->specialSplit() ? "SpecialDefense" : "Special"); return false; } TBOUNDS(baseStat, 1, INT_MAX) CHECK_END() CHECK_BEGIN_ARRAY(Species, int, effortValue, effortValue, Stat, stat) switch (stat) { case ST_SpecialDefense: if (sigmod()->rules()->specialSplit()) case ST_HP ... ST_Special: break; default: EBOUNDS(stat, "HP", sigmod()->rules()->specialSplit() ? "SpecialDefense" : "Special"); return false; } TBOUNDS(effortValue, 0, sigmod()->rules()->maxEVPerStat() ? sigmod()->rules()->maxEVPerStat() : INT_MAX) CHECK_END() CHECK(Species, Style, growth) CHECK_BOUNDS(Species, int, experienceValue, 0, INT_MAX) CHECK_BOUNDS(Species, int, catchValue, 1, 255) CHECK_BOUNDS(Species, int, maxHoldWeight, 0, INT_MAX) CHECK_BOUNDS(Species, Sigcore::Fraction&, runChance, 0, 1) CHECK_BOUNDS(Species, Sigcore::Fraction&, fleeChance, 0, 1) CHECK_BOUNDS(Species, Sigcore::Fraction&, itemChance, 0, 1) CHECK_BOUNDS(Species, int, encyclopediaNumber, -1, INT_MAX) CHECK_BOUNDS(Species, int, weight, 0, INT_MAX) CHECK_BOUNDS(Species, int, height, 0, INT_MAX) CHECK_BEGIN(Species, int, frontMaleSprite) if (m_genderFactor < 1) IBOUNDS(frontMaleSprite, sigmod(), sprite); CHECK_END() CHECK_BEGIN(Species, int, backMaleSprite) if (m_genderFactor < 1) IBOUNDS(backMaleSprite, sigmod(), sprite); CHECK_END() CHECK_BEGIN(Species, int, frontFemaleSprite) if (0 < m_genderFactor) IBOUNDS(frontFemaleSprite, sigmod(), sprite); CHECK_END() CHECK_BEGIN(Species, int, backFemaleSprite) if (0 < m_genderFactor) IBOUNDS(backFemaleSprite, sigmod(), sprite); CHECK_END() CHECK_INDEX(Species, int, skin, sigmod(), skin) CHECK(Species, QString&, encyclopediaEntry) CHECK_BOUNDS(Species, Sigcore::Fraction&, genderFactor, -1, 1) CHECK_INDEX(Species, int, eggSpecies, sigmod(), species) CHECK_BOUNDS(Species, int, eggSteps, 1, INT_MAX) CHECK_INDEX(Species, int, type, sigmod(), type) CHECK_INDEX(Species, int, eggGroup, sigmod(), eggGroup) CHECK(Species, Sigcore::Script&, evolution) SUBCLASS(Species, Ability, ability, abilities) SUBCLASS(Species, Item, item, items) SUBCLASS(Species, Move, move, moves) Sigmod::Species& Sigmod::Species::operator=(const Species& rhs) { if (this == &rhs) return *this; clear(); COPY(name); COPY(baseStat); COPY(effortValue); COPY(growth); COPY(experienceValue); COPY(catchValue); COPY(maxHoldWeight); COPY(runChance); COPY(fleeChance); COPY(itemChance); COPY(encyclopediaNumber); COPY(weight); COPY(height); COPY(frontMaleSprite); COPY(backMaleSprite); COPY(frontFemaleSprite); COPY(backFemaleSprite); COPY(skin); COPY(encyclopediaEntry); COPY(genderFactor); COPY(eggSpecies); COPY(eggSteps); COPY(type); COPY(eggGroup); COPY(evolution); COPY_SUB(SpeciesAbility, abilities); COPY_SUB(SpeciesItem, items); COPY_SUB(SpeciesMove, moves); return *this; } void Sigmod::Species::clear() { SUBCLASS_CLEAR(abilities); SUBCLASS_CLEAR(items); SUBCLASS_CLEAR(moves); }