HeroDamage_runtime is the hero's Damage ParameterReference at fire time — it already includes any ModifyHeroParameterBonusData (e.g. Hammer relic +35..+825 flat) baked into its base value via the ModifiableValue
| # | StepКрок | Value sourceДжерело значення | ConfidenceДостовірність | NotesНотатки |
|---|---|---|---|---|
| 1 | Read hero Damage parameter at runtime | HeroParametersAbility.Damage.Value (ParameterReference -> ModifiableValue | FACT | Base value is HeroConfig.Levels[currentLevel-1].Damage. ModifyHeroParameterBonusData (e.g. Hammer relic, Damage milestone slot at L40 if it spawns Hammer-style) adds modifiers DIRECTLY to this ParameterReference, so they are folded into Value BEFORE the shot formula. Hammer Rare tier values (relic_modifiers.json): 35,75,120,175,240,320,415,530,665,825 flat damage. |
| 2 | Filter active ModifyDamageEffectConfig set | IEffectManager.GetEffects | FACT | Each ModifyDamageEffectConfig carries one IFloatModifier (AddFixed or AddPercent). Filters: target's EnemyType is in the EnemyTypes array (or array empty = all) AND target distance satisfies the DistanceComparisonResult condition. |
| 3 | Aggregate modifiers via Modify(baseValue, currentValue) | currentValue starts at HeroDamage_runtime; each ModifyDamageEffectConfig.Modifier.Modify(baseValue=HeroDamage_runtime, currentValue=accumulator) updates it | FACT | |
| 4 | Apply ModifyDamageToFrozenEnemiesEffectConfig (if target frozen) | Same Modify(baseValue, currentValue) accumulator pattern using ModifyDamageToFrozenEnemiesEffectConfig | FACT | Joins the same additive pool. Triggered only against frozen targets (after Snowball freeze, or any Freeze effect). |
| 5 | Apply ModifyDamageByCurrencyEffectConfig (if active) | Same accumulator pattern with currency-balance gating | FACT | Effect fires only if hero wallet holds the specified currency. Joins additive pool. |
| 6 | Roll crit, apply crit damage | If RollCritDamage(target) == true AND no DisableCriticalDamageEffectConfig active: damage *= CritDamage parameter value (default 2.0) | FACT | Bomb attaches DisableCriticalDamageEffectConfig on its AmmoItemConfig — Bomb shots NEVER crit. CritChance can be raised by ModifyCritChanceBonusData; CritDamage parameter can be raised by ModifyCritDamageBonusData (both seen as relic/vendor offer types). GuaranteedCritDamage* effects (Scout L100 sig 'AfterTakeDamage', OnChangeTarget, OnFirstHit) force RollCritDamage to true under their trigger conditions. |
| 7 | Apply punishment damage (if rolled) | If RollPunishment(ammo) == true: ApplyPunishmentDamage(ref damage, target, isAdditionalAmmo, wasBounced) — adds bonus damage according to AmmoPunishmentEffectConfig | FACT | Likely 'extra free shot' / 'execute' style bonus. Modifies same `damage` by reference, so it is a post-crit additive layer. |
| 8 | HeroLaunchAmmoAbility.Launch passes damage to HeroProjectileBehaviourAbility.Launch | Launch(launcher, ammoItemConfig, target, damage, isMultishot, pitch) | FACT | From this point onwards `damage` is fixed for the projectile. |
| 9 | On hit, projectile applies ModifyAmmoDamage / ModifyAmmoExplosionDamage / ModifyAmmoRadius effects | Aggregate via same Modify(base, current) pattern over per-ammo and per-AOE damage | FACT | These are SECONDARY pools — they fire on impact, scoped to the specific AmmoItemConfig (e.g. vendor's PepperBomb buff = ModifyAmmoDamageBonusData targeting AmmoItemConfig(Bomb) only). They modify the explosion/AOE damage portion separately from the main hit damage. |
| 10 | Apply ModifyBounceDamage / ModifyMultishotDamage (if bounced or multishot) | Aggregate via same pattern | FACT | |
| 11 | HeroDealDamageAbility.DealDamage -> HealthAbility.TakeDamage | HealthAbility.CurrentValue -= amount (after invoking DamageTakenAction) | FACT | NO enemy-side damage reduction. There is no EnemyParametersAbility class and EnemyDamageAbility only exposes an OUTGOING Damage (enemy-to-hero). Bosses have no Armor field (boss_data.json). The ONLY take-damage path that subtracts via a modifier is HeroTakeDamageAbility (hero receiving damage) which applies ModifyReceivedDamageEffectConfig — that's hero defense, not enemy defense. |
| 12 | Snowball special case | AmmoItemConfig(Snowball) carries DisableDamageEffectConfig — final damage forced to 0; FreezeEffectConfig applied instead | FACT |
All ModifyDamageEffectConfig modifiers contribute to the same pool inside HeroCalculateDamageAbility.CalculateBaseDamage. Percent modifiers stack additively on baseValue (Hero Damage parameter) — they do NOT compound multiplicatively. Flat modifiers add before percent.
These run AFTER CalculateBaseDamage returns. Crit uses ref-mutate; ammo/bounce/multishot effects use their own Modify(base, current) aggregator with their own baseValue (the post-base damage).
| SourceДжерело | MechanismМеханізм | RangeДіапазон | Joins poolПриєднується до пулу |
|---|---|---|---|
| Hero base Damage (per-level) | HeroConfig.Levels[currentLevel-1].Damage -> Hero.Damage ParameterReference | L1=30, L100=1500 (all 5 heroes share the same curve — hero_data.json) | base_value_pool |
| Milestone L40 Damage slot | ModifyDamageBonusData (single tier, applied once) | Value not extracted (HeroConfig L40 bonus payload — see HeroConfig.txt ENTRY[3] ModifyDamageBonusData) | additive_pool |
| Hero L80/L100 signature bonuses | Varies per hero — Scout L100 = GuaranteedCritDamageAfterTakeDamageBonusData (force crit after being hit) | Per-hero unique. Scout's adds a conditional always-crit trigger, not a damage % directly. | Affects step 6 (crit pipeline), not the additive pool |
| Active skill: AttackDamage tier | SkillConfig -> ModifyDamageEffectConfig pptr (T1='Attack Damage 115%', T2='Attack Damage 125%', T3='Attack Damage 150%', Super=T3+AmmoExplode AmmoBlowUp) | Asset names imply +15% / +25% / +50% (i.e. multiplier becomes 1.15/1.25/1.50). Could also be interpreted as the OUTPUT scaling (115%, 125%, 150% of base) — same numeric effect either way. Existing _report_data.json labels these as '+115%/+125%/+150%' which is INTERNALLY INCONSISTENT but most likely the report is mis-labelled and the true effect is +15%/+25%/+50% additive percent. | additive_pool |
| Active relic: Hammer (Rare) | ModifyHeroParameterBonusData targeting DamageParameterConfig with AddFixedFloatModifier | Per tier: +35, +75, +120, +175, +240, +320, +415, +530, +665, +825 flat Damage | base_value_pool |
| Vendor in-run offer: Fork | VendorConfig ENTRY[3] ModifyDamageBonusData targeting all enemies | +10% per existing report (numeric not in dumps) | additive_pool |
| Vendor in-run offer: PepperBomb | VendorConfig ENTRY[5] ModifyAmmoDamageBonusData targeting AmmoItemConfig(Bomb) | Per-Bomb shot only (NOT the main additive pool — fires inside projectile Launch via ModifyAmmoDamageEffectConfig step) | multiplicative_pool (ammo step) |
| Vendor in-run offer: Garlic | VendorConfig ENTRY[9] ModifyDamageBonusData | ? | additive_pool |
| Vendor in-run offer: Cake | VendorConfig ENTRY[13] ModifyDamageBonusData targeting EnemyTypeConfig(Boss) + EnemyTypeConfig(Super) | ? | additive_pool (conditional on target type) |
| Vendor in-run offer: Chitin | ModifyReceivedDamageBonusData — DEFENSIVE, hero damage taken reduction. Not part of outgoing shot formula. | ? | (not relevant to shot damage) |
| Ammo type — Bomb | AmmoItemConfig(Bomb) ModifyDamageEffectConfig(Attack Damage +150%) + DisableCriticalDamageEffectConfig | +150% additive percent (label asserts +150%, raw float not in dumps); crit forced off | additive_pool |
| Ammo type — Big Bullet | AmmoItemConfig(BigBullet) ModifyDamageEffectConfig(Big Bullet Attack Damage) | INFERRED +200% per design brief / report | additive_pool |
| Ammo type — Snowball | DisableDamageEffectConfig — zeroes damage; FreezeEffectConfig applies freeze | Damage = 0 | (short-circuits formula) |
| Crit roll | RollCritDamage -> ApplyCritDamage(ref damage). CritChance base = 0.05, CritDamage parameter base = 2.0 (hero_stats.csv tail_floats). | Multiplier 2.0 -> 6.0+ with stacked ModifyCritDamageBonusData. Disabled by DisableCriticalDamageEffectConfig (Bomb). | multiplicative_pool |
| Hero L100 sig: Scout — GuaranteedCritDamageAfterTakeDamage | GuaranteedCritDamageAfterTakeDamageBonusData -> GuaranteedCritDamageAfterTakeDamageEffectConfig; while active, RollCritDamage always returns true | ? | Forces step 6 to succeed (crit always lands during the trigger window) |
No EnemyParametersAbility class. EnemyDamageAbility (dump.cs:309198) only stores outgoing damage. boss_data.json has no Armor field. HealthAbility.TakeDamage(GameUnit owner, float amount, DamageType damageType) directly subtracts amount.
Status: FACT — enemies have no armor stat in Claw Master.
EnemyDodgeAbility (dump.cs:309308) with float DodgeChance field. IgnoreDodgeEffectConfig (dump.cs:298730) can suppress it.
Big Bullet / Bomb / Snowball all attach IgnoreDodgeEffectConfig — only normal Bullets can be dodged. The DodgeChance per enemy is not in the standard EnemyConfig fields parsed in extractions; INFERRED to be 0 for most enemies (the field would otherwise show up in additionalValue1/2 or a separate config — needs verification).
HeroDamage_runtime = 1500additive_percent_pool = +0.50 (AttackDamage T3 = +50%)additive_flat_pool = 0ammo_multiplier = Bullet = no contributioncrit = no roll (5% base chance, assume miss)HeroDamage_runtime = 1500additive_percent_pool = +0.50 (AttackDamage T3) + ~+2.00 (Big Bullet, INFERRED) = +2.50additive_flat_pool = 0crit_multiplier = 2.0HeroDamage_runtime = 1500 + 825 (Hammer T10 flat via ModifyHeroParameter) = 2325additive_percent_pool = +0.50 (AttackDamage T3) + +1.50 (Bomb) = +2.00additive_flat_pool = 0crit_multiplier = 1.0 (DisableCriticalDamage active from Bomb)HeroDamage_runtime = 1500additive_percent_pool = +0.00crit_multiplier = 2.0To resolve: verify by observing in-game damage numbers OR by binary-grepping the ModifyDamageEffectConfig payloads with the path_id list in combat_math.json.