forked from phenom/healer-man
Release Healer Man 0.1.44
This commit is contained in:
1 parent
ccc01396cd
commit
756ee4f64a
24 files changed
+575
-46
No files matched your search
@@ -11,6 +11,7 @@ import { advanceDungeonPartyCombat, partyCombatRangeBand, resetPartyRuntimeClock
|
||||
import { subscribeCombatEvents } from "./combatEvents";
|
||||
import { bossDifficultyMultipliers } from "./dungeonDifficulty";
|
||||
import { abilitiesForClass } from "./abilityCatalog";
|
||||
import type { ContentCategoryId } from "../app/contentCategories";
|
||||
|
||||
const dungeon = requireDungeonDefinition("ragefire-chasm");
|
||||
const final = finalDungeonBoss(dungeon)!;
|
||||
@@ -21,15 +22,16 @@ afterAll(() => {
|
||||
writeFileSync("artifacts/boss-difficulty/ragefire-balance.json", `${JSON.stringify({ samples }, null, 2)}\n`);
|
||||
});
|
||||
|
||||
function fight(bossId: string, level: number, difficulty: number, seed: string, mechanics = false, playerDamage = false) {
|
||||
function fight(bossId: string, level: number, difficulty: number, seed: string, mechanics = false, playerDamage = false,
|
||||
characterSource: ContentCategoryId = "rom", encounterDungeon = dungeon) {
|
||||
clearMobRuntimeRegistry(); clearPartyRuntimeRegistry(); resetPartyRuntimeClock();
|
||||
const entity = dungeon.entities[dungeon.staticSpawns.find((spawn) => spawn.id === bossId)!.entityId];
|
||||
const scaling = dungeonEnemyScaling(dungeon, entity, bossId, level, "normal", difficulty);
|
||||
const entity = encounterDungeon.entities[encounterDungeon.staticSpawns.find((spawn) => spawn.id === bossId)!.entityId];
|
||||
const scaling = dungeonEnemyScaling(encounterDungeon, entity, bossId, level, "normal", difficulty, characterSource);
|
||||
const combat = useCombatStore.getState();
|
||||
const classId = playerDamage ? "rom-mage" : "rom-priest";
|
||||
combat.initializeCharacter({ classId, raceId: "rom-human", level });
|
||||
const classId = characterSource === "wow" ? (playerDamage ? "mage" : "priest") : (playerDamage ? "rom-mage" : "rom-priest");
|
||||
combat.initializeCharacter({ classId, raceId: characterSource === "wow" ? "human" : "rom-human", level });
|
||||
combat.setPlayerPosition([-18, 0, 0]);
|
||||
usePartyStore.getState().initializeParty(seed, level, useCombatStore.getState().health, playerDamage ? "damage" : "healer", 5, "rom");
|
||||
usePartyStore.getState().initializeParty(seed, level, useCombatStore.getState().health, playerDamage ? "damage" : "healer", 5, characterSource);
|
||||
combat.synchronizeActors();
|
||||
combat.registerMob(bossId, { name: entity.name, boss: true, serverEntry: entity.combat?.serverEntry,
|
||||
...scaling, attacks: entity.combat?.attacks, xpReward: 0 });
|
||||
@@ -40,7 +42,8 @@ function fight(bossId: string, level: number, difficulty: number, seed: string,
|
||||
}
|
||||
let firstDamage: number | undefined;
|
||||
let incomingDamage = 0; let healing = 0;
|
||||
const heal = abilitiesForClass("rom-priest").find((ability) => ability.name === "Urgent Heal")!;
|
||||
const heal = abilitiesForClass(classId).find((ability) => ability.target === "friendly"
|
||||
&& ability.effects.some((effect) => effect.kind === "heal") && (ability.unlockLevel ?? 1) <= level)!;
|
||||
const damage = abilitiesForClass(classId).find((ability) => ability.target === "hostile"
|
||||
&& ability.effects.some((effect) => effect.kind === "damage"))!;
|
||||
combat.selectMob(bossId);
|
||||
@@ -59,7 +62,8 @@ function fight(bossId: string, level: number, difficulty: number, seed: string,
|
||||
const injured = usePartyStore.getState().members.filter((member) => member.health > 0)
|
||||
.sort((left, right) => left.health / left.maxHealth - right.health / right.maxHealth)[0];
|
||||
if (injured && injured.health < injured.maxHealth * .8 && !useCombatStore.getState().activeCast) {
|
||||
usePartyStore.getState().selectMember(injured.id); combat.castAbility(heal.id, undefined, now);
|
||||
usePartyStore.getState().selectMember(injured.id);
|
||||
combat.castAbility(heal.id, { targetActorId: injured.id, now });
|
||||
}
|
||||
}
|
||||
const mob = useCombatStore.getState().mobs[bossId];
|
||||
@@ -72,6 +76,39 @@ function fight(bossId: string, level: number, difficulty: number, seed: string,
|
||||
}
|
||||
|
||||
describe("dungeon boss durability and difficulty", () => {
|
||||
const stockades = requireDungeonDefinition("stormwind-stockade");
|
||||
const stockadesBoss = stockades.bosses[0];
|
||||
const stockadesEntity = stockades.entities[stockades.staticSpawns.find((entry) => entry.id === stockadesBoss.id)!.entityId];
|
||||
|
||||
it("gives each level-three Stockades party its source-calibrated health minimum", () => {
|
||||
const easy = dungeonEnemyScaling(stockades, stockadesEntity, stockadesBoss.id, 3, "normal", 1, "wow");
|
||||
expect(easy).toMatchObject({ level: 4, maxHealth: 1300 });
|
||||
expect(dungeonEnemyScaling(stockades, stockadesEntity, stockadesBoss.id, 3, "normal", 10, "wow").maxHealth)
|
||||
.toBe(1300 * bossDifficultyMultipliers(10).health);
|
||||
// The dungeon catalog must not choose the companion power curve.
|
||||
expect(dungeonEnemyScaling(stockades, stockadesEntity, stockadesBoss.id, 3, "normal", 1, "rom").maxHealth).toBeCloseTo(7074.8);
|
||||
expect(dungeonEnemyScaling(stockades, stockadesEntity, stockadesBoss.id, 3, "normal", 1, "coa").maxHealth).toBe(10766);
|
||||
});
|
||||
|
||||
for (const level of [1, 3, 8, 20, 40, 80]) {
|
||||
it(`preserves WoW boss mechanic windows in Stockades at level ${level}`, () => {
|
||||
for (const seed of ["wow-health-1", "wow-health-2", "wow-health-3"]) {
|
||||
const ordinary = fight(stockadesBoss.id, level, 1, seed, false, false, "wow", stockades);
|
||||
const last = fight(finalDungeonBoss(stockades)!.id, level, 1, seed, false, false, "wow", stockades);
|
||||
samples.push({ level, seed, boss: ordinary, final: last });
|
||||
expect(ordinary.seconds ?? 240, JSON.stringify({ level, seed, ordinary, last })).toBeGreaterThanOrEqual(25);
|
||||
expect(last.seconds ?? 240, JSON.stringify({ level, seed, ordinary, last })).toBeGreaterThanOrEqual(45);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
it("allows real Stockades boss mechanics during a level-three WoW Priest party fight", () => {
|
||||
const result = fight(stockadesBoss.id, 3, 1, "wow-health-1", true, false, "wow", stockades);
|
||||
expect(result.seconds, JSON.stringify(result)).not.toBeNull();
|
||||
expect(result.seconds!).toBeLessThanOrEqual(180);
|
||||
expect(result.attacks).toBeGreaterThan(0);
|
||||
expect(result.incomingDamage).toBeGreaterThan(0);
|
||||
});
|
||||
it("increases boss health and damage at every slider step without changing trash", () => {
|
||||
const spawn = dungeon.staticSpawns.find((entry) => entry.id === final.id)!;
|
||||
const entity = dungeon.entities[spawn.entityId];
|
||||
|
||||
Reference in new issue
Block a user