Hooks
static bool BeforeCvUnit_GetRangeCombatDamage(const CvUnit* self, const CvUnit* pDefender, CvCity* pCity, bool bIncludeRand, int iAssumeExtraDamage, int& result);static void AfterCvUnit_GetRangeCombatDamage(const CvUnit* self, const CvUnit* pDefender, CvCity* pCity, bool bIncludeRand, int iAssumeExtraDamage, int& result);static int ReplaceCvUnit_GetRangeCombatDamage(int (*original)(const CvUnit*, const CvUnit*, CvCity*, bool, int), const CvUnit* self, const CvUnit* pDefender, CvCity* pCity, bool bIncludeRand, int iAssumeExtraDamage);CivRegisterBefore<CivHooks::CvUnit_GetRangeCombatDamage>(host, &BeforeCvUnit_GetRangeCombatDamage);CivRegisterAfter<CivHooks::CvUnit_GetRangeCombatDamage>(host, &AfterCvUnit_GetRangeCombatDamage);CivRegisterReplace<CivHooks::CvUnit_GetRangeCombatDamage>(host, &ReplaceCvUnit_GetRangeCombatDamage);
Code
13206int CvUnit::GetRangeCombatDamage(const CvUnit* pDefender, CvCity* pCity, bool bIncludeRand, int iAssumeExtraDamage) const13207{13208 VALIDATE_OBJECT1320913210 int iAttackerStrength = GetMaxRangedCombatStrength(pDefender, pCity, true, /*bForRangedAttack*/ true);13211 int iDefenderStrength;1321213213 CvPlayerAI& kPlayer = GET_PLAYER(getOwner());1321413215 // Unit is Defender13216 if(pCity == NULL)13217 {13218 // If this is a defenseless unit, do a fixed amount of damage13219 if(!pDefender->IsCanDefend())13220 return /*4*/ GC.getNONCOMBAT_UNIT_RANGED_DAMAGE();1322113222 if (pDefender->isEmbarked())13223 {13224 iDefenderStrength = pDefender->GetEmbarkedUnitDefense();;13225 }1322613227 // Use Ranged combat value for defender, UNLESS it's a boat or an Impi (ranged support)13228 else if(!pDefender->isRangedSupportFire() && pDefender->getDomainType() != DOMAIN_SEA && pDefender->GetMaxRangedCombatStrength(this, /*pCity*/ NULL, false, false) > 0)13229 {13230 iDefenderStrength = pDefender->GetMaxRangedCombatStrength(this, /*pCity*/ NULL, false, /*bForRangedAttack*/ false);1323113232 // Ranged units take less damage from one another13233 iDefenderStrength *= /*125*/ GC.getRANGE_ATTACK_RANGED_DEFENDER_MOD();13234 iDefenderStrength /= 100;13235 }13236 else13237 {13238 iDefenderStrength = pDefender->GetMaxDefenseStrength(pDefender->plot(), this, /*bFromRangedAttack*/ true);13239 }13240 }13241 // City is Defender13242 else13243 {13244 iDefenderStrength = pCity->getStrengthValue();13245 }1324613247 // The roll will vary damage between 30 and 40 (out of 100) for two units of identical strength1324813249 // Note, 0 is valid - means we don't do anything13250 int iWoundedDamageMultiplier = /*50*/ GC.getWOUNDED_DAMAGE_MULTIPLIER();13251 iWoundedDamageMultiplier += kPlayer.GetWoundedUnitDamageMod();132521325313254#if defined(MOD_UNITS_MAX_HP)13255 int iAttackerDamageRatio = GetMaxHitPoints() - ((getDamage() - iAssumeExtraDamage) * iWoundedDamageMultiplier / 100);13256#else13257 int iAttackerDamageRatio = GC.getMAX_HIT_POINTS() - ((getDamage() - iAssumeExtraDamage) * iWoundedDamageMultiplier / 100);13258#endif13259 if(iAttackerDamageRatio < 0)13260 iAttackerDamageRatio = 0;1326113262 int iAttackerDamage = /*250*/ GC.getRANGE_ATTACK_SAME_STRENGTH_MIN_DAMAGE();13263 iAttackerDamage *= iAttackerDamageRatio;13264#if defined(MOD_UNITS_MAX_HP)13265 iAttackerDamage /= GetMaxHitPoints();13266#else13267 iAttackerDamage /= GC.getMAX_HIT_POINTS();13268#endif1326913270 int iAttackerRoll = 0;13271 if(bIncludeRand)13272 {13273 iAttackerRoll = /*300*/ GC.getGame().getJonRandNum(GC.getRANGE_ATTACK_SAME_STRENGTH_POSSIBLE_EXTRA_DAMAGE(), "Unit Ranged Combat Damage");13274 iAttackerRoll *= iAttackerDamageRatio;13275#if defined(MOD_UNITS_MAX_HP)13276 iAttackerRoll /= GetMaxHitPoints();13277#else13278 iAttackerRoll /= GC.getMAX_HIT_POINTS();13279#endif13280 }13281 else13282 {13283 iAttackerRoll = /*300*/ GC.getRANGE_ATTACK_SAME_STRENGTH_POSSIBLE_EXTRA_DAMAGE();13284 iAttackerRoll -= 1; // Subtract 1 here, because this is the amount normally "lost" when doing a rand roll13285 iAttackerRoll *= iAttackerDamageRatio;13286#if defined(MOD_UNITS_MAX_HP)13287 iAttackerRoll /= GetMaxHitPoints();13288#else13289 iAttackerRoll /= GC.getMAX_HIT_POINTS();13290#endif13291 iAttackerRoll /= 2; // The divide by 2 is to provide the average damage13292 }13293 iAttackerDamage += iAttackerRoll;1329413295 double fStrengthRatio = (iDefenderStrength > 0)?(double(iAttackerStrength) / iDefenderStrength):double(iAttackerStrength);1329613297 // In case our strength is less than the other guy's, we'll do things in reverse then make the ratio 1 over the result13298 if(iDefenderStrength > iAttackerStrength)13299 {13300 fStrengthRatio = (double(iDefenderStrength) / iAttackerStrength);13301 }1330213303 fStrengthRatio = (fStrengthRatio + 3) / 4;13304 fStrengthRatio = pow(fStrengthRatio, 4.0);13305 fStrengthRatio = (fStrengthRatio + 1) / 2;1330613307 if(iDefenderStrength > iAttackerStrength)13308 {13309 fStrengthRatio = 1 / fStrengthRatio;13310 }1331113312 double fAttackerDamage = (double)iAttackerDamage * fStrengthRatio;13313 // Protect against it overflowing an int13314 if(fAttackerDamage > INT_MAX)13315 iAttackerDamage = INT_MAX;13316 else13317 iAttackerDamage = int(fAttackerDamage);1331813319 // Bring it back out of hundreds13320 iAttackerDamage /= 100;1332113322 iAttackerDamage = max(1,iAttackerDamage);1332313324 return iAttackerDamage;13325}