Skip to content

Battle Mechanics

Cowculator is a turn-based strategy engine where each skill is processed in a pre-defined sequential order.

Turn Meter System

Each fighter has a turn meter to determine who act first:

  • Each fighter's turn meter increases every tick based on their speed stat.
  • When the meter reaches a defined threshold (TURN_METER_FULL, e.g., 1000), the fighter becomes active and performs its next skill.
  • The fighter with higher speed takes the first turn and acts more throughout the battle.
  • Battles have a maximum duration (default: 60 turns) to prevent infinite loops.

Skills and Passive Skills

Skills are the primary way fighters engage in battle. They are executed in a pre-defined sequential order. Each skill can:

  • Deal damage
  • Heal
  • Apply buffs (positive effects) or debuffs (negative effects)

Cowculator also supports passive skills, which automatically apply buffs or effects. It triggers at the start of battle.

See the Skills Guide for more details.

Damage Type

Cowculator supports two main types of damage:

Normal Damage:
  • Affected by the defense and any damage reduction effects.
True Damage:
  • Ignores the defense and damage reduction effects entirely.

Damage Calculation

Damage determines how much HP a fighter loses. It is calculated through the following steps:

  1. Base Damage:

    Calculate initial damage output before any defense or mitigation:

    base_damage = skill_damage * attacker.attack * attacker.damage_multiplier
    
  2. True Damage:

    If the skill's damage_type is true:

    • True damage ignores defense and damage reduction.
    • Final damage is simply:
        final_damage = base_damage
      
  3. Normal Damage:

    If the skill's damage_type is normal, calculate additional defence and damage reduction factor:

    1. Defense Mitigation:

      Reduce damage based on defender’s defense:

      defense_multiplier = max(MIN_DEFENSE_MULTIPLIER, 1 - (defender.defence / (defender.defence + DEFENSE_SCALING_FACTOR)))
      
    2. Damage Reduction:

      Further reduce damage based on flat reduction percentage:

      damage_reduction_multiplier = 1 - defender.damage_reduction
      
    3. Final Damage:

      Apply both defense and damage reduction:

      final_damage = max(1, base_damage * defense_multiplier * damage_reduction_multiplier)
      
  4. Critical Hit:

    1. Critical chance (to determine if the attack can deal critical hit):

      crit_chance = max(0, min(1, attacker.critical_rate - defender.critical_resistance))
      
    2. Critical Damage (if it is a critical hit):

      final_damage *= attacker.critical_damage
      

Example: How Cowculator Calculates Damage

Let’s walk through a full damage calculation example, step by step — from base damage to potential critical hits.

Stats Input

Stat Value
Attacker.attack 200
Attacker.damage_multiplier 1.2
Attacker.critical_rate 0.3
Attacker.critical_damage 2.0
Skill Damage 1.5
Defender.defence 100
Defender.damage_reduction 0.15
Defender.critical_resistance 0.1
DEFENSE_SCALING_FACTOR 200
MIN_DEFENSE_MULTIPLIER 0.2

Step-by-Step Breakdown

  1. Base Damage:

    base_damage = skill_damage * attacker.attack * attacker.damage_multiplier
                = 1.5 × 200 × 1.2
                = 360
    
  2. Defense Mitigation:

    Reduce damage based on defender’s defense:

    defence_multiplier = max(MIN_DEFENSE_MULTIPLIER, 1 - (defender.defence / (defender.defence + DEFENSE_SCALING_FACTOR)))
                       = max(0.2, 1 - (100 / (100 + 200)))
                       = max(0.2, 1 - 0.333)
                       = max(0.2, 0.667) = 0.667
    
  3. Damage Reduction:

    Further reduce damage based on flat reduction percentage:

    damage_reduction_multiplier = 1 - Defender.damage_reduction
                                = 1 - 0.15
                                = 0.85
    
  4. Final Raw Damage (Before Crit):

    Apply both defense and damage reduction:

    final_damage = max(1, base_damage × defense_multiplier × damage_reduction_multiplier)
                 = max(1, 360 × 0.667 × 0.85)
                 ≈ max(1, 204) = 204
    
  5. Critical Hit Chance:

    Determine if this hit can crit:

    crit_chance = max(0, min(1, Attacker.critical_rate - Defender.critical_resistance))
                = max(0, min(1, 0.3 - 0.1))
                = 0.2 → 20% chance to crit
    
  6. Final Damage (After Crit)

    If this hit is a critical hit, apply crit multiplier:

    crit_damage = final_damage × Attacker.critical_damage
                = 204 × 2.0 = 408
    

    So:

    Non-crit: 204
    Crit: 408
    
  7. True Damage?

    If this skill deals true damage, it skips defense and reduction steps:

    true_damage = base_damage = 360
    true_crit   = 360 × 2.0 = 720
    

Note

  • Minimum damage is always 1, even if reductions would lower it further.
  • True damage ignores defense and damage reduction, but can still be affected by critical hits.

Shields

A shield is a special type of buff that provides temporary protection that absorb damage before it affects HP. Shields are granted by certain skills or passive effects as a separate value from HP.

  • Damage is deducted from the shield first.
  • If the shield fully absorbs the hit, HP remains unchanged.
  • If the damage exceeds the shield, the remaining damage is applied to HP.
  • Shields may:
    • Be refreshed or replaced by skills
    • Expire after a set number of turns
    • Stack (configurable depending on your game)

Example

If a unit has a shield of 100 and receives 80 damage, the shield is reduced to 20 and HP is unaffected. If the unit receives 120 damage, the shield is depleted and the remaining 20 damage is applied to HP.

Energy System

Energy is consumed to use skills.

  • Each fighter starts with a base amount of energy.
  • Skills consume varying amounts of energy.
  • Energy regenerates over time or through specific actions.
  • Some effects can modify energy costs or regeneration rates.
  • default_skill will be used if there is not enough energy to perform the skill.

Default Skill

A fallback skill used when the fighter cannot afford the energy cost of its intended skill.

Battle Flow

Preparation

  1. Fighters are set up with initial stats (health, energy, turn meter, etc.).
  2. Passive skills are applied, granting buffs or special effects.

Battle Start

  1. Turn meters increment based on fighters' speed:

    turn_meter += speed
    
  2. When a fighter's turn meter reaches the threshold:

    • Turn Start:

      1. Remove expired status effects.
      2. Apply any active status effects, such as damage over time (DoT) or healing over time (HoT).
      3. The unit executes the next available skill (based on defined order)
      4. Deduct energy cost
      5. Execute the skill's actions, which may include:
        • Dealing damage
        • Applying buffs or debuffs
        • Healing allies
    • Turn End:

      • Apply end-of-turn effects (i.e, HP and Energy recovery)
      • Reset the acting fighter’s turn meter

Battle End

Battle ends when one of the fighter reach 0 HP or the turn limit reached. Fighter with the highest remaining HP will be the winner.

Battle Result

Every action, effect, and outcome of the battle is recorded in a battle log. This log provides transparency, helps with debugging, and can be used for analytics or replaying battles.

Please see Interpreting battle_event_logs for more details.