forked from phenom/healer-man
Update Healer Man server
This commit is contained in:
1 parent
9d7e0e2f9e
commit
35dfdaed61
94 files changed
+17034
-418
No files matched your search
@@ -0,0 +1,119 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { PLAYER_AURA_ENTITY_ID, useCombatStore, resolvedAbilityCosts } from "./combatStore";
|
||||
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
|
||||
import { clearPartyRuntimeRegistry } from "./partyRuntimeRegistry";
|
||||
import { usePartyStore } from "./partyStore";
|
||||
|
||||
function shamanAbility(name: string) {
|
||||
const ability = useCombatStore.getState().abilities.find((candidate) => candidate.name === name);
|
||||
expect(ability, `Shaman ${name}`).toBeDefined();
|
||||
return ability!;
|
||||
}
|
||||
|
||||
function setTalentRank(talentId: string, rank: number): void {
|
||||
useCombatStore.setState((state) => ({
|
||||
talentRanks: { ...state.talentRanks, [talentId]: rank },
|
||||
}));
|
||||
}
|
||||
|
||||
function castAndFinish(abilityId: string, targetActorId: string | null | undefined, now: number): void {
|
||||
const result = useCombatStore.getState().castAbility(
|
||||
abilityId,
|
||||
targetActorId !== undefined ? { targetActorId, now } : { now },
|
||||
);
|
||||
expect(result.ok, JSON.stringify(result)).toBe(true);
|
||||
const activeCast = useCombatStore.getState().activeCast;
|
||||
if (activeCast) useCombatStore.getState().tick(0.1, activeCast.completesAt);
|
||||
}
|
||||
|
||||
function setupShaman(): void {
|
||||
clearMobRuntimeRegistry();
|
||||
clearPartyRuntimeRegistry();
|
||||
useCombatStore.getState().initializeCharacter({ classId: "shaman", level: 80, xp: 0 });
|
||||
useCombatStore.getState().resetSettings();
|
||||
useCombatStore.getState().setPlayerPosition([0, 0, 0]);
|
||||
usePartyStore.getState().initializeParty("wow-shaman-conditional-talent-tests", 80, useCombatStore.getState().health);
|
||||
useCombatStore.getState().registerMob("shaman-conditional-target", {
|
||||
name: "Shaman conditional talent target",
|
||||
level: 80,
|
||||
maxHealth: 1_000_000,
|
||||
xpReward: 0,
|
||||
});
|
||||
setMobPosition("shaman-conditional-target", [8, 0, 0]);
|
||||
useCombatStore.getState().selectMob("shaman-conditional-target");
|
||||
}
|
||||
|
||||
describe("WoW Shaman conditional talent mechanics", () => {
|
||||
beforeEach(setupShaman);
|
||||
|
||||
it("grants two 30% mana-cost reductions after a critical elemental spell", () => {
|
||||
setTalentRank("talent-574", 2);
|
||||
useCombatStore.setState((state) => ({
|
||||
gearStats: { ...state.gearStats, criticalStrikeRating: 1_000_000 },
|
||||
}));
|
||||
const lightningBolt = shamanAbility("Lightning Bolt");
|
||||
castAndFinish(lightningBolt.id, undefined, 1_000);
|
||||
|
||||
expect(useCombatStore.getState().combatEvents.some((event) => (
|
||||
event.kind === "damage" && event.abilityId === lightningBolt.id && event.critical
|
||||
))).toBe(true);
|
||||
const clearcasting = () => useCombatStore.getState().auras.find((aura) => (
|
||||
aura.targetId === PLAYER_AURA_ENTITY_ID
|
||||
&& aura.definition.utilityTags?.includes("wow335-shaman-elemental-focus-clearcasting")
|
||||
));
|
||||
expect(clearcasting()?.stacks).toBe(2);
|
||||
|
||||
const healingWave = shamanAbility("Healing Wave");
|
||||
const before = useCombatStore.getState();
|
||||
const fullCost = resolvedAbilityCosts(healingWave, before.talentModifiers, { ...before, auras: [] })
|
||||
.find((cost) => cost.resource === "mana")?.amount;
|
||||
expect(fullCost).toBeGreaterThan(0);
|
||||
const discountedCost = Math.round(fullCost! * 0.7);
|
||||
expect(resolvedAbilityCosts(healingWave, before.talentModifiers, before)
|
||||
.find((cost) => cost.resource === "mana")?.amount).toBe(discountedCost);
|
||||
|
||||
castAndFinish(healingWave.id, null, 10_000);
|
||||
expect(clearcasting()?.stacks).toBe(1);
|
||||
const oneChargeState = useCombatStore.getState();
|
||||
expect(resolvedAbilityCosts(healingWave, oneChargeState.talentModifiers, oneChargeState)
|
||||
.find((cost) => cost.resource === "mana")?.amount).toBe(discountedCost);
|
||||
castAndFinish(healingWave.id, null, 20_000);
|
||||
expect(clearcasting()).toBeUndefined();
|
||||
});
|
||||
|
||||
it("uses Reverberation's rank chance and 20% bonus on the next different Shock", () => {
|
||||
setTalentRank("talent-575", 3);
|
||||
const earthShock = shamanAbility("Earth Shock");
|
||||
const frostShock = shamanAbility("Frost Shock");
|
||||
|
||||
castAndFinish(earthShock.id, undefined, 1_000);
|
||||
const initialReverberation = useCombatStore.getState().auras.find((aura) => (
|
||||
aura.definition.utilityTags?.includes("wow335-shaman-reverberation")
|
||||
));
|
||||
expect(initialReverberation?.expiresAt).toBe(9_000);
|
||||
expect(initialReverberation?.definition.utilityTags).toContain(`wow335-shaman-reverberation:from:${earthShock.id}`);
|
||||
|
||||
castAndFinish(frostShock.id, undefined, 6_000);
|
||||
const frostShockHit = useCombatStore.getState().combatEvents.find((event) => (
|
||||
event.kind === "damage" && event.abilityId === frostShock.id
|
||||
));
|
||||
expect(frostShockHit?.effectiveAmount).toBeGreaterThan(0);
|
||||
const refreshedReverberation = useCombatStore.getState().auras.find((aura) => (
|
||||
aura.definition.utilityTags?.includes("wow335-shaman-reverberation")
|
||||
));
|
||||
expect(refreshedReverberation?.definition.utilityTags)
|
||||
.toContain(`wow335-shaman-reverberation:from:${frostShock.id}`);
|
||||
|
||||
const buffedRawDamage = frostShockHit?.rawAmount;
|
||||
setupShaman();
|
||||
const baselineBolt = shamanAbility("Lightning Bolt");
|
||||
const baselineFrostShock = shamanAbility("Frost Shock");
|
||||
castAndFinish(baselineBolt.id, undefined, 1_000);
|
||||
castAndFinish(baselineFrostShock.id, undefined, 6_000);
|
||||
const baselineHit = useCombatStore.getState().combatEvents.find((event) => (
|
||||
event.kind === "damage" && event.abilityId === baselineFrostShock.id
|
||||
));
|
||||
expect(baselineHit?.rawAmount).toBeGreaterThan(0);
|
||||
expect(buffedRawDamage).toBe(Math.round((baselineHit?.rawAmount ?? 0) * 1.2));
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user