Release Healer Man 0.1.24

This commit is contained in:
phenom committed 2026-09-09 16:43:37 -04:00
1 parent c4346751a9
commit bac0da9300
118 files changed
+857 -289

No files matched your search

+35 -9
View File
@@ -19,7 +19,7 @@ import {
} from "./combatStore";
import { TALENT_NODES, talentNodesForTree } from "./talentCatalog";
import { EMPTY_ITEM_STATS } from "./itemStats";
import { abilitiesForClass, defaultActionBarForClass } from "./abilityCatalog";
import { abilitiesForClass, abilityAtLevel, defaultActionBarForClass } from "./abilityCatalog";
import { defaultActionBindings } from "./actionBindings";
import { deriveCharacterStats, MANA_POOL_MULTIPLIER } from "./wotlkStats";
import { subscribeCombatPresentation, type CombatPresentationEvent } from "./combatPresentation";
@@ -93,14 +93,12 @@ describe("combat store", () => {
expect(useCombatStore.getState().mobs.ravager.health).toBe(100);
useCombatStore.getState().tick(0.1, 2500);
expect(useCombatStore.getState().mobs.ravager.health).toBeLessThan(100);
expect(useCombatStore.getState().resource).toBe(
startingResource - Math.round(startingResource / MANA_POOL_MULTIPLIER * 0.14),
);
expect(useCombatStore.getState().resource).toBe(startingResource - 17);
expect(useCombatStore.getState().activeCast).toBeNull();
expect(useCombatStore.getState().mobs.ravager.engaged).toBe(true);
});
it("uses the displayed primary mana and resolved percentage cost for affordability", () => {
it("uses the displayed primary mana and fixed rank cost for affordability", () => {
useCombatStore.getState().initializeCharacter({ classId: "mage", level: 1 });
const initial = useCombatStore.getState();
const frostbolt = initial.abilities.find((ability) => ability.id === "mage-frostbolt");
@@ -108,7 +106,7 @@ describe("combat store", () => {
const [cost] = resolvedAbilityCosts(frostbolt!, initial.talentModifiers, initial);
expect(cost).toEqual({
resource: "mana",
amount: Math.round(initial.maxResource / MANA_POOL_MULTIPLIER * 0.14),
amount: 17,
});
registerTarget("mana-target", [10, 0, 0]);
@@ -129,6 +127,31 @@ describe("combat store", () => {
});
});
it("does not increase a classic spell's mana cost until a new rank is learned", () => {
const pain = abilitiesForClass("priest").find((ability) => ability.id === "priest-shadow-word-pain");
expect(pain).toBeDefined();
const resolvedAtLevel = (level: number) => {
useCombatStore.getState().initializeCharacter({ classId: "priest", level });
const state = useCombatStore.getState();
const ranked = abilityAtLevel(pain!, level);
return {
dbcSpellId: ranked.dbcSpellId,
maximumMana: state.maxResource,
cost: resolvedAbilityCosts(ranked, state.talentModifiers, state)[0],
};
};
const rankFourAt26 = resolvedAtLevel(26);
const rankFourAt32 = resolvedAtLevel(32);
const rankFiveAt34 = resolvedAtLevel(34);
expect(rankFourAt26).toMatchObject({ dbcSpellId: 992, cost: { resource: "mana", amount: 133 } });
expect(rankFourAt32).toMatchObject({ dbcSpellId: 992, cost: { resource: "mana", amount: 133 } });
expect(rankFourAt32.maximumMana).toBeGreaterThan(rankFourAt26.maximumMana);
expect(rankFiveAt34).toMatchObject({ dbcSpellId: 2767, cost: { resource: "mana", amount: 188 } });
});
it("emits exactly one cast and release event and cancels presentation with the cast", () => {
useCombatStore.getState().initializeCharacter({ classId: "mage", level: 1 });
registerTarget("presentation-target", [10, 0, 0]);
@@ -1080,13 +1103,16 @@ describe("combat store", () => {
expect(useCombatStore.getState().talentModifiers).toEqual(expect.arrayContaining([
expect.objectContaining({ kind: "resource-cost-percent", amount: -15, sourceTalentName: "Convection" }),
]));
const lightningBolt = abilityAtLevel(
abilitiesForClass("shaman").find((ability) => ability.id === "shaman-lightning-bolt")!,
80,
);
const expectedLightningBoltCost = Math.round(lightningBolt.cost.amount * 0.85);
registerTarget("mana-dummy", [10, 0, 0], 10_000, 0);
expect(useCombatStore.getState().castSlot(0, undefined, 10_000).ok).toBe(true);
const boltCompletion = useCombatStore.getState().activeCast!.completesAt;
useCombatStore.getState().tick(0.1, boltCompletion);
expect(useCombatStore.getState().resource).toBe(
startingMana - Math.round(startingMana / MANA_POOL_MULTIPLIER * 0.1 * 0.85),
);
expect(useCombatStore.getState().resource).toBe(startingMana - expectedLightningBoltCost);
});
it("routes a cast-time direct heal to the selected living party member", () => {