diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index 09f8a2fc..59d776c2 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -2630,7 +2630,15 @@ bool Unit::update() { int64 heightFactor = getHeightFactor(ANIMATION_SPEED_MULTIPLIER); int64 speedDenominator = speedDivider * game->getWorld()->getUpdateFps(this->getFactionIndex()); - int64 progressIncrease = (currSkill->getAnimSpeed() * heightFactor) / speedDenominator; + + // Override the animation speed for attacks that have upgraded the attack speed + int animSpeed = currSkill->getAnimSpeed(); + if(currSkill->getClass() == scAttack) { + int animSpeedBoost = ((AttackSkillType *) currSkill)->getAnimSpeedBoost(&totalUpgrade); + animSpeed += animSpeedBoost; + } + + int64 progressIncrease = (animSpeed * heightFactor) / speedDenominator; // Ensure we increment at least a value of 1 of the action will be stuck infinitely if(currSkill->getAnimSpeed() > 0 && heightFactor > 0 && progressIncrease == 0) { progressIncrease = 1; diff --git a/source/glest_game/types/command_type.cpp b/source/glest_game/types/command_type.cpp index 6e775622..7c3e2b6a 100644 --- a/source/glest_game/types/command_type.cpp +++ b/source/glest_game/types/command_type.cpp @@ -288,7 +288,13 @@ string AttackCommandType::getDesc(const TotalUpgrade *totalUpgrade, bool transla } str+="\n"; + //attack speed str+= lang.getString("AttackSpeed",(translatedValue == true ? "" : "english"))+": "+ intToStr(attackSkillType->getSpeed()) +"\n"; + if(totalUpgrade->getAttackSpeed(attackSkillType) != 0) { + str+= "+"+intToStr(totalUpgrade->getAttackSpeed(attackSkillType)); + } + str+="\n"; + str+=attackSkillType->getBoostDesc(translatedValue); return str; } diff --git a/source/glest_game/types/skill_type.cpp b/source/glest_game/types/skill_type.cpp index 5f53b1c5..006b707f 100644 --- a/source/glest_game/types/skill_type.cpp +++ b/source/glest_game/types/skill_type.cpp @@ -1013,6 +1013,24 @@ void AttackSkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode, } } +int AttackSkillType::getTotalSpeed(const TotalUpgrade *totalUpgrade) const{ + int result = speed + totalUpgrade->getAttackSpeed(this); + result = max(0,result); + return result; +} + +// Get the amount to boost the attack animation speed by (based on attack-speed upgrades) +int AttackSkillType::getAnimSpeedBoost(const TotalUpgrade *totalUpgrade) const{ + // Same calculation as in TotalUpgrade::sum, but bypassing the use of the value + // list (which is for the attack speed, not animation speed) + if(totalUpgrade->getAttackRangeIsMultiplier()) { + return animSpeed * (totalUpgrade->getAttackSpeed(NULL) / (double)100); + } + else { + return totalUpgrade->getAttackSpeed(NULL); + } +} + string AttackSkillType::toString(bool translatedValue) const{ if(translatedValue == false) { return "Attack"; diff --git a/source/glest_game/types/skill_type.h b/source/glest_game/types/skill_type.h index c0b4f3b8..15f32360 100644 --- a/source/glest_game/types/skill_type.h +++ b/source/glest_game/types/skill_type.h @@ -334,6 +334,8 @@ public: //misc int getTotalAttackStrength(const TotalUpgrade *totalUpgrade) const; int getTotalAttackRange(const TotalUpgrade *totalUpgrade) const; + virtual int getTotalSpeed(const TotalUpgrade *totalUpgrade) const; + virtual int getAnimSpeedBoost(const TotalUpgrade *totalUpgrade) const; virtual void saveGame(XmlNode *rootNode); }; diff --git a/source/glest_game/types/upgrade_type.cpp b/source/glest_game/types/upgrade_type.cpp index 812f247d..b47a97ce 100644 --- a/source/glest_game/types/upgrade_type.cpp +++ b/source/glest_game/types/upgrade_type.cpp @@ -169,6 +169,19 @@ void UpgradeTypeBase::load(const XmlNode *upgradeNode, string upgradename) { else { prodSpeed = 0; } + + attackSpeedIsMultiplier = false; + if(upgradeNode->hasChild("attack-speed") == true) { + attackSpeed= upgradeNode->getChild("attack-speed")->getAttribute("value")->getIntValue(); + if(upgradeNode->getChild("attack-speed")->getAttribute(VALUE_PERCENT_MULTIPLIER_KEY_NAME,false) != NULL) { + attackSpeedIsMultiplier = upgradeNode->getChild("attack-speed")->getAttribute(VALUE_PERCENT_MULTIPLIER_KEY_NAME)->getBoolValue(); + + //printf("Found prodSpeedIsMultiplier = %d\n",prodSpeedIsMultiplier); + } + } + else { + attackSpeed = 0; + } } int UpgradeTypeBase::getAttackStrength(const AttackSkillType *st) const { @@ -212,6 +225,20 @@ int UpgradeTypeBase::getMoveSpeed(const MoveSkillType *st) const { } } +int UpgradeTypeBase::getAttackSpeed(const AttackSkillType *st) const { + if(attackSpeedIsMultiplier == false || st == NULL) { + return attackSpeed; + } + else { + int result = 0; + if(attackSpeedIsMultiplierValueList.find(st->getName()) != attackSpeedIsMultiplierValueList.end()) { + result = attackSpeedIsMultiplierValueList.find(st->getName())->second; + } + + return result; + } +} + int UpgradeTypeBase::getProdSpeed(const SkillType *st) const { if(prodSpeedIsMultiplier == false || st == NULL) { return prodSpeed; @@ -347,6 +374,18 @@ string UpgradeTypeBase::getDesc(bool translatedValue) const{ str+= indent+lang.getString("ProductionSpeed",(translatedValue == true ? "" : "english")) + " +" + intToStr(prodSpeed); } } + if(attackSpeed != 0) { + if(str != "") { + str += "\n"; + } + + if(attackSpeedIsMultiplier) { + str+= indent+lang.getString("AttackSpeed",(translatedValue == true ? "" : "english")) + " *" + intToStr(moveSpeed); + } + else { + str+= indent+lang.getString("AttackSpeed",(translatedValue == true ? "" : "english")) + " +" + intToStr(moveSpeed); + } + } if(str != "") { str += "\n"; } @@ -821,6 +860,9 @@ void TotalUpgrade::reset() { prodSpeed=0; prodSpeedIsMultiplier=false; + + attackSpeed=0; + attackSpeedIsMultiplier=false; } void TotalUpgrade::sum(const UpgradeTypeBase *ut, const Unit *unit) { @@ -832,6 +874,7 @@ void TotalUpgrade::sum(const UpgradeTypeBase *ut, const Unit *unit) { attackRangeIsMultiplier = ut->getAttackRangeIsMultiplier(); moveSpeedIsMultiplier = ut->getMoveSpeedIsMultiplier(); prodSpeedIsMultiplier = ut->getProdSpeedIsMultiplier(); + attackSpeedIsMultiplier = ut->getAttackSpeedIsMultiplier(); if(ut->getMaxHpIsMultiplier() == true) { //printf("#1 Maxhp maxHp = %d, unit->getHp() = %d ut->getMaxHp() = %d\n",maxHp,unit->getHp(),ut->getMaxHp()); @@ -941,6 +984,19 @@ void TotalUpgrade::sum(const UpgradeTypeBase *ut, const Unit *unit) { else { prodSpeed += ut->getProdSpeed(NULL); } + + if(ut->getAttackSpeedIsMultiplier() == true) { + for(unsigned int i = 0; i < (unsigned int)unit->getType()->getSkillTypeCount(); ++i) { + const SkillType *skillType = unit->getType()->getSkillType(i); + const AttackSkillType *ast = dynamic_cast(skillType); + if(ast != NULL) { + attackSpeedIsMultiplierValueList[ast->getName()] += ((double)ast->getSpeed() * ((double)ut->getAttackSpeed(NULL) / (double)100)); + } + } + } + else { + attackSpeed += ut->getAttackSpeed(NULL); + } } void TotalUpgrade::apply(const UpgradeTypeBase *ut, const Unit *unit) { @@ -1080,6 +1136,23 @@ void TotalUpgrade::deapply(const UpgradeTypeBase *ut,const Unit *unit) { prodSpeed -= ut->getProdSpeed(NULL); enforceMinimumValue(0,prodSpeed); } + + if(ut->getAttackSpeedIsMultiplier() == true) { + for(unsigned int i = 0; i < (unsigned int)unit->getType()->getSkillTypeCount(); ++i) { + const SkillType *skillType = unit->getType()->getSkillType(i); + const AttackSkillType *ast = dynamic_cast(skillType); + if(ast != NULL) { + attackSpeedIsMultiplierValueList[ast->getName()] -= ((double)ast->getSpeed() * ((double)ut->getAttackSpeed(NULL) / (double)100)); + enforceMinimumValue(0, attackSpeedIsMultiplierValueList[ast->getName()]); + } + } + + //printf("AFTER Applying moveSpeedIsMultiplier, moveSpeed = %d\n",moveSpeed); + } + else { + attackSpeed -= ut->getAttackSpeed(NULL); + enforceMinimumValue(0, attackSpeed); + } } void TotalUpgrade::incLevel(const UnitType *ut) { @@ -1184,6 +1257,16 @@ void TotalUpgrade::saveGame(XmlNode *rootNode) const { prodSpeedMorphIsMultiplierValueListNode->addAttribute("key",iterMap->first, mapTagReplacements); prodSpeedMorphIsMultiplierValueListNode->addAttribute("value",intToStr(iterMap->second), mapTagReplacements); } + + upgradeTypeBaseNode->addAttribute("attackSpeed",intToStr(attackSpeed), mapTagReplacements); + upgradeTypeBaseNode->addAttribute("attackSpeedIsMultiplier",intToStr(attackSpeedIsMultiplier), mapTagReplacements); + for(std::map::const_iterator iterMap = attackSpeedIsMultiplierValueList.begin(); + iterMap != attackSpeedIsMultiplierValueList.end(); ++iterMap) { + XmlNode *attackSpeedIsMultiplierValueListNode = upgradeTypeBaseNode->addChild("attackSpeedIsMultiplierValueList"); + + attackSpeedIsMultiplierValueListNode->addAttribute("key",iterMap->first, mapTagReplacements); + attackSpeedIsMultiplierValueListNode->addAttribute("value",intToStr(iterMap->second), mapTagReplacements); + } } void TotalUpgrade::loadGame(const XmlNode *rootNode) { @@ -1282,6 +1365,16 @@ void TotalUpgrade::loadGame(const XmlNode *rootNode) { prodSpeedMorphIsMultiplierValueList[node->getAttribute("key")->getValue()] = node->getAttribute("value")->getIntValue(); } + + attackSpeed = upgradeTypeBaseNode->getAttribute("attackSpeed")->getIntValue(); + attackSpeedIsMultiplier = upgradeTypeBaseNode->getAttribute("attackSpeedIsMultiplier")->getIntValue() != 0; + vector attackSpeedIsMultiplierValueNodeList = upgradeTypeBaseNode->getChildList("attackSpeedIsMultiplierValueList"); + for(unsigned int i = 0; i < attackSpeedIsMultiplierValueNodeList.size(); ++i) { + XmlNode *node = attackSpeedIsMultiplierValueNodeList[i]; + + attackSpeedIsMultiplierValueList[node->getAttribute("key")->getValue()] = + node->getAttribute("value")->getIntValue(); + } } diff --git a/source/glest_game/types/upgrade_type.h b/source/glest_game/types/upgrade_type.h index f3a1cf4a..5d8fa483 100644 --- a/source/glest_game/types/upgrade_type.h +++ b/source/glest_game/types/upgrade_type.h @@ -92,6 +92,10 @@ protected: std::map prodSpeedUpgradeIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */ std::map prodSpeedMorphIsMultiplierValueList; /**< @see #attackStrengthMultiplierValueList */ + int attackSpeed; + bool attackSpeedIsMultiplier; + std::map attackSpeedIsMultiplierValueList; + public: /** * Creates an UpgradeTypeBase with values such that there are no stat changes. @@ -142,13 +146,16 @@ public: bool getMoveSpeedIsMultiplier() const {return moveSpeedIsMultiplier;} int getProdSpeed(const SkillType *st) const; bool getProdSpeedIsMultiplier() const {return prodSpeedIsMultiplier;} - + int getAttackSpeed(const AttackSkillType *st) const; + bool getAttackSpeedIsMultiplier() const {return attackSpeedIsMultiplier;} + /** * Loads the upgrade values (stat boosts and whether or not the boosts use a multiplier) from an * XML node. * @param upgradeNode Node containing the stat boost elements (`max-hp`, `attack-strength`, etc). * @param upgradename Unique identifier for the upgrade. */ + void load(const XmlNode *upgradeNode, string upgradename); /** @@ -243,6 +250,9 @@ public: crcForUpgradeType.addInt64((int64)prodSpeedUpgradeIsMultiplierValueList.size()); //std::map prodSpeedMorphIsMultiplierValueList; crcForUpgradeType.addInt64((int64)prodSpeedMorphIsMultiplierValueList.size()); + + crcForUpgradeType.addInt(attackSpeed); + crcForUpgradeType.addInt(attackSpeedIsMultiplier); return crcForUpgradeType; }