import { beforeEach, describe, expect, it } from "vitest"; import { PLAYER_AGGRO_ID } from "./aggro"; import { DEFAULT_ENEMY_ATTACK } from "./enemyAttacks"; import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry"; import { clearPartyRuntimeRegistry, registerPartyRuntimePosition } from "./partyRuntimeRegistry"; import { EMPTY_ITEM_STATS } from "./itemStats"; import { usePartyStore, createConfiguredPartyMember } from "./partyStore"; import { useCombatStore } from "./combatStore"; import { deriveCharacterStats } from "./wotlkStats"; import { WOW335_WARRIOR_DAMAGE_SHIELD_ABILITY_ID, WOW335_WARRIOR_DAMAGE_SHIELD_TALENT_ID, wow335WarriorDamageShieldReflectDamage, } from "./wow335WarriorDamageShieldRuntime"; function registerAttacker(id: string, targetActorId: string): void { useCombatStore.getState().registerMob(id, { name: id, level: 80, maxHealth: 100_000, xpReward: 0, attacks: [{ ...DEFAULT_ENEMY_ATTACK, damageMultiplier: 2 }], }); setMobPosition(id, [2, 0, 0]); useCombatStore.getState().damageMob(id, 1, 100, { actorId: targetActorId, role: "tank", }, "physical"); } function reflectedEvent(targetId: string, sourceActorId: string) { return useCombatStore.getState().combatEvents.find((event) => ( event.abilityId === WOW335_WARRIOR_DAMAGE_SHIELD_ABILITY_ID && event.sourceActorId === sourceActorId && event.targetActorId === targetId )); } describe("WoW 3.3.5 Warrior Damage Shield combat hooks", () => { beforeEach(() => { clearMobRuntimeRegistry(); clearPartyRuntimeRegistry(); useCombatStore.getState().initializeCharacter({ classId: "mage", level: 80 }); usePartyStore.getState().initializeParty("damage-shield-tests", 80, useCombatStore.getState().health, "damage", 1); }); it("reflects rank-scaled block value after a landed direct melee hit on the player", () => { useCombatStore.getState().initializeCharacter({ classId: "warrior", level: 80, role: "tank" }); useCombatStore.setState((state) => ({ gearStats: { ...EMPTY_ITEM_STATS, blockValue: 1_000 }, talentRanks: { ...state.talentRanks, [WOW335_WARRIOR_DAMAGE_SHIELD_TALENT_ID]: 2 }, })); usePartyStore.getState().initializeParty("damage-shield-player", 80, useCombatStore.getState().health, "tank", 1); registerAttacker("damage-shield-player-target", PLAYER_AGGRO_ID); useCombatStore.getState().advanceMobCombat(1_000); const state = useCombatStore.getState(); const blockValue = deriveCharacterStats( state.classId, state.level, state.gearStats, state.raceId, undefined, state.secondaryClassId, ).blockValue; expect(useCombatStore.getState().lastCombatResult?.landed).toBe(true); expect(reflectedEvent("damage-shield-player-target", PLAYER_AGGRO_ID)).toMatchObject({ rawAmount: wow335WarriorDamageShieldReflectDamage(blockValue, 2, true), effectiveAmount: wow335WarriorDamageShieldReflectDamage(blockValue, 2, true), school: "physical", }); }); it("reflects a generated Warrior companion's block value and talent rank", () => { const warrior = createConfiguredPartyMember({ name: "Damage Shield Warrior", classId: "warrior", specialization: "Protection", specializationId: "warrior:protection", talentTreeId: "warrior-protection", talentRanks: { [WOW335_WARRIOR_DAMAGE_SHIELD_TALENT_ID]: 1 }, role: "tank", }, 80, 0, "damage-shield-party"); usePartyStore.getState().initializeParty("damage-shield-party", 80, useCombatStore.getState().health, "damage", 2); usePartyStore.setState({ members: [{ ...warrior, gearStats: { ...EMPTY_ITEM_STATS, blockValue: 1_000 }, }] }); registerPartyRuntimePosition(warrior.id, [0, 0, 0]); useCombatStore.getState().synchronizeActors(); registerAttacker("damage-shield-party-target", warrior.id); useCombatStore.getState().advanceMobCombat(1_000); const partyMember = usePartyStore.getState().members.find((member) => member.id === warrior.id)!; const blockValue = deriveCharacterStats( partyMember.classId, partyMember.level, partyMember.gearStats, partyMember.raceId, ).blockValue; expect(useCombatStore.getState().lastCombatResult?.landed).toBe(true); expect(reflectedEvent("damage-shield-party-target", warrior.id)).toMatchObject({ rawAmount: wow335WarriorDamageShieldReflectDamage(blockValue, 1, true), effectiveAmount: wow335WarriorDamageShieldReflectDamage(blockValue, 1, true), school: "physical", }); }); });