/// Update military Power void CvUnitEntry::DoUpdatePower() { int iPower; // *************** // Main Factors - Strength & Moves // *************** // We want a Unit that has twice the strength to be roughly worth 3x as much with regards to Power iPower = int(pow((double) GetCombat(), 1.5)); // Ranged Strength int iRangedStrength = int(pow((double) GetRangedCombat(), 1.45)); // Naval ranged attacks are less useful if(GetDomainType() == DOMAIN_SEA) { iRangedStrength /= 2; } if(iRangedStrength > 0) { iPower = iRangedStrength; } // We want Movement rate to be important, but not a dominating factor; a Unit with double the moves of a similarly-strengthed Unit should be ~1.5x as Powerful iPower = int((float) iPower * pow((double) GetMoves(), 0.3)); // *************** // Other modifiers // *************** // Suicide Units are obviously less useful if(IsSuicide()) { iPower /= 2; } // Nukes are cool if(GetNukeDamageLevel() > 0) { iPower += 4000; } // *************** // Promotion modifiers // *************** int iTemp; int iLoop; for(int iPromotionLoop = 0; iPromotionLoop < GC.getNumPromotionInfos(); iPromotionLoop++) { CvPromotionEntry* kPromotion = GC.getPromotionInfo((PromotionTypes)iPromotionLoop); if(kPromotion == NULL) continue; if(GetFreePromotions(iPromotionLoop)) { // City Attack - add half of the bonus if(kPromotion->GetCityAttackPercent() > 0) { iTemp = (iPower * kPromotion->GetCityAttackPercent() / 2); iTemp /= 100; iPower += iTemp; } // Attack - add half of the bonus if(kPromotion->GetAttackMod() > 0) { iTemp = (iPower * kPromotion->GetAttackMod() / 2); iTemp /= 100; iPower += iTemp; } // Defense - add half of the bonus if(kPromotion->GetDefenseMod() > 0) { iTemp = (iPower * kPromotion->GetDefenseMod() / 2); iTemp /= 100; iPower += iTemp; } // Paradrop - add 25% if(kPromotion->GetDropRange() > 0) { iTemp = iPower; iTemp /= 4; iPower += iTemp; } // Blitz - add 20% if(kPromotion->IsBlitz()) { iTemp = iPower; iTemp /= 5; iPower += iTemp; } // Set Up For Ranged Attack - reduce by 20% if(kPromotion->IsMustSetUpToRangedAttack()) { iTemp = iPower; iTemp /= 5; iPower -= iTemp; } // Only Defensive - reduce by 25%, but only if the Unit has no ranged capability if(kPromotion->IsOnlyDefensive() && GetRangedCombat() == 0) { iTemp = iPower; iTemp /= 4; iPower -= iTemp; } for(iLoop = 0; iLoop < GC.getNumTerrainInfos(); iLoop++) { // Terrain Attack - add one quarter of the bonus if(kPromotion->GetTerrainAttackPercent(iLoop) > 0) { iTemp = (iPower * kPromotion->GetTerrainAttackPercent(iLoop) / 4); iTemp /= 100; iPower += iTemp; } // Terrain Defense - add one quarter of the bonus if(kPromotion->GetTerrainDefensePercent(iLoop) > 0) { iTemp = (iPower * kPromotion->GetTerrainDefensePercent(iLoop) / 4); iTemp /= 100; iPower += iTemp; } } for(iLoop = 0; iLoop < GC.getNumFeatureInfos(); iLoop++) { // Feature Attack - add one quarter of the bonus if(kPromotion->GetFeatureAttackPercent(iLoop) > 0) { iTemp = (iPower * kPromotion->GetFeatureAttackPercent(iLoop) / 4); iTemp /= 100; iPower += iTemp; } // Feature Defense - add one quarter of the bonus if(kPromotion->GetFeatureDefensePercent(iLoop) > 0) { iTemp = (iPower * kPromotion->GetFeatureDefensePercent(iLoop) / 4); iTemp /= 100; iPower += iTemp; } } for(iLoop = 0; iLoop < GC.getNumUnitCombatClassInfos(); iLoop++) { // Unit Combat Class (e.g. Pikemen) - add one quarter of the bonus if(kPromotion->GetUnitCombatModifierPercent(iLoop) > 0) { iTemp = (iPower * kPromotion->GetUnitCombatModifierPercent(iLoop) / 4); iTemp /= 100; iPower += iTemp; } } for(iLoop = 0; iLoop < GC.getNumUnitClassInfos(); iLoop++) { // Unit Class (e.g. bonus ONLY against Galleys) - add one eighth of the bonus // We're assuming here that the bonus against the other Unit is at least going to be somewhat useful - trust the XML! :o if(kPromotion->GetUnitClassModifierPercent(iLoop) > 0) { iTemp = (iPower * kPromotion->GetUnitClassModifierPercent(iLoop) / 8); iTemp /= 100; iPower += iTemp; } // Unit Class Attack - one tenth of the bonus if(kPromotion->GetUnitClassAttackModifier(iLoop) > 0) { iTemp = (iPower * kPromotion->GetUnitClassAttackModifier(iLoop) / 10); iTemp /= 100; iPower += iTemp; } // Unit Class Defense - one tenth of the bonus if(kPromotion->GetUnitClassDefenseModifier(iLoop) > 0) { iTemp = (iPower * kPromotion->GetUnitClassDefenseModifier(iLoop) / 10); iTemp /= 100; iPower += iTemp; } } for(iLoop = 0; iLoop < NUM_DOMAIN_TYPES; iLoop++) { // Domain - add one quarter of the bonus if(kPromotion->GetDomainModifierPercent(iLoop) > 0) { iTemp = (iPower * kPromotion->GetDomainModifierPercent(iLoop) / 4); iTemp /= 100; iPower += iTemp; } } } } // Debug output //char temp[256]; //sprintf(temp, "%s: %i\n", GetDescription(), iPower); //OutputDebugString(temp); m_iCachedPower = iPower; }
bool isPromotionValid(PromotionTypes ePromotion, UnitTypes eUnit, bool bLeader, bool bTestingPrereq) { CvUnitEntry* unitInfo = GC.getUnitInfo(eUnit); CvPromotionEntry* promotionInfo = GC.getPromotionInfo(ePromotion); if(unitInfo == NULL || promotionInfo == NULL) return false; // Can this Promotion not be chosen through normal leveling? if(!bTestingPrereq && promotionInfo->IsCannotBeChosen()) { return false; } // If a Unit gets a Promotion for free then hand it out, no questions asked if(unitInfo->GetFreePromotions(ePromotion)) { return true; } // If this isn't a combat Unit, no Promotion if(unitInfo->GetUnitCombatType() == NO_UNITCOMBAT) { return false; } // Is this a valid Promotion for the UnitCombatType? if(!::IsPromotionValidForUnitCombatType(ePromotion, eUnit)) { return false; } if(!bLeader && promotionInfo->IsLeader()) { return false; } // If the Unit only has one move then Blitz is not useful if(unitInfo->GetMoves() == 1) { if(promotionInfo->IsBlitz()) { return false; } } // Promotion Prereqs if(NO_PROMOTION != promotionInfo->GetPrereqPromotion()) { if(!isPromotionValid((PromotionTypes)promotionInfo->GetPrereqPromotion(), eUnit, bLeader, true)) { return false; } } PromotionTypes ePrereq1 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion1(); PromotionTypes ePrereq2 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion2(); PromotionTypes ePrereq3 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion3(); PromotionTypes ePrereq4 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion4(); PromotionTypes ePrereq5 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion5(); PromotionTypes ePrereq6 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion6(); PromotionTypes ePrereq7 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion7(); PromotionTypes ePrereq8 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion8(); PromotionTypes ePrereq9 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion9(); if(ePrereq1 != NO_PROMOTION || ePrereq2 != NO_PROMOTION || ePrereq3 != NO_PROMOTION || ePrereq4 != NO_PROMOTION || ePrereq5 != NO_PROMOTION || ePrereq6 != NO_PROMOTION || ePrereq7 != NO_PROMOTION || ePrereq8 != NO_PROMOTION || ePrereq9 != NO_PROMOTION) { bool bValid = false; if(!bValid) { if(NO_PROMOTION != ePrereq1 && isPromotionValid(ePrereq1, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq2 && isPromotionValid(ePrereq2, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq3 && isPromotionValid(ePrereq3, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq4 && isPromotionValid(ePrereq4, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq5 && isPromotionValid(ePrereq5, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq6 && isPromotionValid(ePrereq6, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq7 && isPromotionValid(ePrereq7, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq8 && isPromotionValid(ePrereq8, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq9 && isPromotionValid(ePrereq9, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { return false; } } return true; }