Hooks
static bool BeforeCvUnit_getCombatDamage(const CvUnit* self, int iStrength, int iOpponentStrength, int iCurrentDamage, bool bIncludeRand, bool bAttackerIsCity, bool bDefenderIsCity, int& result);static void AfterCvUnit_getCombatDamage(const CvUnit* self, int iStrength, int iOpponentStrength, int iCurrentDamage, bool bIncludeRand, bool bAttackerIsCity, bool bDefenderIsCity, int& result);static int ReplaceCvUnit_getCombatDamage(int (*original)(const CvUnit*, int, int, int, bool, bool, bool), const CvUnit* self, int iStrength, int iOpponentStrength, int iCurrentDamage, bool bIncludeRand, bool bAttackerIsCity, bool bDefenderIsCity);CivRegisterBefore<CivHooks::CvUnit_getCombatDamage>(host, &BeforeCvUnit_getCombatDamage);CivRegisterAfter<CivHooks::CvUnit_getCombatDamage>(host, &AfterCvUnit_getCombatDamage);CivRegisterReplace<CivHooks::CvUnit_getCombatDamage>(host, &ReplaceCvUnit_getCombatDamage);
Code
3419int CvUnit::getCombatDamage(int iStrength, int iOpponentStrength, int iCurrentDamage, bool bIncludeRand, bool bAttackerIsCity, bool bDefenderIsCity) const3420{3421 VALIDATE_OBJECT3422 // The roll will vary damage between 40 and 60 (out of 100) for two units of identical strength34233424 int iDamageRatio;34253426 int iWoundedDamageMultiplier = /*50*/ GC.getWOUNDED_DAMAGE_MULTIPLIER();34273428 if(bAttackerIsCity)3429 {3430#if defined(MOD_UNITS_MAX_HP)3431 // Yeah, given the comment on the line below it looks weird, but the max HP of cities isn't GC.getMAX_HIT_POINTS() but pCity->GetMaxHitPoints(), so this works3432 iDamageRatio = GetMaxHitPoints(); // JON: Cities don't do less damage when wounded3433#else3434 iDamageRatio = GC.getMAX_HIT_POINTS(); // JON: Cities don't do less damage when wounded3435#endif3436 }3437 else3438 {3439 // Mod (Policies, etc.)3440 iWoundedDamageMultiplier += GET_PLAYER(getOwner()).GetWoundedUnitDamageMod();34413442#if defined(MOD_UNITS_MAX_HP)3443 iDamageRatio = GetMaxHitPoints() - (iCurrentDamage * iWoundedDamageMultiplier / 100);3444#else3445 iDamageRatio = GC.getMAX_HIT_POINTS() - (iCurrentDamage * iWoundedDamageMultiplier / 100);3446#endif3447 }34483449 int iDamage = 0;34503451#if defined(MOD_UNITS_MAX_HP)3452 iDamage = /*400*/ GC.getATTACK_SAME_STRENGTH_MIN_DAMAGE() * iDamageRatio / GetMaxHitPoints();3453#else3454 iDamage = /*400*/ GC.getATTACK_SAME_STRENGTH_MIN_DAMAGE() * iDamageRatio / GC.getMAX_HIT_POINTS();3455#endif34563457 // Don't use rand when calculating projected combat results3458 int iRoll = 0;3459 if(bIncludeRand)3460 {3461 iRoll = /*400*/ GC.getGame().getJonRandNum(GC.getATTACK_SAME_STRENGTH_POSSIBLE_EXTRA_DAMAGE(), "Unit Combat Damage");3462 iRoll *= iDamageRatio;3463#if defined(MOD_UNITS_MAX_HP)3464 iRoll /= GetMaxHitPoints();3465#else3466 iRoll /= GC.getMAX_HIT_POINTS();3467#endif3468 }3469 else3470 {3471 iRoll = /*400*/ GC.getATTACK_SAME_STRENGTH_POSSIBLE_EXTRA_DAMAGE();3472 iRoll -= 1; // Subtract 1 here, because this is the amount normally "lost" when doing a rand roll3473 iRoll *= iDamageRatio;3474#if defined(MOD_UNITS_MAX_HP)3475 iRoll /= GetMaxHitPoints();3476#else3477 iRoll /= GC.getMAX_HIT_POINTS();3478#endif3479 iRoll /= 2; // The divide by 2 is to provide the average damage3480 }3481 iDamage += iRoll;34823483 // Calculations performed to dampen amount of damage by units that are close in strength3484 // RATIO = (((((ME / OPP) + 3) / 4) ^ 4) + 1) / 23485 // Examples:3486 // 1.301 = (((((9 / 6) + 3) / 4) ^ 4) + 1 / 23487 // 17.5 = (((((40 / 6) + 3) / 4) ^ 4) + 1 / 234883489 double fStrengthRatio = (double(iStrength) / iOpponentStrength);34903491 // In case our strength is less than the other guy's, we'll do things in reverse then make the ratio 1 over the result (we need a # above 1.0)3492 if(iOpponentStrength > iStrength)3493 {3494 fStrengthRatio = (double(iOpponentStrength) / iStrength);3495 }34963497 fStrengthRatio = (fStrengthRatio + 3) / 4;3498 fStrengthRatio = pow(fStrengthRatio, 4.0);3499 fStrengthRatio = (fStrengthRatio + 1) / 2;35003501 if(iOpponentStrength > iStrength)3502 {3503 fStrengthRatio = 1 / fStrengthRatio;3504 }35053506 iDamage = int(iDamage * fStrengthRatio);35073508 // Modify damage for when a city "attacks" a unit3509 if(bAttackerIsCity)3510 {3511 iDamage *= /*50*/ GC.getCITY_ATTACKING_DAMAGE_MOD();3512 iDamage /= 100;3513 }35143515 // Modify damage for when unit is attacking a city3516 if(bDefenderIsCity)3517 {3518 iDamage *= /*100*/ GC.getATTACKING_CITY_MELEE_DAMAGE_MOD();3519 iDamage /= 100;3520 }35213522 // Bring it back out of hundreds3523 iDamage /= 100;35243525 iDamage = iDamage > 0 ? iDamage : 1;35263527 return iDamage;3528}