Attack speed is now upgradable

Syntax is the same as all other upgrade stats. This also allows attack
boosts to upgrade the attack speed (since they use the same code).
This commit is contained in:
Mike Hoffert 2014-07-19 22:01:34 -06:00
parent 31def0dc1a
commit 3165e41014
6 changed files with 129 additions and 1 deletions

View File

@ -2615,7 +2615,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;

View File

@ -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;
}

View File

@ -935,6 +935,16 @@ 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;
}
int AttackSkillType::getAnimSpeedBoost(const TotalUpgrade *totalUpgrade) const{
return totalUpgrade->getAttackSpeed(this);
}
string AttackSkillType::toString(bool translatedValue) const{
if(translatedValue == false) {
return "Attack";

View File

@ -309,6 +309,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);
};

View File

@ -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<const AttackSkillType *>(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<const AttackSkillType *>(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<string,int>::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<XmlNode *> 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();
}
}

View File

@ -80,6 +80,10 @@ protected:
std::map<string,int> prodSpeedUpgradeIsMultiplierValueList;
std::map<string,int> prodSpeedMorphIsMultiplierValueList;
int attackSpeed;
bool attackSpeedIsMultiplier;
std::map<string,int> attackSpeedIsMultiplierValueList;
public:
UpgradeTypeBase() {
maxHp = 0;;
@ -127,6 +131,8 @@ 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;}
void load(const XmlNode *upgradeNode, string upgradename);
@ -207,6 +213,9 @@ public:
crcForUpgradeType.addInt64((int64)prodSpeedUpgradeIsMultiplierValueList.size());
//std::map<string,int> prodSpeedMorphIsMultiplierValueList;
crcForUpgradeType.addInt64((int64)prodSpeedMorphIsMultiplierValueList.size());
crcForUpgradeType.addInt(attackSpeed);
crcForUpgradeType.addInt(attackSpeedIsMultiplier);
return crcForUpgradeType;
}