@@ -1073,31 +1073,42 @@ export class StatEngine {
10731073
10741074 this . debugLogs . push ( `Flat Stats: Damage=${ flatDamageWithMelee . toFixed ( 0 ) } (skillPassive: ${ this . stats . skillPassiveDamage . toFixed ( 0 ) } ), Health=${ flatHealth . toFixed ( 0 ) } (skillPassive: ${ this . stats . skillPassiveHealth . toFixed ( 0 ) } )` ) ;
10751075
1076- // 4. Mount, Secondary DamageMulti/HealthMulti, Skin Bonuses, and Set Bonuses are ADDITIVE
1077- const damageAdditiveMulti = 1 + this . mountDamageMulti + this . secondaryStats . damageMulti + this . skinDamageMulti + this . setDamageMulti ;
1078- const healthAdditiveMulti = 1 + this . mountHealthMulti + this . secondaryStats . healthMulti + this . skinHealthMulti + this . setHealthMulti ;
1076+ // 4. Additive Multipliers: Mount + Secondary (Tech Tree/Items)
1077+ const damageAdditiveMulti = 1 + this . mountDamageMulti + this . secondaryStats . damageMulti ;
1078+ const healthAdditiveMulti = 1 + this . mountHealthMulti + this . secondaryStats . healthMulti ;
10791079
10801080 this . debugLogs . push ( `Additive Multipliers: Damage=${ damageAdditiveMulti . toFixed ( 3 ) } (1 + ${ this . mountDamageMulti . toFixed ( 3 ) } + ${ this . secondaryStats . damageMulti . toFixed ( 3 ) } )` ) ;
10811081 this . debugLogs . push ( `Additive Multipliers: Health=${ healthAdditiveMulti . toFixed ( 3 ) } (1 + ${ this . mountHealthMulti . toFixed ( 3 ) } + ${ this . secondaryStats . healthMulti . toFixed ( 3 ) } )` ) ;
10821082
1083- const damageAfterAdditive = flatDamageWithMelee * damageAdditiveMulti ;
1084- const healthAfterAdditive = flatHealth * healthAdditiveMulti ;
1083+ // 5. Distinct Multipliers: Skin and Sets
1084+ // These are applied fully multiplicatively to the result to avoid dilution
1085+ const skinDmgFactor = 1 + this . skinDamageMulti ;
1086+ const skinHpFactor = 1 + this . skinHealthMulti ;
10851087
1086- // 5. MeleeDamageMulti is applied MULTIPLICATIVELY (only for melee weapons)
1087- // RangedDamageMulti is applied MULTIPLICATIVELY (only for ranged weapons)
1088+ const setDmgFactor = 1 + this . setDamageMulti ;
1089+ const setHpFactor = 1 + this . setHealthMulti ;
1090+
1091+ this . debugLogs . push ( `Skin Factor: Dmg=${ skinDmgFactor . toFixed ( 3 ) } , Hp=${ skinHpFactor . toFixed ( 3 ) } ` ) ;
1092+ this . debugLogs . push ( `Set Factor: Dmg=${ setDmgFactor . toFixed ( 3 ) } , Hp=${ setHpFactor . toFixed ( 3 ) } ` ) ;
1093+
1094+ const damageAfterGlobalMultis = flatDamageWithMelee * damageAdditiveMulti * skinDmgFactor * setDmgFactor ;
1095+ const healthAfterGlobalMultis = flatHealth * healthAdditiveMulti * skinHpFactor * setHpFactor ;
1096+
1097+ // 6. Melee/Ranged Specific Multipliers (Multiplicative)
10881098 const specificDamageMulti = isWeaponMelee
10891099 ? ( 1 + this . secondaryStats . meleeDamageMulti )
10901100 : ( 1 + this . secondaryStats . rangedDamageMulti ) ;
10911101
1092- const finalDamage = damageAfterAdditive * specificDamageMulti ;
1102+ const finalDamage = damageAfterGlobalMultis * specificDamageMulti ;
10931103
10941104 this . debugLogs . push ( `After SpecificMulti (×${ specificDamageMulti . toFixed ( 3 ) } ): Damage=${ finalDamage . toFixed ( 0 ) } ` ) ;
10951105
1096- // 6 . Final stats (no empirical corrections applied)
1106+ // 7 . Final stats
10971107 this . stats . totalDamage = finalDamage ;
1098- this . stats . totalHealth = healthAfterAdditive ;
1108+ this . stats . totalHealth = healthAfterGlobalMultis ;
10991109
11001110 // Store multipliers for display
1111+ // We report the 'base' keys as just the additive parts correctly.
11011112 this . stats . damageMultiplier = damageAdditiveMulti ;
11021113 this . stats . healthMultiplier = healthAdditiveMulti ;
11031114 this . stats . secondaryDamageMulti = this . secondaryStats . damageMulti ;
@@ -1110,8 +1121,9 @@ export class StatEngine {
11101121 const flatDamageNoMelee = this . stats . basePlayerDamage + this . stats . itemDamage + this . stats . petDamage ;
11111122
11121123 // Melee/Ranged specific damage (for display)
1113- this . stats . meleeDamage = isWeaponMelee ? this . stats . totalDamage : ( flatDamageWithMelee * damageAdditiveMulti * ( 1 + this . secondaryStats . meleeDamageMulti ) ) ;
1114- this . stats . rangedDamage = ! isWeaponMelee ? this . stats . totalDamage : ( flatDamageNoMelee * damageAdditiveMulti * ( 1 + this . secondaryStats . rangedDamageMulti ) ) ;
1124+ const globalDmgFactor = damageAdditiveMulti * skinDmgFactor * setDmgFactor ;
1125+ this . stats . meleeDamage = isWeaponMelee ? this . stats . totalDamage : ( flatDamageWithMelee * globalDmgFactor * ( 1 + this . secondaryStats . meleeDamageMulti ) ) ;
1126+ this . stats . rangedDamage = ! isWeaponMelee ? this . stats . totalDamage : ( flatDamageNoMelee * globalDmgFactor * ( 1 + this . secondaryStats . rangedDamageMulti ) ) ;
11151127
11161128 // Power calculation - GHIDRA REVERSE ENGINEERED FORMULA (VERIFIED):
11171129 // Power = ((Damage - 10) × 8 + (Health - 80)) × 3
@@ -1120,7 +1132,7 @@ export class StatEngine {
11201132 const baseDmg = this . stats . basePlayerDamage ; // 10.0 from config
11211133 const baseHp = this . stats . basePlayerHealth ; // 80.0 from config
11221134
1123- const basePower = ( ( finalDamage - baseDmg ) * powerDmgMulti + ( healthAfterAdditive - baseHp ) ) * 3 ;
1135+ const basePower = ( ( finalDamage - baseDmg ) * powerDmgMulti + ( healthAfterGlobalMultis - baseHp ) ) * 3 ;
11241136 this . stats . power = Math . round ( basePower ) ; // Game uses RoundToInt128
11251137
11261138
@@ -1193,7 +1205,10 @@ export class StatEngine {
11931205
11941206 const effectiveMultiplier = skillMulti + globalDamageMulti - 1 - mountMulti ;
11951207
1196- const dmgPerHit = flatSkillDmg * effectiveMultiplier * statMultiplier ;
1208+ // Apply Skin and Set Multipliers to Skills as well
1209+ const skinFactor = 1 + this . skinDamageMulti ;
1210+ const setFactor = 1 + this . setDamageMulti ;
1211+ const dmgPerHit = flatSkillDmg * effectiveMultiplier * statMultiplier * skinFactor * setFactor ;
11971212
11981213 this . stats . skillDps += dmgPerHit / finalCd ;
11991214 }
0 commit comments