Skip to content

Damage Calculation

When an attack action succeeds, Cowculator calculates one whole-number damage amount. The calculation depends on the attack's damage type, the attacker's stats, the defender's protection, and whether the attack is a critical hit.

In the formulas below, action.damage_value is the value configured on the attack action. Buffs and debuffs can change the stats used by the formulas. After these modifiers are combined:

  • Effective attack and damage multiplier cannot fall below 0.
  • Critical damage cannot fall below 1.
  • Damage reduction remains between 0 and 1.

Calculation order

Cowculator calculates damage in four stages:

  1. Calculate base damage.
  2. Apply defence and damage reduction for normal damage.
  3. Check for a critical hit.
  4. Round the result and enforce minimum damage.

Shields and current health are handled afterward when the calculated damage is resolved against the target.

1. Calculate base damage

Base damage combines the action's damage value with the attacker's effective attack and general damage multiplier:

base_damage = action.damage_value × attacker.attack × attacker.damage_multiplier

The target's protection and any critical hit have not yet been applied.

2. Apply the damage type

Normal damage uses the target's defence and damage reduction. True damage skips both of these stats.

Normal damage

Cowculator first calculates a defence multiplier using two balance constants:

Constant Current value Purpose
DEFENSE_SCALING_FACTOR 100 Controls how strongly defence changes damage
MIN_DEFENSE_MULTIPLIER 0.1 Prevents non-negative defence from reducing damage below 10% at this stage

For zero or positive defence:

defence_multiplier = max(MIN_DEFENSE_MULTIPLIER, 1 - defender.defence / (defender.defence + DEFENSE_SCALING_FACTOR))

Higher defence produces a smaller multiplier until it reaches the configured minimum.

Negative defence uses a separate formula:

defence_multiplier = 2 - DEFENSE_SCALING_FACTOR / (DEFENSE_SCALING_FACTOR + abs(defender.defence))

Negative defence increases normal damage. The multiplier is greater than 1 and approaches, but never reaches, 2 as defence becomes more negative.

Cowculator then applies the defence multiplier and damage reduction:

damage_before_critical = base_damage × defence_multiplier × (1 - defender.damage_reduction)

True damage

True damage skips defence and damage reduction:

damage_before_critical = base_damage

Critical hits, minimum damage, shields, and available health still apply.

3. Check for a critical hit

The attacker's critical rate is opposed by the defender's critical resistance:

critical_chance = clamp(attacker.critical_rate - defender.critical_resistance, 0, 1)

If the critical check succeeds, Cowculator applies the attacker's critical damage multiplier:

damage_after_critical = damage_before_critical × attacker.critical_damage

If the check fails, damage_after_critical equals damage_before_critical.

4. Produce calculated damage

Cowculator rounds the result once using round-half-up, then enforces a minimum calculated damage of 1:

calculated_damage = max(1, round_half_up(damage_after_critical))

This amount is then resolved against the target. Shields may absorb some or all of it, and damage cannot remove more health than the target currently has. Battle events therefore distinguish calculated damage, shield absorption, and the amount applied to health.

Worked example

Suppose a normal attack resolves with these values:

Input Value
action.damage_value 1.5
attacker.attack 200
attacker.damage_multiplier 1.2
attacker.critical_rate 0.3
attacker.critical_damage 2.0
defender.defence 100
defender.damage_reduction 0.15
defender.critical_resistance 0.1
DEFENSE_SCALING_FACTOR 100
MIN_DEFENSE_MULTIPLIER 0.1

Base damage

base_damage = action.damage_value × attacker.attack × attacker.damage_multiplier
            = 1.5 × 200 × 1.2
            = 360

Defence multiplier

defence_multiplier = max(MIN_DEFENSE_MULTIPLIER, 1 - 100 / (100 + DEFENSE_SCALING_FACTOR))
                   = max(0.1, 1 - 100 / (100 + 100))
                   = max(0.1, 0.5)
                   = 0.5

Damage after protection

damage_before_critical = base_damage × defence_multiplier × (1 - defender.damage_reduction)
                       = 360 × 0.5 × (1 - 0.15)
                       = 360 × 0.5 × 0.85
                       = 153

Critical chance

critical_chance = clamp(attacker.critical_rate - defender.critical_resistance, 0, 1)
                = clamp(0.3 - 0.1, 0, 1)
                = 0.2

The attack has a 20% chance to be critical.

Calculated damage

  • Without a critical hit: round_half_up(153) = 153.
  • With a critical hit: round_half_up(153 × 2.0) = 306.

With the same offensive values and damage_type: "true", Cowculator skips the defence multiplier and damage reduction. The calculated damage is 360, or 720 on a critical hit, before shield absorption and health application.

See the battle mechanics overview for how damage fits into the rest of a battle.