import { describe, expect, it } from "vitest"; import { enemySourceAuraContract } from "./enemySourceAuras"; import { canEnemyNpcBlock, canEnemyNpcBlockSpell, classifyEnemyNpcSpellBlockPhase, CREATURE_FLAG_EXTRA_NO_BLOCK, enemyNpcSourceSpellBlockMetadata, enemyNpcBlockChanceAfterSkill, enemyNpcSpellBlockChanceAfterSkill, resolveEnemyNpcBlockStats, SPELL_ATTR0_CU_DIRECT_DAMAGE, SPELL_ATTR0_CU_BLOCKING_KNOWN_MASK, SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET, SPELL_ATTR0_NO_ACTIVE_DEFENSE, SPELL_ATTR3_ALWAYS_HIT, SPELL_ATTR3_COMPLETELY_BLOCKED, SPELL_DAMAGE_CLASS_MAGIC, SPELL_DAMAGE_CLASS_MELEE, SPELL_DAMAGE_CLASS_RANGED, SPELL_SCHOOL_MASK_NORMAL, } from "./enemyBlocking"; const baseWeaponInput = { attack: "melee-auto" as const, blockPercent: 5, flagsExtra: 0, isTotem: false, attackerLevel: 80, defenderLevel: 80, attackerIsBehind: false, ignoresHitDirection: false, isCastingNonMeleeSpell: false, isControlled: false, isEvadingAttacks: false, }; const physicalDirectSpell = { damageClass: SPELL_DAMAGE_CLASS_MELEE, schoolMask: SPELL_SCHOOL_MASK_NORMAL, attributes0: 0, attributes3: 0, directDamageFromEffects: true, sourceProfile: "wow335" as const, }; const baseSpellInput = { spell: physicalDirectSpell, blockPercent: 5, flagsExtra: 0, isTotem: false, attackerWeaponSkill: 400, defenderLevel: 80, attackerIsBehind: false, ignoresHitDirection: false, isCastingNonMeleeSpell: false, isControlled: false, }; describe("source-backed enemy NPC blocking", () => { it("uses the ordinary-creature base chance and inherent level-only block value", () => { expect(resolveEnemyNpcBlockStats({ level: 79, blockChanceAuraPercent: 0, isTotem: false, })).toEqual({ blockPercent: 5, blockValue: 39 }); }); it("adds Improved Blocking's sourced 75 percentage points in both profiles", () => { for (const profile of ["ascension", "epoch"] as const) { const contract = enemySourceAuraContract(3419, profile); expect(contract?.durationMs).toBe(6_000); expect(contract?.signature.effects).toContainEqual(expect.objectContaining({ auraType: 51, basePoints: 75, })); expect(resolveEnemyNpcBlockStats({ level: 60, blockChanceAuraPercent: contract!.signature.effects[0]!.basePoints, isTotem: false, })).toEqual({ blockPercent: 80, blockValue: 30 }); } }); it("keeps totems at zero block chance and clamps negative aura totals", () => { expect(resolveEnemyNpcBlockStats({ level: 60, blockChanceAuraPercent: 75, isTotem: true, })).toEqual({ blockPercent: 0, blockValue: 30 }); expect(resolveEnemyNpcBlockStats({ level: 60, blockChanceAuraPercent: -10, isTotem: false, })?.blockPercent).toBe(0); }); it("fails closed outside the simulator level cap or for unsourced numeric inputs", () => { expect(resolveEnemyNpcBlockStats({ level: 81, blockChanceAuraPercent: 75, isTotem: false, })).toBeNull(); expect(resolveEnemyNpcBlockStats({ level: 60, blockChanceAuraPercent: Number.NaN, isTotem: false, })).toBeNull(); expect(enemyNpcBlockChanceAfterSkill({ blockPercent: 5, attackerLevel: 81, defenderLevel: 80 })).toBeNull(); }); it("gates creature no-block, rear, casting, controlled, evading, and nonpositive skill-adjusted chances", () => { expect(canEnemyNpcBlock({ ...baseWeaponInput, flagsExtra: CREATURE_FLAG_EXTRA_NO_BLOCK })).toBe(false); expect(canEnemyNpcBlock({ ...baseWeaponInput, attackerIsBehind: true })).toBe(false); expect(canEnemyNpcBlock({ ...baseWeaponInput, isCastingNonMeleeSpell: true })).toBe(false); expect(canEnemyNpcBlock({ ...baseWeaponInput, isControlled: true })).toBe(false); expect(canEnemyNpcBlock({ ...baseWeaponInput, isEvadingAttacks: true })).toBe(false); expect(canEnemyNpcBlock({ ...baseWeaponInput, attackerLevel: 81 })).toBe(false); expect(canEnemyNpcBlock({ ...baseWeaponInput, isTotem: true })).toBe(false); }); it("allows ranged weapon blocks and applies the sourced four-hundredths skill adjustment", () => { expect(canEnemyNpcBlock({ ...baseWeaponInput, attack: "ranged-auto", })).toBe(true); expect(enemyNpcBlockChanceAfterSkill({ blockPercent: 80, attackerLevel: 70, defenderLevel: 80 })).toBe(82); expect(enemyNpcBlockChanceAfterSkill({ blockPercent: 80, attackerLevel: 80, defenderLevel: 70 })).toBe(78); expect(enemyNpcBlockChanceAfterSkill({ blockPercent: 5, attackerLevel: 80, defenderLevel: 55 })).toBe(0); expect(enemyNpcBlockChanceAfterSkill({ blockPercent: 0, attackerLevel: 1, defenderLevel: 80 })).toBe(0); }); it("fails closed for spell and other packets until spell attributes are imported", () => { expect(canEnemyNpcBlock({ ...baseWeaponInput, attack: "spell" })).toBe(false); expect(canEnemyNpcBlock({ ...baseWeaponInput, attack: "other" })).toBe(false); }); it("classifies source-backed physical direct-damage melee and ranged spells for post-hit blocking", () => { expect(classifyEnemyNpcSpellBlockPhase(physicalDirectSpell)).toBe("direct-damage"); expect(classifyEnemyNpcSpellBlockPhase({ ...physicalDirectSpell, damageClass: SPELL_DAMAGE_CLASS_RANGED, sourceProfile: "ascension", })).toBe("direct-damage"); expect(classifyEnemyNpcSpellBlockPhase({ ...physicalDirectSpell, damageClass: SPELL_DAMAGE_CLASS_MAGIC, })).toBe("none"); expect(classifyEnemyNpcSpellBlockPhase({ ...physicalDirectSpell, schoolMask: 0x10, })).toBe("none"); expect(classifyEnemyNpcSpellBlockPhase({ ...physicalDirectSpell, attributes0: SPELL_ATTR0_NO_ACTIVE_DEFENSE, })).toBe("none"); expect(classifyEnemyNpcSpellBlockPhase({ ...physicalDirectSpell, attributes3: SPELL_ATTR3_ALWAYS_HIT, })).toBe("none"); }); it("requires explicit AzerothCore custom attributes before enabling a hit-table full block", () => { const nonDirect = { ...physicalDirectSpell, directDamageFromEffects: false, attributes3: SPELL_ATTR3_COMPLETELY_BLOCKED, }; expect(classifyEnemyNpcSpellBlockPhase(nonDirect)).toBe("none"); expect(classifyEnemyNpcSpellBlockPhase({ ...nonDirect, customAttributes: 0 })).toBe("hit-table"); expect(classifyEnemyNpcSpellBlockPhase({ ...nonDirect, damageClass: SPELL_DAMAGE_CLASS_MAGIC, customAttributes: 0, })).toBe("none"); expect(classifyEnemyNpcSpellBlockPhase({ ...nonDirect, attributes0: SPELL_ATTR0_NO_ACTIVE_DEFENSE, customAttributes: 0, })).toBe("none"); expect(classifyEnemyNpcSpellBlockPhase({ ...nonDirect, attributes3: SPELL_ATTR3_COMPLETELY_BLOCKED | SPELL_ATTR3_ALWAYS_HIT, customAttributes: 0, })).toBe("none"); expect(classifyEnemyNpcSpellBlockPhase({ ...nonDirect, customAttributes: SPELL_ATTR0_CU_DIRECT_DAMAGE, })).toBe("direct-damage"); expect(classifyEnemyNpcSpellBlockPhase({ ...nonDirect, customAttributes: -1 })).toBeNull(); expect(classifyEnemyNpcSpellBlockPhase({ ...physicalDirectSpell, sourceProfile: "epoch" as never })).toBeNull(); }); it("uses only the two source-proven custom bits for the three exact utility ranks", () => { const shieldBash = enemyNpcSourceSpellBlockMetadata(72, "wow335"); expect(shieldBash).toMatchObject({ damageClass: SPELL_DAMAGE_CLASS_MELEE, schoolMask: SPELL_SCHOOL_MASK_NORMAL, attributes0: 327696, attributes3: SPELL_ATTR3_COMPLETELY_BLOCKED, directDamageFromEffects: false, sourceProfile: "wow335", customAttributeEvidence: { knownMask: SPELL_ATTR0_CU_BLOCKING_KNOWN_MASK, value: 0 }, }); expect(classifyEnemyNpcSpellBlockPhase(shieldBash!)).toBe("hit-table"); expect(canEnemyNpcBlockSpell({ ...baseSpellInput, spell: shieldBash!, attackerIsBehind: true, ignoresHitDirection: true, })).toBe(true); expect(enemyNpcSourceSpellBlockMetadata(72, "ascension")).toBeUndefined(); expect(enemyNpcSourceSpellBlockMetadata(1766, "wow335")).toEqual(shieldBash); expect(enemyNpcSourceSpellBlockMetadata(6552, "wow335")).toEqual(shieldBash); expect(enemyNpcSourceSpellBlockMetadata(5246, "wow335")).toBeUndefined(); const unknownBehindBit = { ...shieldBash!, customAttributeEvidence: { knownMask: SPELL_ATTR0_CU_DIRECT_DAMAGE, value: 0 }, }; expect(classifyEnemyNpcSpellBlockPhase(unknownBehindBit)).toBe("hit-table"); expect(canEnemyNpcBlockSpell({ ...baseSpellInput, spell: unknownBehindBit, attackerIsBehind: true, ignoresHitDirection: true, })).toBe(false); expect(classifyEnemyNpcSpellBlockPhase({ ...shieldBash!, customAttributes: 0, customAttributeEvidence: { knownMask: SPELL_ATTR0_CU_BLOCKING_KNOWN_MASK, value: 0 }, })).toBe("hit-table"); expect(classifyEnemyNpcSpellBlockPhase({ ...shieldBash!, customAttributes: SPELL_ATTR0_CU_DIRECT_DAMAGE, customAttributeEvidence: { knownMask: SPELL_ATTR0_CU_BLOCKING_KNOWN_MASK, value: 0 }, })).toBeNull(); }); it("uses the different source skill signs for hit-table and post-hit spell blocks", () => { expect(enemyNpcSpellBlockChanceAfterSkill({ phase: "direct-damage", blockPercent: 5, attackerWeaponSkill: 450, defenderLevel: 80, })).toBe(7); expect(enemyNpcSpellBlockChanceAfterSkill({ phase: "hit-table", blockPercent: 5, attackerWeaponSkill: 450, defenderLevel: 80, })).toBe(3); expect(enemyNpcSpellBlockChanceAfterSkill({ phase: "direct-damage", blockPercent: 5, attackerWeaponSkill: 200, defenderLevel: 80, })).toBe(0); expect(enemyNpcSpellBlockChanceAfterSkill({ phase: "hit-table", blockPercent: 5, attackerWeaponSkill: 600, defenderLevel: 80, })).toBe(0); expect(enemyNpcSpellBlockChanceAfterSkill({ phase: "direct-damage", blockPercent: 0, attackerWeaponSkill: 450, defenderLevel: 80, })).toBe(2); expect(enemyNpcSpellBlockChanceAfterSkill({ phase: "hit-table", blockPercent: 0, attackerWeaponSkill: 350, defenderLevel: 80, })).toBe(2); }); it("applies direct-spell no-block, direction, cast, control, and skill gates", () => { expect(canEnemyNpcBlockSpell(baseSpellInput)).toBe(true); expect(canEnemyNpcBlockSpell({ ...baseSpellInput, flagsExtra: CREATURE_FLAG_EXTRA_NO_BLOCK })).toBe(false); expect(canEnemyNpcBlockSpell({ ...baseSpellInput, isTotem: true })).toBe(false); expect(canEnemyNpcBlockSpell({ ...baseSpellInput, attackerIsBehind: true })).toBe(false); expect(canEnemyNpcBlockSpell({ ...baseSpellInput, attackerIsBehind: true, ignoresHitDirection: true })).toBe(true); expect(canEnemyNpcBlockSpell({ ...baseSpellInput, isCastingNonMeleeSpell: true })).toBe(false); expect(canEnemyNpcBlockSpell({ ...baseSpellInput, isControlled: true })).toBe(false); expect(canEnemyNpcBlockSpell({ ...baseSpellInput, attackerWeaponSkill: 200 })).toBe(false); expect(canEnemyNpcBlockSpell({ ...baseSpellInput, blockPercent: 0, attackerWeaponSkill: 450, })).toBe(true); }); it("keeps hit-table spell direction exceptions and requires-behind attribute semantics", () => { const hitTableSpell = { damageClass: SPELL_DAMAGE_CLASS_MELEE, schoolMask: SPELL_SCHOOL_MASK_NORMAL, attributes0: 0, attributes3: SPELL_ATTR3_COMPLETELY_BLOCKED, directDamageFromEffects: false, sourceProfile: "wow335" as const, customAttributes: 0, }; expect(canEnemyNpcBlockSpell({ ...baseSpellInput, spell: hitTableSpell })).toBe(true); expect(canEnemyNpcBlockSpell({ ...baseSpellInput, spell: hitTableSpell, attackerIsBehind: true, ignoresHitDirection: true, })).toBe(true); expect(canEnemyNpcBlockSpell({ ...baseSpellInput, spell: { ...hitTableSpell, customAttributes: SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET }, attackerIsBehind: true, ignoresHitDirection: true, })).toBe(false); }); });