/** * Adversarial Stress & Edge Case Verification Suite — Paladin Offensive Auras (10 Skills). * * 5 Critical Edge Scenarios: * 1. Conviction Immunity-Breaking Thresholds (100%, 110%, 140%, 160% resistance; zero poison/magic pierce) * 2. Sanctuary vs Physical Immune Undead (0% effective phys res on Undead; living/demons untouched) * 3. Thorns Overkill & PvP 1/4th Penalty (10,000 dmg, monster mitigation, PvP 75% cut, 0 on immune) * 4. Holy Freeze CBF Bypass & 2:1 Isometric Geometry (dx=100, dy=50 in range vs dx=100, dy=100 out) * 5. Fanaticism Asymmetric Party Scaling & Rapid Aura Switching (1 Pal + 3 allies, 100 frame swap loop) */ import { describe, expect, it } from 'vitest' import { getSharedDataRegistry } from '../../../src/baker/mpq-archive-source.ts' import { FIXED_ONE, UnitStatList } from '../../../src/server/engine/stat-list.ts' import { StateBus } from '../../../src/server/engine/state-bus.ts' import { AuraScanner } from '../../../src/server/engine/aura-scanner.ts' import { computeEffectiveResistance, executeSUnitDmg, type CombatUnitContext, } from '../../../src/server/engine/combat-pipeline.ts' describe('Paladin Offensive Auras — Adversarial Stress & Edge Cases', () => { // -------------------------------------------------------------------------- // Scenario 1: Conviction Immunity-Breaking Thresholds // -------------------------------------------------------------------------- it('Scenario 1: Conviction breaking thresholds (100%, 110%, 140%, 160%) and Poison/Magic exclusion', async () => { const registry = await getSharedDataRegistry() const palStats = new UnitStatList(registry, { maxhp: 1000 * FIXED_ONE, hitpoints: 1000 * FIXED_ONE }) const paladin: CombatUnitContext = { id: 'paladin', name: 'Paladin', statList: palStats, stateBus: new StateBus(palStats, registry), unitType: 'player', } // Slvl 25 Conviction has -150% uncapped elemental resistance reduction // Against immunities (baseRes >= 100%), applies at 1/5th effectiveness = -30% const pierce25 = 150 // 1. Monster with 100% Fire Resistance const res100 = computeEffectiveResistance({ baseRes: 100, convictionPierce: pierce25 }) expect(res100.isImmune).toBe(false) expect(res100.effectiveRes).toBe(70) // 100 - 30 = 70% // 2. Monster with 110% Lightning Resistance const res110 = computeEffectiveResistance({ baseRes: 110, convictionPierce: pierce25 }) expect(res110.isImmune).toBe(false) expect(res110.effectiveRes).toBe(80) // 110 - 30 = 80% // 3. Monster with 140% Cold Resistance (Unbreakable!) const res140 = computeEffectiveResistance({ baseRes: 140, convictionPierce: pierce25 }) expect(res140.isImmune).toBe(true) expect(res140.effectiveRes).toBe(100) // 140 - 30 = 110% >= 100 -> Remains Immune! // 4. Monster with 160% Fire Resistance (Unbreakable!) const res160 = computeEffectiveResistance({ baseRes: 160, convictionPierce: pierce25 }) expect(res160.isImmune).toBe(true) expect(res160.effectiveRes).toBe(100) // 5. Conviction NEVER impacts Poison or Magic Resistance const monsterStats = new UnitStatList(registry, { maxhp: 1000 * FIXED_ONE, hitpoints: 1000 * FIXED_ONE, poisonresist: 50, magicresist: 50, }) const monsterBus = new StateBus(monsterStats, registry) monsterBus.applyState({ stateNameOrId: 'conviction', slvl: 25, stats: { conviction_pierce: 150, item_armor_percent: -90 }, }) const monster: CombatUnitContext = { id: 'monster_pois_mag', name: 'Target', statList: monsterStats, stateBus: monsterBus, unitType: 'monster', } // Poison attack with Conviction on defender const poisOut = executeSUnitDmg(paladin, monster, { skillId: 0, attackKind: 'melee', elemType: 'pois', elemMin256: 100 * FIXED_ONE, elemMax256: 100 * FIXED_ONE, autoHit: true, }) // 50% poison resistance applies in full -> 50 damage taken (NOT pierced by Conviction!) expect(poisOut.elemDamage256).toBe(50 * FIXED_ONE) // Magic attack with Conviction on defender const magOut = executeSUnitDmg(paladin, monster, { skillId: 0, attackKind: 'spell', elemType: 'mag', elemMin256: 100 * FIXED_ONE, elemMax256: 100 * FIXED_ONE, autoHit: true, }) // 50% magic resistance applies in full -> 50 damage taken (NOT pierced by Conviction!) expect(magOut.elemDamage256).toBe(50 * FIXED_ONE) }) // -------------------------------------------------------------------------- // Scenario 2: Sanctuary vs Physical Immune Undead // -------------------------------------------------------------------------- it('Scenario 2: Sanctuary pierces 100% and 150% Physical Immune Undead while leaving living/demons immune', async () => { const registry = await getSharedDataRegistry() const palStats = new UnitStatList(registry, { maxhp: 1000 * FIXED_ONE, hitpoints: 1000 * FIXED_ONE }) const palBus = new StateBus(palStats, registry) palBus.applyState({ stateNameOrId: 'sanctuary', slvl: 10 }) // +420% ED vs Undead const paladin: CombatUnitContext = { id: 'paladin', name: 'Paladin', statList: palStats, stateBus: palBus, unitType: 'player', weaponMinPhys: 100, weaponMaxPhys: 100, } // 1. Ghost (100% Physical Immune Undead) const ghostStats = new UnitStatList(registry, { maxhp: 5000 * FIXED_ONE, hitpoints: 5000 * FIXED_ONE, damageresist: 100 }) const ghost: CombatUnitContext = { id: 'ghost_100', name: 'Ghost (100% Phys Res)', statList: ghostStats, stateBus: new StateBus(ghostStats, registry), unitType: 'monster', isUndead: true, } const outGhost100 = executeSUnitDmg(paladin, ghost, { skillId: 0, attackKind: 'melee', autoHit: true }) expect(outGhost100.immuneToPhys).toBe(false) // 100 base * (100 + 420)% = 520 physical damage dealt with 0% resistance! expect(outGhost100.physDamage256).toBe(520 * FIXED_ONE) // 2. Stone Skin Ghost (150% Physical Immune Undead) const stoneSkinGhostStats = new UnitStatList(registry, { maxhp: 5000 * FIXED_ONE, hitpoints: 5000 * FIXED_ONE, damageresist: 150 }) const stoneSkinGhost: CombatUnitContext = { id: 'ghost_150', name: 'Stone Skin Ghost (150% Phys Res)', statList: stoneSkinGhostStats, stateBus: new StateBus(stoneSkinGhostStats, registry), unitType: 'monster', isUndead: true, } const outGhost150 = executeSUnitDmg(paladin, stoneSkinGhost, { skillId: 0, attackKind: 'melee', autoHit: true }) expect(outGhost150.immuneToPhys).toBe(false) expect(outGhost150.physDamage256).toBe(520 * FIXED_ONE) // 3. Stone Skin Demon (100% Phys Res, isDemon: true, isUndead: false) -> Sanctuary does NOT pierce! const demonStats = new UnitStatList(registry, { maxhp: 5000 * FIXED_ONE, hitpoints: 5000 * FIXED_ONE, damageresist: 100 }) const demon: CombatUnitContext = { id: 'demon_100', name: 'Demon (100% Phys Res)', statList: demonStats, stateBus: new StateBus(demonStats, registry), unitType: 'monster', isDemon: true, isUndead: false, } const outDemon = executeSUnitDmg(paladin, demon, { skillId: 0, attackKind: 'melee', autoHit: true }) expect(outDemon.immuneToPhys).toBe(true) expect(outDemon.physDamage256).toBe(0) }) // -------------------------------------------------------------------------- // Scenario 3: Thorns Overkill & PvP 1/4th Penalty // -------------------------------------------------------------------------- it('Scenario 3: Thorns massive overkill reflection, attacker physical resistance, and PvP 1/4th penalty', async () => { const registry = await getSharedDataRegistry() // Defender with Slvl 20 Thorns (1010% reflection) const defStats = new UnitStatList(registry, { maxhp: 50000 * FIXED_ONE, hitpoints: 50000 * FIXED_ONE, damageresist: 0 }) const defBus = new StateBus(defStats, registry) defBus.applyState({ stateNameOrId: 'thorns', slvl: 20 }) const paladinDef: CombatUnitContext = { id: 'paladin_thorns', name: 'Thorns Paladin', statList: defStats, stateBus: defBus, unitType: 'player', } // 1. Monster attacks for 10,000 melee physical damage const atkStats = new UnitStatList(registry, { maxhp: 200000 * FIXED_ONE, hitpoints: 200000 * FIXED_ONE, damageresist: 0 }) const monsterAtk: CombatUnitContext = { id: 'massive_monster', name: 'Massive Monster', statList: atkStats, stateBus: new StateBus(atkStats, registry), unitType: 'monster', weaponMinPhys: 10000, weaponMaxPhys: 10000, } const outMassive = executeSUnitDmg(monsterAtk, paladinDef, { skillId: 0, attackKind: 'melee', autoHit: true }) // 10,000 * 1010% = 101,000 physical damage reflected! expect(outMassive.reflectedPhys256).toBe(101000 * FIXED_ONE) expect(monsterAtk.statList.getHp256()).toBe((200000 - 101000) * FIXED_ONE) // 2. PvP Penalty: Player attacker attacks for 10,000 damage const playerAtkStats = new UnitStatList(registry, { maxhp: 200000 * FIXED_ONE, hitpoints: 200000 * FIXED_ONE, damageresist: 0 }) const playerAtk: CombatUnitContext = { id: 'player_atk', name: 'Player Attacker', statList: playerAtkStats, stateBus: new StateBus(playerAtkStats, registry), unitType: 'player', weaponMinPhys: 10000, weaponMaxPhys: 10000, } const outPvP = executeSUnitDmg(playerAtk, paladinDef, { skillId: 0, attackKind: 'melee', autoHit: true }) // In PvP, 1/4th penalty applies: Math.trunc(101,000 / 4) = 25,250 reflected! expect(outPvP.reflectedPhys256).toBe(25250 * FIXED_ONE) // 3. Physical Immune Attacker: Takes strictly 0 reflected damage! const immuneAtkStats = new UnitStatList(registry, { maxhp: 50000 * FIXED_ONE, hitpoints: 50000 * FIXED_ONE, damageresist: 100 }) const immuneAtk: CombatUnitContext = { id: 'immune_atk', name: 'Physical Immune Attacker', statList: immuneAtkStats, stateBus: new StateBus(immuneAtkStats, registry), unitType: 'monster', weaponMinPhys: 1000, weaponMaxPhys: 1000, } const outImmune = executeSUnitDmg(immuneAtk, paladinDef, { skillId: 0, attackKind: 'melee', autoHit: true }) expect(outImmune.reflectedPhys256).toBeUndefined() expect(immuneAtk.statList.getHp256()).toBe(50000 * FIXED_ONE) }) // -------------------------------------------------------------------------- // Scenario 4: Holy Freeze CBF Bypass & 2:1 Isometric Geometry // -------------------------------------------------------------------------- it('Scenario 4: Holy Freeze CBF bypass and 2:1 isometric ground space range check', async () => { const registry = await getSharedDataRegistry() const scanner = new AuraScanner(registry) // Paladin at origin (0, 0) const palStats = new UnitStatList(registry, { maxhp: 1000 * FIXED_ONE, hitpoints: 1000 * FIXED_ONE }) const paladin: CombatUnitContext = { id: 'paladin', name: 'Paladin', statList: palStats, stateBus: new StateBus(palStats, registry), unitType: 'player', x: 0, y: 0, } // Enemy 1: In range in 2:1 iso ground space: (dx=100, dy=50) // Math.hypot(100, 50 * 2) = Math.hypot(100, 100) = 141.42 <= 200 const e1Stats = new UnitStatList(registry, { maxhp: 1000 * FIXED_ONE, hitpoints: 1000 * FIXED_ONE, cannot_be_frozen: 1 }) const enemy1: CombatUnitContext = { id: 'enemy_in_range', name: 'In Range CBF Enemy', statList: e1Stats, stateBus: new StateBus(e1Stats, registry), unitType: 'monster', x: 100, y: 50, } // Enemy 2: Out of range in 2:1 iso ground space: (dx=100, dy=100) // Math.hypot(100, 100 * 2) = Math.hypot(100, 200) = 223.6 > 200 const e2Stats = new UnitStatList(registry, { maxhp: 1000 * FIXED_ONE, hitpoints: 1000 * FIXED_ONE, cannot_be_frozen: 1 }) const enemy2: CombatUnitContext = { id: 'enemy_out_of_range', name: 'Out of Range CBF Enemy', statList: e2Stats, stateBus: new StateBus(e2Stats, registry), unitType: 'monster', x: 100, y: 100, } // Slvl 10 Holy Freeze: radiusSubtiles = 15 -> radiusPx = Math.round(15 * 40/3) = 200 px const auraSource = scanner.setActiveAura(paladin, 114, 10)! expect(auraSource).toBeDefined() scanner.pulseAura(auraSource, 0, [paladin], [enemy1, enemy2]) // Enemy 1 is in range and slowed (bypassing CBF!) expect(enemy1.stateBus.hasState('holywindcold')).toBe(true) expect(enemy1.statList.getModifierBonus('item_slow')).toBe(46) // Enemy 2 is out of range and NOT affected expect(enemy2.stateBus.hasState('holywindcold')).toBe(false) expect(enemy2.statList.getModifierBonus('item_slow')).toBe(0) }) // -------------------------------------------------------------------------- // Scenario 5: Fanaticism Asymmetric Party Scaling & Rapid Aura Switching // -------------------------------------------------------------------------- it('Scenario 5: Fanaticism asymmetric party scaling and rapid aura switching stability', async () => { const registry = await getSharedDataRegistry() const scanner = new AuraScanner(registry) // Paladin Caster const palStats = new UnitStatList(registry, { maxhp: 1000 * FIXED_ONE, hitpoints: 1000 * FIXED_ONE }) const paladin: CombatUnitContext = { id: 'paladin', name: 'Paladin', statList: palStats, stateBus: new StateBus(palStats, registry), unitType: 'player', weaponMinPhys: 100, weaponMaxPhys: 100, } // 3 Allies const allies: CombatUnitContext[] = [1, 2, 3].map(i => { const s = new UnitStatList(registry, { maxhp: 1000 * FIXED_ONE, hitpoints: 1000 * FIXED_ONE }) return { id: `ally_${i}`, name: `Ally ${i}`, statList: s, stateBus: new StateBus(s, registry), unitType: 'party', weaponMinPhys: 100, weaponMaxPhys: 100, } }) // Activate Slvl 20 Fanaticism (Caster: 373% ED, Allies: 186% ED) const fanatAura = scanner.setActiveAura(paladin, 122, 20)! scanner.pulseAura(fanatAura, 0, [paladin, ...allies], []) // Asserts Paladin receives full %ED (373%) and allies receive exactly half %ED (186%) expect(paladin.stateBus.hasState('fanaticism')).toBe(true) for (const ally of allies) { expect(ally.stateBus.hasState('fanaticism')).toBe(true) expect(ally.statList.getModifierBonus('damagepercent')).toBe(186) } // Simulate switching between Fanaticism (122), Conviction (123), and Might (98) over 100 consecutive frames const auraCycle = [122, 123, 98] for (let frame = 1; frame <= 100; frame++) { const nextAuraId = auraCycle[frame % 3]! scanner.clearUnitAuras(paladin.id) paladin.stateBus.removeState('fanaticism') paladin.stateBus.removeState('conviction') paladin.stateBus.removeState('might') for (const ally of allies) { ally.stateBus.removeState('fanaticism') ally.stateBus.removeState('conviction') ally.stateBus.removeState('might') } const active = scanner.setActiveAura(paladin, nextAuraId, 10, frame)! scanner.pulseAura(active, frame, [paladin, ...allies], []) } // Final state check: last frame (100 % 3 = 1 -> Conviction 123) // Paladin must have active Conviction visual without debuff expect(paladin.stateBus.hasState('conviction')).toBe(true) expect(paladin.statList.getModifierBonus('item_armor_percent')).toBe(0) expect(paladin.statList.getModifierBonus('conviction_pierce')).toBe(0) // No lingering Fanaticism or Might modifiers remain expect(paladin.stateBus.hasState('fanaticism')).toBe(false) expect(paladin.stateBus.hasState('might')).toBe(false) for (const ally of allies) { expect(ally.stateBus.hasState('fanaticism')).toBe(false) expect(ally.stateBus.hasState('might')).toBe(false) expect(ally.statList.getModifierBonus('damagepercent')).toBe(0) } }) })