forked from phenom/healer-man
Update Healer Man server
This commit is contained in:
1 parent
6114a2295f
commit
69809f7228
593 files changed
+903643
-40774
No files matched your search
@@ -6,8 +6,12 @@ const path = require('node:path');
|
||||
const {
|
||||
DEFAULT_TEST_DUNGEON_ID,
|
||||
DEFAULT_TEST_DUNGEON_TITLE,
|
||||
DEFAULT_TEST_DUNGEON_BOSS,
|
||||
DEFAULT_TEST_DUNGEON_CATEGORY,
|
||||
FULL_STOCKADE_DUNGEON_ID,
|
||||
FULL_STOCKADE_DUNGEON_TITLE,
|
||||
FULL_STOCKADE_BOSS,
|
||||
selectDefaultTestDungeon,
|
||||
selectFullStockadeDungeon,
|
||||
openSelectedDungeonRoles,
|
||||
} = require('./playtest-defaults.cjs');
|
||||
|
||||
@@ -50,7 +54,8 @@ const moduleUrls = moduleFiles.map((file) => `/assets/${file}`);
|
||||
const routes = [
|
||||
{ id: 'barren-caves', title: 'Barren Caves', category: 'RoM' },
|
||||
{ id: 'wailing-caverns', title: 'Wailing Caverns', category: 'WoW' },
|
||||
{ id: DEFAULT_TEST_DUNGEON_ID, title: DEFAULT_TEST_DUNGEON_TITLE, category: 'WoW' },
|
||||
{ id: DEFAULT_TEST_DUNGEON_ID, title: DEFAULT_TEST_DUNGEON_TITLE, category: DEFAULT_TEST_DUNGEON_CATEGORY },
|
||||
{ id: FULL_STOCKADE_DUNGEON_ID, title: FULL_STOCKADE_DUNGEON_TITLE, category: 'WoW' },
|
||||
];
|
||||
const routesToRun = routeSelection
|
||||
? routes.filter((route) => route.id === routeSelection)
|
||||
@@ -62,7 +67,10 @@ if (routeSelection === 'wailing-caverns' && !historicalWailing) {
|
||||
if (historicalWailing && routeSelection !== 'wailing-caverns') {
|
||||
throw new Error('--historical-wailing requires --route=wailing-caverns.');
|
||||
}
|
||||
if (stockadeVowDiagnostic && (!campaignBossRoute || routeSelection !== DEFAULT_TEST_DUNGEON_ID)) {
|
||||
if (campaignBossRoute && !routeSelection) {
|
||||
throw new Error('--campaign-boss-route requires an explicit --route=<dungeon-id> selection.');
|
||||
}
|
||||
if (stockadeVowDiagnostic && (!campaignBossRoute || routeSelection !== FULL_STOCKADE_DUNGEON_ID)) {
|
||||
throw new Error('--stockade-vow-diagnostic requires --campaign-boss-route --route=stormwind-stockade.');
|
||||
}
|
||||
const dataDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'healer-man-native-routes-'));
|
||||
@@ -335,7 +343,7 @@ function sameObservedMobCast(left, right) {
|
||||
}
|
||||
|
||||
function isHamhockChainLightning(mob) {
|
||||
return Boolean(mob && !mob.dead && mob.health > 0 && mob.name === DEFAULT_TEST_DUNGEON_BOSS
|
||||
return Boolean(mob && !mob.dead && mob.health > 0 && mob.name === FULL_STOCKADE_BOSS
|
||||
&& mob.activeCast?.interruptible
|
||||
&& (mob.activeCast.spellId === 421 || mob.activeCast.attackId === 'spell-421'
|
||||
|| /chain lightning/i.test(mob.activeCast.name ?? '')));
|
||||
@@ -607,7 +615,7 @@ async function attemptStockadeVowInterrupt(page, routeResult, record, initialSna
|
||||
}
|
||||
let current = initialSnapshot;
|
||||
let hamhock = current.mobs.find((mob) => mob.id === diagnostic.targetBossId)
|
||||
?? current.mobs.find((mob) => mob.name === DEFAULT_TEST_DUNGEON_BOSS && mob.boss);
|
||||
?? current.mobs.find((mob) => mob.name === FULL_STOCKADE_BOSS && mob.boss);
|
||||
if (!isHamhockChainLightning(hamhock)) return { snapshot: current, attempted: false };
|
||||
diagnostic.hamhockObserved = true;
|
||||
const watchedCast = { attackId: hamhock.activeCast.attackId,
|
||||
@@ -1737,7 +1745,7 @@ async function runCampaignBossCheckpoint(page, route, result, objective, profile
|
||||
}
|
||||
}
|
||||
|
||||
if (stockadeVowDiagnostic && boss.name === DEFAULT_TEST_DUNGEON_BOSS
|
||||
if (stockadeVowDiagnostic && boss.name === FULL_STOCKADE_BOSS
|
||||
&& isHamhockChainLightning(boss)) {
|
||||
const vowWatch = await attemptStockadeVowInterrupt(page, result, record, current,
|
||||
plan.vowOfSilence, collect);
|
||||
@@ -1752,11 +1760,11 @@ async function runCampaignBossCheckpoint(page, route, result, objective, profile
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const casterCast = !stockadeVowDiagnostic && boss.name === DEFAULT_TEST_DUNGEON_BOSS
|
||||
const casterCast = !stockadeVowDiagnostic && boss.name === FULL_STOCKADE_BOSS
|
||||
&& (boss.activeCast?.spellId === 421 || boss.activeCast?.attackId === 'spell-421'
|
||||
|| /chain lightning/i.test(boss.activeCast?.name ?? ''))
|
||||
? boss.activeCast : null;
|
||||
if (route.id === DEFAULT_TEST_DUNGEON_ID && vowSetup?.menuAssignmentObserved && casterCast
|
||||
if (route.id === FULL_STOCKADE_DUNGEON_ID && vowSetup?.menuAssignmentObserved && casterCast
|
||||
&& casterCast.completesAt > current.now && current.player.selectedTargetId === boss.id
|
||||
&& current.now - (record.lastVowAttemptAt ?? 0) > 1_000) {
|
||||
const attempt = { observedAt: current.now, input: vowSetup.input, abilityId: vowSetup.id,
|
||||
@@ -2115,10 +2123,10 @@ async function replayRecoveredRouteToCursor(page, route, result, profile, plan,
|
||||
|
||||
async function runCampaignBossRoute(page, route, entryState, profile) {
|
||||
const guidance = readNavigationGuidance(route.id);
|
||||
const vowSetup = route.id === DEFAULT_TEST_DUNGEON_ID ? await assignVowThroughAbilityControls(page) : null;
|
||||
if (route.id === DEFAULT_TEST_DUNGEON_ID && vowSetup?.menuAssignmentObserved) entryState = await readLiveState(page, true);
|
||||
const vowSetup = route.id === FULL_STOCKADE_DUNGEON_ID ? await assignVowThroughAbilityControls(page) : null;
|
||||
if (route.id === FULL_STOCKADE_DUNGEON_ID && vowSetup?.menuAssignmentObserved) entryState = await readLiveState(page, true);
|
||||
const plan = actionPlanFromSnapshot(entryState);
|
||||
const hamhockObjective = guidance.objectives.find((objective) => objective.name === DEFAULT_TEST_DUNGEON_BOSS);
|
||||
const hamhockObjective = guidance.objectives.find((objective) => objective.name === FULL_STOCKADE_BOSS);
|
||||
const result = {
|
||||
dungeonId: route.id, title: route.title,
|
||||
coverage: stockadeVowDiagnostic
|
||||
@@ -2145,7 +2153,7 @@ async function runCampaignBossRoute(page, route, entryState, profile) {
|
||||
status: vowSetup?.menuAssignmentObserved && plan.vowOfSilence
|
||||
? 'watching' : 'vow-not-learned-or-not-bound-through-normal-ability-controls',
|
||||
targetBossId: hamhockObjective?.id ?? null,
|
||||
targetBossName: hamhockObjective?.name ?? DEFAULT_TEST_DUNGEON_BOSS,
|
||||
targetBossName: hamhockObjective?.name ?? FULL_STOCKADE_BOSS,
|
||||
abilityId: vowSetup?.id ?? null,
|
||||
abilityName: vowSetup?.name ?? 'Vow of Silence',
|
||||
input: vowSetup?.input ?? plan.vowOfSilence?.key ?? null,
|
||||
@@ -2179,7 +2187,7 @@ async function runCampaignBossRoute(page, route, entryState, profile) {
|
||||
throw new Error(`Targeted Vow diagnostic cannot start: ${result.vowDiagnostic.status}.`);
|
||||
}
|
||||
if (!plan.damage) throw new Error(`${route.id}: no normal bound damage ability for campaign route.`);
|
||||
if (route.id === DEFAULT_TEST_DUNGEON_ID && !result.vowSetup?.menuAssignmentObserved) {
|
||||
if (route.id === FULL_STOCKADE_DUNGEON_ID && !result.vowSetup?.menuAssignmentObserved) {
|
||||
result.vowSetup?.learned || console.warn('Vow of Silence was not observed in the selected identity action catalog.');
|
||||
}
|
||||
if (cameraDiagnostic) {
|
||||
@@ -2211,7 +2219,7 @@ async function runCampaignBossRoute(page, route, entryState, profile) {
|
||||
result.vowDiagnostic.targetDefeatedAt = snapshot.now;
|
||||
result.vowDiagnostic.stopReason = 'Hamhock was defeated before a Vow cancellation was confirmed';
|
||||
} else if (snapshot.mobs.some((mob) => mob.id === result.vowDiagnostic.targetBossId
|
||||
|| (mob.name === DEFAULT_TEST_DUNGEON_BOSS && mob.boss))) {
|
||||
|| (mob.name === FULL_STOCKADE_BOSS && mob.boss))) {
|
||||
result.vowDiagnostic.hamhockObserved = true;
|
||||
}
|
||||
}
|
||||
@@ -3389,6 +3397,8 @@ async function enterCampaignDungeon(page, route, isFirst, minimumLevel = 30) {
|
||||
await page.locator('.dungeon-select-screen').waitFor();
|
||||
if (route.id === DEFAULT_TEST_DUNGEON_ID) {
|
||||
await selectDefaultTestDungeon(page);
|
||||
} else if (route.id === FULL_STOCKADE_DUNGEON_ID) {
|
||||
await selectFullStockadeDungeon(page);
|
||||
} else {
|
||||
await page.locator('.dungeon-category-tab').filter({ hasText: route.category }).click();
|
||||
}
|
||||
@@ -3402,7 +3412,7 @@ async function enterCampaignDungeon(page, route, isFirst, minimumLevel = 30) {
|
||||
const selectedRowTitle = (await row.locator('strong').innerText()).trim();
|
||||
assert.equal(selectedRowTitle, route.title, `${route.title} campaign selection is exact`);
|
||||
await page.screenshot({ path: path.join(outputDirectory, `${route.id}-campaign-picker.png`) });
|
||||
if (route.id !== DEFAULT_TEST_DUNGEON_ID) await row.click();
|
||||
if (route.id !== DEFAULT_TEST_DUNGEON_ID && route.id !== FULL_STOCKADE_DUNGEON_ID) await row.click();
|
||||
await openSelectedDungeonRoles(page);
|
||||
await page.locator('.dungeon-role-option--healer').waitFor({ state: 'visible', timeout: 180_000 });
|
||||
await page.locator('.dungeon-role-option--healer').click();
|
||||
|
||||
Reference in new issue
Block a user