Help me understand Combat Power calculation — my formula doesn't match the game
---
**TL;DR:** I tried to reverse-engineer `Unit_CombatPower` for Byzantine Light Archers (got ~9) and Skoutatoi (got ~32). But the game shows different numbers. Can anyone point out my mistakes or give me the actual in-game values so I can work backwards?
---
---
Hi everyone,
I've been trying to reverse-engineer the `Unit_CombatPower` function from `Unit.BSF` to understand how Combat Power is calculated. But my results don't match what the game shows. Can anyone help me figure out what I'm missing?
## The Formula (as I understand it)
From `Unit.BSF`:
```c
FUNCTION Unit_CombatPower(unitID)
{
attack = Unit_Attack(unitID) + (Unit_FlankingMod(unitID) / 2) + (Unit_AttackAssaultChange(unitID) / 2);
defense = Unit_Defense(unitID) + (Unit_DefenseAssaultChange(unitID) / 2);
range = Unit_RangedAttackValue(unitID) + Unit_RangedMaxEffecDamages(unitID);
xp = Unit_GetXPLevel(unitID);
base = (Unit_GetHits(unitID) * UNIT_CP_HIT_INCh) + (Unit_GetEffec(unitID) * UNIT_CP_EFF_INCh);
base += (attack * UNIT_CP_ATK_INCh) + (defense * UNIT_CP_DEF_INCh);
base += (range * UNIT_CP_RNG_INCh) + (xp * UNIT_CP_EXP_INCh);
mult = (Unit_GetHits(unitID) * UNIT_CP_HIT_PERC) + (Unit_GetEffec(unitID) * UNIT_CP_EFF_PERC);
mult += (attack * UNIT_CP_ATK_PERC) + (defense * UNIT_CP_DEF_PERC);
mult += (range * UNIT_CP_RNG_PERC) + (xp * UNIT_CP_EXP_PERC);
result = base * (100 + mult);
result = DivideAndRound(result, 10000);
result = Pow(result, UNIT_CP_NUMERATORh, UNIT_CP_DENOMINATORh) / 10; // ^1.66
result = Max(1, result);
if (Unit_TemplateKind(unitID) == KIND_NAV)
result /= 2;
return result;
}
```
With the constants (from the comments):
```
UNIT_CP_HIT_INCh = 100
UNIT_CP_EFF_INCh = 50
UNIT_CP_EXP_INCh = 35
UNIT_CP_ATK_INCh = 25
UNIT_CP_DEF_INCh = 25
UNIT_CP_RNG_INCh = 10
UNIT_CP_HIT_PERC = 8
UNIT_CP_EFF_PERC = 22
UNIT_CP_EXP_PERC = 18
UNIT_CP_ATK_PERC = 15
UNIT_CP_DEF_PERC = 15
UNIT_CP_RNG_PERC = 6
```
## Example 1: Byzantine Light Archers
| Stat | Value |
|---|---|
| Hits | 1 |
| Effectiveness | 3 |
| Attack | 3 |
| Defense | 3 |
| RangedAttack | 7 |
| RangedMaxDamages | 1 |
| FlankingModifier | 1 |
| AtkAssaultChg | 0 |
| DefAssaultChg | 1 |
| XP Level | 0 |
### My calculation
**Step 1 — Compute derived stats:**
```
attack = 3 + (1 / 2) + (0 / 2) = 3 + 0 + 0 = 3
defense = 3 + (1 / 2) = 3 + 0 = 3
range = 7 + 1 = 8
xp = 0
```
> Note: integer division, `1/2 = 0`.
**Step 2 — Base value:**
```
base = (1 × 100) + (3 × 50) = 100 + 150 = 250
base += (3 × 25) + (3 × 25) = 75 + 75 = 150
base += (8 × 10) + (0 × 35) = 80 + 0 = 80
base = 250 + 150 + 80 = 480
```
**Step 3 — Multiplier:**
```
mult = (1 × 8 ) + (3 × 22) = 8 + 66 = 74
mult += (3 × 15) + (3 × 15) = 45 + 45 = 90
mult += (8 × 6) + (0 × 18) = 48 + 0 = 48
mult = 74 + 90 + 48 = 212
```
**Step 4 — Combine:**
```
result = 480 × (100 + 212) = 480 × 312 = 149,760
result = 149,760 / 10,000 = 14.976
```
**Step 5 — Pow(1.66):**
```
14.976 ^ 1.66 ≈ ?
ln(14.976) ≈ 2.7063
1.66 × 2.7063 ≈ 4.4925
e^4.4925 ≈ 89.4
result = 89.4 / 10 = 8.94
```
**Step 6 — Final:**
```
result = max(1, 8.94) = 8.94 ≈ 9
```
**My result: ~9**
But the game shows 5. Can anyone tell me where the discrepancy comes from?
## Example 2: Skoutatoi
| Stat | Value |
|---|---|
| Hits | 3 |
| Effectiveness | 3 |
| Attack | 6 |
| Defense | 8 |
| RangedAttack | 0 |
| RangedMaxDamages | 0 |
| FlankingModifier | 1 |
| AtkAssaultChg | 1 |
| DefAssaultChg | 0 |
| XP Level | 0|
### My calculation
**Step 1 — Derived stats:**
```
attack = 6 + (1 / 2) + (1 / 2) = 6 + 0 + 0 = 6
defense = 8 + (0 / 2) = 8 + 0 = 8
range = 0 + 0 = 0
xp = 0
```
**Step 2 — Base value:**
```
base = (3 × 100) + (3 × 50) = 300 + 150 = 450
base += (6 × 25) + (8 × 25) = 150 + 200 = 350
base += (0 × 10) + (0 × 35) = 0 + 0 = 0
base = 450 + 350 + 0 = 800
```
**Step 3 — Multiplier:**
```
mult = (3 × 8 ) + (3 × 22) = 24 + 66 = 90
mult += (6 × 15) + (8 × 15) = 90 + 120 = 210
mult += (0 × 6) + (0 × 18) = 0 + 0 = 0
mult = 90 + 210 + 0 = 300
```
**Step 4 — Combine:**
```
result = 800 × (100 + 300) = 800 × 400 = 320,000
result = 320,000 / 10,000 = 32.0
```
**Step 5 — Pow(1.66):**
```
32 ^ 1.66 ≈ ?
ln(32) ≈ 3.4657
1.66 × 3.4657 ≈ 5.7531
e^5.7531 ≈ 315.4
result = 315.4 / 10 = 31.54
```
**Step 6 — Final:**
```
result = max(1, 31.54) = 31.54 ≈ 32
```
**My result: ~32**
But the game shows 12.
## My Questions
1. **Are my constants correct?** I got them from comments in `Unit.BSF`.
2. **Integer division truncation:** In `attack = Unit_Attack + (Flanking / 2) + (AtkAssaultChg / 2)`, does `1 / 2` become 0 (integer) or 0.5 (float)?
Thanks for any help!
Why Does My Combat Power Calculation Differ from the Game?
Moderator: FOGK Moderators
-
duirixuanyan
- Corporal - Strongpoint

- Posts: 61
- Joined: Mon Aug 05, 2019 3:11 pm
Re: Why Does My Combat Power Calculation Differ from the Game?
Won't the result of step 4 be 15 as its divide and round?
There should be a file where the real numbers are.
There should be a file where the real numbers are.
There are 10 kind of hard problems in computer science, naming, cache invalidations and off-by-one errors.
There are also 10 kinds of people, those who understand binary and those who do not.
There are also 10 kinds of people, those who understand binary and those who do not.
-
duirixuanyan
- Corporal - Strongpoint

- Posts: 61
- Joined: Mon Aug 05, 2019 3:11 pm
Re: Why Does My Combat Power Calculation Differ from the Game?
Thanks for replying.
Yes, the result of step 4 should be 15. However, the number still doesn't match which is confusing.
Yes, the result of step 4 should be 15. However, the number still doesn't match which is confusing.
Re: Why Does My Combat Power Calculation Differ from the Game?
Comments gets outdated so you need to find the file where the values are actually set.duirixuanyan wrote: Mon Oct 12, 2026 7:25 am Thanks for replying.
Yes, the result of step 4 should be 15. However, the number still doesn't match which is confusing.
There are 10 kind of hard problems in computer science, naming, cache invalidations and off-by-one errors.
There are also 10 kinds of people, those who understand binary and those who do not.
There are also 10 kinds of people, those who understand binary and those who do not.
-
duirixuanyan
- Corporal - Strongpoint

- Posts: 61
- Joined: Mon Aug 05, 2019 3:11 pm
Re: Why Does My Combat Power Calculation Differ from the Game?
Surt wrote: Mon Oct 12, 2026 10:26 am Comments gets outdated so you need to find the file where the values are actually set.
Thank you. You are right. The real values are in MapGlobals.BSF as follows. And the numbers finally match with the game.
Code: Select all
// Units, cbt power estimate
// see Unit_CombatPower for the details
#define UNIT_CP_HIT_INCh 75
#define UNIT_CP_HIT_PERC 10
#define UNIT_CP_EFF_INCh 50
#define UNIT_CP_EFF_PERC 20
#define UNIT_CP_EXP_INCh 25
#define UNIT_CP_EXP_PERC 18
#define UNIT_CP_ATK_INCh 15
#define UNIT_CP_ATK_PERC 8
#define UNIT_CP_DEF_INCh 15
#define UNIT_CP_DEF_PERC 8
#define UNIT_CP_RNG_INCh 10
#define UNIT_CP_RNG_PERC 6
#define UNIT_CP_NUMERATORh 200
#define UNIT_CP_DENOMINATORh 120-
duirixuanyan
- Corporal - Strongpoint

- Posts: 61
- Joined: Mon Aug 05, 2019 3:11 pm
Re: Why Does My Combat Power Calculation Differ from the Game?
Code: Select all
case 1
attack = Attack + FlankingMod/2 + AtkAssaultChg/2
= 3 + 1/2 + 0/2
= 3 + 0 + 0 (Truncating division,1/2 = 0)
= 3
defense = Defense + DefAssaultChg/2
= 3 + 1/2
= 3 + 0
= 3
range = RangedAttack + RangedMaxDamages
= 7 + 1
= 8
xp = 0Code: Select all
case 2
attack = Attack + FlankingMod/2 + AtkAssaultChg/2
= 6 + 1/2 + 1/2
= 6 + 0 + 0 (Truncating division,1/2 = 0)
= 6
defense = Defense + DefAssaultChg/2
= 8 + 0/2
= 8
range = RangedAttack + RangedMaxDamages
= 0 + 0
= 0
xp = 0Re: Why Does My Combat Power Calculation Differ from the Game?
Hmm yeah the values should be multiplied by x and then only at the end rounded. There x could be 2 as that is the only divisor.
There are 10 kind of hard problems in computer science, naming, cache invalidations and off-by-one errors.
There are also 10 kinds of people, those who understand binary and those who do not.
There are also 10 kinds of people, those who understand binary and those who do not.
