Release v0.1.4 2026-07-12

This commit is contained in:
Warren H
2026-07-12 13:49:46 -04:00
parent b48b3a4f8f
commit bef71d391a
803 changed files with 3800 additions and 358322 deletions
+9 -15
View File
@@ -1,7 +1,7 @@
import { BOSS_DEFINITIONS } from "../bossCatalog";
import { angleTo, moveToward, pointToSegmentDistance } from "../geometry";
import type { BossMotionState, BossState, MemberId, SlashLane, WorldPosition } from "../types";
import { applyMelee, chooseLivingTarget, cloneMotion, createBaseMotion, memberName } from "./shared";
import type { BossId, BossMotionState, BossState, MemberId, SlashLane, WorldPosition } from "../types";
import { applyMelee, chooseLivingTarget, cloneMotion, createBaseMotion, memberName, returnBossToArenaCenter } from "./shared";
import type { BossMechanicContext, BossMechanicResult, UpcomingMechanic } from "./types";
export const EMBER_MANTIS_SLASH = {
@@ -27,8 +27,8 @@ const TARGET_ORDER: readonly MemberId[] = ["nia", "orin", "aelia", "vale", "bran
const MIN_BOSS_X = -5.8;
const MAX_BOSS_X = 5.8;
export function createEmberMantisState(): BossState {
const definition = BOSS_DEFINITIONS["ember-mantis-duelist"];
export function createEmberMantisState(bossId: BossId = "warcaller-orc"): BossState {
const definition = BOSS_DEFINITIONS[bossId];
return {
id: definition.id,
name: definition.name,
@@ -41,9 +41,9 @@ export function createEmberMantisState(): BossState {
};
}
export function createEmberMantisMotion(): BossMotionState {
export function createEmberMantisMotion(bossId: BossId = "warcaller-orc"): BossMotionState {
return {
...createBaseMotion("ember-mantis-duelist"),
...createBaseMotion(bossId),
position: [0, -6.6],
nextMechanicAt: EMBER_MANTIS_SLASH.firstAt,
};
@@ -161,17 +161,12 @@ export function advanceEmberMantisMechanics(context: BossMechanicContext): BossM
const events: BossMechanicResult["events"] = [];
if (motion.mode === "holding") {
const tank = context.partyPositions.brann;
motion.position = moveToward(
motion.position,
[tank[0] + motion.formationOffsetX, tank[1] - 4.25],
2.5 * context.delta,
);
returnBossToArenaCenter(motion, context.delta, 2.5);
if (context.time >= motion.nextMechanicAt) {
motion = beginSidestep(motion, party, context.partyPositions, context.time);
events.push({
at: context.time,
message: `Gate Guardian shifts toward ${memberName(party, motion.chargeTargetId)}. Track its arms.`,
message: `${boss.name} shifts toward ${memberName(party, motion.chargeTargetId)}. Track its attack.`,
tone: "danger",
pulseKind: "slash",
targetId: motion.chargeTargetId,
@@ -223,7 +218,6 @@ export function upcomingEmberMantisMechanic(
motion: BossMotionState,
time: number,
): UpcomingMechanic {
void boss;
if (motion.mode === "mantis_sidestep") {
return { name: "Guardian repositioning", remaining: Math.max(0, motion.phaseEndsAt - time), cycle: EMBER_MANTIS_SLASH.sidestepDuration, urgent: true };
}
@@ -234,7 +228,7 @@ export function upcomingEmberMantisMechanic(
return { name: "Guardian Cross — safe quadrant", remaining: Math.max(0, motion.phaseEndsAt - time), cycle: EMBER_MANTIS_SLASH.telegraphDuration, urgent: true };
}
if (motion.mode === "mantis_recover") {
return { name: "Gate Guardian exposed", remaining: Math.max(0, motion.phaseEndsAt - time), cycle: EMBER_MANTIS_SLASH.recoverDuration, urgent: false };
return { name: `${boss.name} exposed`, remaining: Math.max(0, motion.phaseEndsAt - time), cycle: EMBER_MANTIS_SLASH.recoverDuration, urgent: false };
}
const nextIsCross = motion.mechanicCount % 2 === 1;
const remaining = Math.max(0, motion.nextMechanicAt - time);