1 // ============================================================== 2 // This file is part of Glest (www.glest.org) 3 // 4 // Copyright (C) 2001-2008 Martiño Figueroa 5 // 6 // You can redistribute this code and/or modify it under 7 // the terms of the GNU General Public License as published 8 // by the Free Software Foundation; either version 2 of the 9 // License, or (at your option) any later version 10 // ============================================================== 11 12 /** 13 * @file 14 * Classified the Upgrade type (which is sort of like a class for upgrades). Each upgrade has a 15 * type that details the stats that it boosts and the units that it affects. Also has TotalUpgrade, 16 * which is a sum of all upgrades applied to a particular unit (and is what determines how units 17 * stats are modified by an upgrade. 18 */ 19 20 #ifndef _GLEST_GAME_UPGRADETYPE_H_ 21 #define _GLEST_GAME_UPGRADETYPE_H_ 22 23 #ifdef WIN32 24 #include <winsock2.h> 25 #include <winsock.h> 26 #endif 27 28 #include "element_type.h" 29 #include "checksum.h" 30 #include "conversion.h" 31 #include "xml_parser.h" 32 #include "leak_dumper.h" 33 #include <set> 34 35 using Shared::Util::Checksum; 36 using namespace Shared::Util; 37 using namespace Shared::Xml; 38 39 namespace Glest { namespace Game { 40 41 class TechTree; 42 class FactionType; 43 class UnitType; 44 class Unit; 45 class SkillType; 46 class AttackSkillType; 47 class MoveSkillType; 48 class ProduceSkillType; 49 class Faction; 50 51 /** 52 * Groups all information used for upgrades. Attack boosts also use this class for modifying stats. 53 */ 54 class UpgradeTypeBase { 55 protected: 56 string upgradename; 57 int maxHp; 58 bool maxHpIsMultiplier; 59 int maxHpRegeneration; 60 //bool maxHpRegenerationIsMultiplier; 61 62 int sight; 63 bool sightIsMultiplier; 64 65 int maxEp; 66 bool maxEpIsMultiplier; 67 int maxEpRegeneration; 68 //bool maxEpRegenerationIsMultiplier; 69 70 int armor; 71 bool armorIsMultiplier; 72 73 int attackStrength; 74 bool attackStrengthIsMultiplier; 75 /** 76 * List of the values (for each skill type) that the stat was boosted by. This is used so 77 * that we can restore the original values when the upgrade is removed (eg, an attack 78 * boost wears off). 79 */ 80 std::map<string,int> attackStrengthMultiplierValueList; 81 82 int attackRange; 83 bool attackRangeIsMultiplier; 84 std::map<string,int> attackRangeMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */ 85 86 int moveSpeed; 87 bool moveSpeedIsMultiplier; 88 std::map<string,int> moveSpeedIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */ 89 90 int prodSpeed; 91 bool prodSpeedIsMultiplier; 92 std::map<string,int> prodSpeedProduceIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */ 93 std::map<string,int> prodSpeedUpgradeIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */ 94 std::map<string,int> prodSpeedMorphIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */ 95 96 int attackSpeed; 97 bool attackSpeedIsMultiplier; 98 std::map<string,int> attackSpeedIsMultiplierValueList; 99 100 protected: 101 getAttackStrength()102 virtual int getAttackStrength() const { return attackStrength; } getAttackRange()103 virtual int getAttackRange() const { return attackRange; } getMoveSpeed()104 virtual int getMoveSpeed() const { return moveSpeed; } getProdSpeed()105 virtual int getProdSpeed() const { return prodSpeed; } getAttackSpeed()106 virtual int getAttackSpeed() const { return attackSpeed; } 107 getMaxHpFromBoosts()108 virtual int getMaxHpFromBoosts() const { return 0; } getMaxHpRegenerationFromBoosts()109 virtual int getMaxHpRegenerationFromBoosts() const { return 0; } getSightFromBoosts()110 virtual int getSightFromBoosts() const { return 0; } getMaxEpFromBoosts()111 virtual int getMaxEpFromBoosts() const { return 0; } getMaxEpRegenerationFromBoosts()112 virtual int getMaxEpRegenerationFromBoosts() const { return 0; } getArmorFromBoosts()113 virtual int getArmorFromBoosts() const { return 0; }; getAttackStrengthFromBoosts(const AttackSkillType * st)114 virtual int getAttackStrengthFromBoosts(const AttackSkillType *st) const { return 0; } getAttackRangeFromBoosts(const AttackSkillType * st)115 virtual int getAttackRangeFromBoosts(const AttackSkillType *st) const { return 0; } getMoveSpeedFromBoosts(const MoveSkillType * st)116 virtual int getMoveSpeedFromBoosts(const MoveSkillType *st) const { return 0; } getProdSpeedFromBoosts(const SkillType * st)117 virtual int getProdSpeedFromBoosts(const SkillType *st) const { return 0; } getAttackSpeedFromBoosts(const AttackSkillType * st)118 virtual int getAttackSpeedFromBoosts(const AttackSkillType *st) const { return 0; } 119 120 public: 121 /** 122 * Creates an UpgradeTypeBase with values such that there are no stat changes. 123 */ UpgradeTypeBase()124 UpgradeTypeBase() { 125 maxHp = 0;; 126 maxHpIsMultiplier = false; 127 maxHpRegeneration = 0; 128 sight = 0; 129 sightIsMultiplier = false; 130 maxEp = 0;; 131 maxEpIsMultiplier = false; 132 maxEpRegeneration = 0; 133 armor = 0; 134 armorIsMultiplier = false; 135 attackStrength = 0; 136 attackStrengthIsMultiplier = false; 137 attackRange = 0; 138 attackRangeIsMultiplier = false; 139 moveSpeed = 0; 140 moveSpeedIsMultiplier = false; 141 prodSpeed = 0; 142 prodSpeedIsMultiplier = false; 143 attackSpeed = 0; 144 attackSpeedIsMultiplier = false; 145 } ~UpgradeTypeBase()146 virtual ~UpgradeTypeBase() {} 147 148 virtual void copyDataFrom(UpgradeTypeBase *source); 149 getUpgradeName()150 virtual string getUpgradeName() const { return upgradename; } getMaxHp()151 virtual int getMaxHp() const {return maxHp;} getMaxHpRegeneration()152 virtual int getMaxHpRegeneration() const {return maxHpRegeneration;} getSight()153 virtual int getSight() const {return sight;} getMaxEp()154 virtual int getMaxEp() const {return maxEp;} getMaxEpRegeneration()155 virtual int getMaxEpRegeneration() const {return maxEpRegeneration;} getArmor()156 virtual int getArmor() const {return armor;} 157 virtual int getAttackStrength(const AttackSkillType *st) const; 158 virtual int getAttackRange(const AttackSkillType *st) const; 159 virtual int getMoveSpeed(const MoveSkillType *st) const; 160 virtual int getProdSpeed(const SkillType *st) const; 161 virtual int getAttackSpeed(const AttackSkillType *st) const; 162 getAttackStrengthIsMultiplier()163 virtual bool getAttackStrengthIsMultiplier() const {return attackStrengthIsMultiplier;} getMaxHpIsMultiplier()164 virtual bool getMaxHpIsMultiplier() const {return maxHpIsMultiplier;} getSightIsMultiplier()165 virtual bool getSightIsMultiplier() const {return sightIsMultiplier;} getMaxEpIsMultiplier()166 virtual bool getMaxEpIsMultiplier() const {return maxEpIsMultiplier;} getArmorIsMultiplier()167 virtual bool getArmorIsMultiplier() const {return armorIsMultiplier;} getAttackRangeIsMultiplier()168 virtual bool getAttackRangeIsMultiplier() const {return attackRangeIsMultiplier;} getMoveSpeedIsMultiplier()169 virtual bool getMoveSpeedIsMultiplier() const {return moveSpeedIsMultiplier;} getProdSpeedIsMultiplier()170 virtual bool getProdSpeedIsMultiplier() const {return prodSpeedIsMultiplier;} getAttackSpeedIsMultiplier()171 virtual bool getAttackSpeedIsMultiplier() const {return attackSpeedIsMultiplier;} 172 173 /** 174 * Loads the upgrade values (stat boosts and whether or not the boosts use a multiplier) from an 175 * XML node. 176 * @param upgradeNode Node containing the stat boost elements (`max-hp`, `attack-strength`, etc). 177 * @param upgradename Unique identifier for the upgrade. 178 */ 179 180 virtual void load(const XmlNode *upgradeNode, string upgradename); 181 182 /** 183 * Creates a string representation of the upgrade. All stat boosts are detailed on their own line 184 * with their corresponding boosts. 185 * @param translatedValue If true, the description is translated. Otherwise the description uses 186 * names as they appear in the XMLs. 187 */ 188 virtual string getDesc(bool translatedValue) const; 189 190 /** 191 * Returns a string representation of this object. Lists all the value that the object stores. 192 * For debugging purposes, only. 193 */ toString()194 virtual std::string toString() const { 195 std::string result = ""; 196 197 result += "upgradename =" + getUpgradeName(); 198 result += "maxHp = " + intToStr(getMaxHp()); 199 result += "maxHpIsMultiplier = " + intToStr(getMaxHpIsMultiplier()); 200 result += "maxHpRegeneration = " + intToStr(getMaxHpRegeneration()); 201 //result += "maxHpRegenerationIsMultiplier = " + intToStr(maxHpRegenerationIsMultiplier); 202 203 result += " sight = " + intToStr(getSight()); 204 result += "sightIsMultiplier = " + intToStr(getSightIsMultiplier()); 205 206 result += " maxEp = " + intToStr(getMaxEp()); 207 result += " maxEpIsMultiplier = " + intToStr(getMaxEpIsMultiplier()); 208 result += " maxEpRegeneration = " + intToStr(getMaxEpRegeneration()); 209 //result += "maxEpRegenerationIsMultiplier = " + intToStr(maxEpRegenerationIsMultiplier); 210 211 result += " armor = " + intToStr(getArmor()); 212 result += " armorIsMultiplier = " + intToStr(getArmorIsMultiplier()); 213 result += " attackStrength = " + intToStr(getAttackStrength()); 214 result += " attackStrengthIsMultiplier = " + intToStr(getAttackStrengthIsMultiplier()); 215 result += " attackRange = " + intToStr(getAttackRange()); 216 result += " attackRangeIsMultiplier = " + intToStr(getAttackRangeIsMultiplier()); 217 result += " moveSpeed = " + intToStr(getMoveSpeed()); 218 result += " moveSpeedIsMultiplier = " + intToStr(getMoveSpeedIsMultiplier()); 219 result += " prodSpeed = " + intToStr(getProdSpeed()); 220 result += " prodSpeedIsMultiplier = " + intToStr(getProdSpeedIsMultiplier()); 221 222 return result; 223 } 224 225 // TODO: It's not clear if these save game methods are being used, currently. I think 226 // attack boosts might use the few lines that aren't commented out. 227 virtual void saveGame(XmlNode *rootNode) const; 228 virtual void saveGameBoost(XmlNode *rootNode) const; 229 static const UpgradeType * loadGame(const XmlNode *rootNode, Faction *faction); 230 void loadGameBoost(const XmlNode *rootNode); 231 232 /** 233 * Generates a checksum value for the upgrade. 234 */ getCRC()235 virtual Checksum getCRC() { 236 Checksum crcForUpgradeType; 237 238 crcForUpgradeType.addString(getUpgradeName()); 239 crcForUpgradeType.addInt(getMaxHp()); 240 crcForUpgradeType.addInt(getMaxHpIsMultiplier()); 241 crcForUpgradeType.addInt(getMaxHpRegeneration()); 242 243 crcForUpgradeType.addInt(getSight()); 244 crcForUpgradeType.addInt(getSightIsMultiplier()); 245 246 crcForUpgradeType.addInt(getMaxEp()); 247 crcForUpgradeType.addInt(getMaxEpIsMultiplier()); 248 crcForUpgradeType.addInt(getMaxEpRegeneration()); 249 250 crcForUpgradeType.addInt(getArmor()); 251 crcForUpgradeType.addInt(getArmorIsMultiplier()); 252 253 crcForUpgradeType.addInt(getAttackStrength()); 254 crcForUpgradeType.addInt(getAttackStrengthIsMultiplier()); 255 //std::map<string,int> attackStrengthMultiplierValueList; 256 crcForUpgradeType.addInt64((int64)attackStrengthMultiplierValueList.size()); 257 258 crcForUpgradeType.addInt(getAttackRange()); 259 crcForUpgradeType.addInt(getAttackRangeIsMultiplier()); 260 //std::map<string,int> attackRangeMultiplierValueList; 261 crcForUpgradeType.addInt64((int64)attackRangeMultiplierValueList.size()); 262 263 crcForUpgradeType.addInt(getMoveSpeed()); 264 crcForUpgradeType.addInt(getMoveSpeedIsMultiplier()); 265 //std::map<string,int> moveSpeedIsMultiplierValueList; 266 crcForUpgradeType.addInt64((int64)moveSpeedIsMultiplierValueList.size()); 267 268 crcForUpgradeType.addInt(getProdSpeed()); 269 crcForUpgradeType.addInt(getProdSpeedIsMultiplier()); 270 //std::map<string,int> prodSpeedProduceIsMultiplierValueList; 271 crcForUpgradeType.addInt64((int64)prodSpeedProduceIsMultiplierValueList.size()); 272 //std::map<string,int> prodSpeedUpgradeIsMultiplierValueList; 273 crcForUpgradeType.addInt64((int64)prodSpeedUpgradeIsMultiplierValueList.size()); 274 //std::map<string,int> prodSpeedMorphIsMultiplierValueList; 275 crcForUpgradeType.addInt64((int64)prodSpeedMorphIsMultiplierValueList.size()); 276 277 crcForUpgradeType.addInt(getAttackSpeed()); 278 crcForUpgradeType.addInt(getAttackSpeedIsMultiplier()); 279 280 return crcForUpgradeType; 281 } 282 }; 283 284 /** 285 * Represents the type of upgrade. That is, the single upgrade as it appears in the faction's XML 286 * files. Each upgrade has a single `UpgradeType`. Contains information about what units are 287 * affected by the upgrade. 288 */ 289 class UpgradeType: public UpgradeTypeBase, public ProducibleType { 290 private: 291 /** 292 * Set of unit types (the "classes" of units, eg, swordman) that are affected by this upgrade. 293 */ 294 std::set<const UnitType*> effects; 295 std::set<string> tags; 296 297 public: 298 /** 299 * Sets the upgrade name to the directory name (the base name of `dir`). 300 * @param dir Path of the upgrade directory. 301 */ 302 void preLoad(const string &dir); 303 304 /** 305 * Loads an upgrade from an XML file. 306 * @param dir Path of the upgrade directory. The file name is determined from this. 307 * @param techTree The techtree that this upgrade is in. Used to access the common data 308 * directory and to access resources. 309 * @param factionType The faction type (a unique type for each faction) that the upgrade belongs 310 * to. Used for accessing unit types that are in the unit requirements list. 311 * @param checksum Will have the checksum of the upgrade path added to it (treated the same way 312 * as the `techtreeChecksum`). 313 * @param techtreeChecksum Cumulative checksum for the techtree. The path of loaded upgrades 314 * is added to this checksum. 315 */ 316 void load(const string &dir, const TechTree *techTree, 317 const FactionType *factionType, Checksum* checksum, 318 Checksum* techtreeChecksum, 319 std::map<string,vector<pair<string, string> > > &loadedFileList, 320 bool validationMode=false); 321 322 /** 323 * Obtains the upgrade name. 324 * @param translatedValue If true, the name is translated. Otherwise the name is returned as it 325 * appears in the XMLs. 326 */ 327 virtual string getName(bool translatedValue=false) const; 328 string getTagName(string tag, bool translatedValue=false) const; 329 330 /** 331 * Determines if a unit is affected by this upgrade. 332 * @param unitType The UnitType we are checking (to see if they're affected). 333 * @return True if the unit is affected, false otherwise. 334 */ 335 bool isAffected(const UnitType *unitType) const; 336 337 /** 338 * Creates a description for this upgrade. Lists the affected units. 339 */ 340 virtual string getReqDesc(bool translatedValue) const; 341 342 //virtual void saveGame(XmlNode *rootNode) const; 343 //virtual void loadGame(const XmlNode *rootNode); 344 }; 345 346 /** 347 * Keeps track of the cumulative effects of upgrades on units. This allows us to apply multiple 348 * upgrades to a unit with the effects stacking. 349 */ 350 class TotalUpgrade: public UpgradeTypeBase { 351 352 private: 353 354 // List of boosts 355 const UpgradeTypeBase *boostUpgradeBase; 356 int boostUpgradeSourceUnit; 357 int boostUpgradeDestUnit; 358 std::vector<TotalUpgrade *> boostUpgrades; 359 360 public: 361 TotalUpgrade(); ~TotalUpgrade()362 virtual ~TotalUpgrade() {} 363 364 /** 365 * Resets all stat boosts (so there's effectively no upgrade). 366 */ 367 void reset(); 368 369 /** 370 * Adds an upgrade to this one, stacking the effects. Note that multipliers are stacked 371 * by multiplying by the original, unboosted amount, and then adding that to the TotalUpgrade. 372 * @param ut The upgrade to apply. 373 * @param unit The unit this TotalUpgrade is associated with (since when we use a multiplier, 374 * the stats raise by an amount relative to the unit's base stats). 375 */ 376 void sum(const UpgradeTypeBase *ut, const Unit *unit, bool boostMode=false); 377 378 /** 379 * Increases the level of the unit. Doing so results in their HP, EP, and armour going up by 380 * 50% while their sight goes up by 20%. 381 * @param ut The unit type to get the original stats from (so we can determine just how much 382 * to increase the stats by on level up). 383 */ 384 void incLevel(const UnitType *ut); 385 386 /** 387 * Applies the upgrade. Just a delegate to TotalUpgrade::sum. 388 */ 389 void apply(int sourceUnitId, const UpgradeTypeBase *ut, const Unit *unit); 390 391 /** 392 * Removes the effect of an upgrade to a specific unit. Using this after applying the upgrade 393 * is an invariant. ie, 394 * 395 * totalUpgrade->apply(upgrade, unit); 396 * totalUpgrade->deapply(upgrade, unit); 397 * // totalUpgrade is now the same as before the call to apply() 398 * 399 * @param ut The upgrade to remove. 400 * @param unit The unit this TotalUpgrade is associated with (since when we use a multiplier, 401 * the stats were raise by an amount relative to the unit's base stats). 402 */ 403 void deapply(int sourceUnitId, const UpgradeTypeBase *ut,int destUnitId); 404 405 virtual int getMaxHp() const; 406 virtual int getMaxHpRegeneration() const; 407 virtual int getSight() const; 408 virtual int getMaxEp() const; 409 virtual int getMaxEpRegeneration() const; 410 virtual int getArmor() const; 411 virtual int getAttackStrength(const AttackSkillType *st) const; 412 virtual int getAttackRange(const AttackSkillType *st) const; 413 virtual int getMoveSpeed(const MoveSkillType *st) const; 414 virtual int getProdSpeed(const SkillType *st) const; 415 virtual int getAttackSpeed(const AttackSkillType *st) const; 416 417 virtual int getMaxHpFromBoosts() const; 418 virtual int getMaxHpRegenerationFromBoosts() const; 419 virtual int getSightFromBoosts() const; 420 virtual int getMaxEpFromBoosts() const; 421 virtual int getMaxEpRegenerationFromBoosts() const; 422 virtual int getArmorFromBoosts() const; 423 virtual int getAttackStrengthFromBoosts(const AttackSkillType *st) const; 424 virtual int getAttackRangeFromBoosts(const AttackSkillType *st) const; 425 virtual int getMoveSpeedFromBoosts(const MoveSkillType *st) const; 426 virtual int getProdSpeedFromBoosts(const SkillType *st) const; 427 virtual int getAttackSpeedFromBoosts(const AttackSkillType *st) const; 428 429 /** 430 * Creates the XML for the save game file. Essentially just stores everything about its state. 431 * @rootNode The node of the unit that this TotalUpgrade object belongs to. 432 */ 433 void saveGame(XmlNode *rootNode) const; 434 435 /** 436 * Reloads the object's state from a saved game. 437 * @rootNode The node of the unit that this TotalUpgrade object belongs to. 438 */ 439 void loadGame(const XmlNode *rootNode); 440 }; 441 442 }}//end namespace 443 444 #endif 445