forked from phenom/healer-man
Release Healer Man 0.1.22
This commit is contained in:
1 parent
f6f2375145
commit
7f6001723a
144 files changed
+54107
-690
No files matched your search
@@ -0,0 +1,70 @@
|
||||
import type { DungeonEncounterEvent } from "./dungeonEncounterTypes";
|
||||
|
||||
export interface DungeonEncounterMobObservation {
|
||||
readonly engaged: boolean;
|
||||
readonly dead: boolean;
|
||||
readonly despawned: boolean;
|
||||
readonly health: number;
|
||||
readonly maxHealth: number;
|
||||
}
|
||||
|
||||
export interface DungeonEncounterMobCursorEntry {
|
||||
readonly engaged: boolean;
|
||||
readonly dead: boolean;
|
||||
readonly healthPercent: number;
|
||||
}
|
||||
|
||||
export type DungeonEncounterMobCursor = Readonly<Record<string, DungeonEncounterMobCursorEntry>>;
|
||||
|
||||
type CombatEdgeEvent = Extract<
|
||||
DungeonEncounterEvent,
|
||||
{ readonly kind: "entity-engaged" | "entity-health" | "entity-death" }
|
||||
>;
|
||||
|
||||
export interface DungeonEncounterCombatEventBatch {
|
||||
readonly cursor: DungeonEncounterMobCursor;
|
||||
readonly events: readonly CombatEdgeEvent[];
|
||||
}
|
||||
|
||||
function healthPercent(mob: DungeonEncounterMobObservation): number {
|
||||
if (!Number.isFinite(mob.maxHealth) || mob.maxHealth <= 0) return 0;
|
||||
return Math.max(0, Math.min(100, (Math.max(0, mob.health) / mob.maxHealth) * 100));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts mutable combat-state edges into deterministic encounter events.
|
||||
* Despawned actors are deliberately omitted so scripted cleanup never looks
|
||||
* like a kill and a later respawn of the same stable id can engage normally.
|
||||
*/
|
||||
export function deriveDungeonEncounterCombatEvents(
|
||||
previous: DungeonEncounterMobCursor,
|
||||
mobs: Readonly<Record<string, DungeonEncounterMobObservation>>,
|
||||
now: number,
|
||||
): DungeonEncounterCombatEventBatch {
|
||||
const cursor: Record<string, DungeonEncounterMobCursorEntry> = {};
|
||||
const events: CombatEdgeEvent[] = [];
|
||||
|
||||
for (const entityId of Object.keys(mobs).sort()) {
|
||||
const mob = mobs[entityId];
|
||||
if (mob.despawned) continue;
|
||||
const percent = healthPercent(mob);
|
||||
const prior = previous[entityId];
|
||||
cursor[entityId] = Object.freeze({
|
||||
engaged: mob.engaged,
|
||||
dead: mob.dead,
|
||||
healthPercent: percent,
|
||||
});
|
||||
|
||||
if (mob.engaged && !mob.dead && !prior?.engaged) {
|
||||
events.push(Object.freeze({ kind: "entity-engaged", entityId, now }));
|
||||
}
|
||||
if (!mob.dead && percent < (prior?.healthPercent ?? 100)) {
|
||||
events.push(Object.freeze({ kind: "entity-health", entityId, healthPercent: percent, now }));
|
||||
}
|
||||
if (mob.dead && !prior?.dead) {
|
||||
events.push(Object.freeze({ kind: "entity-death", entityId, now }));
|
||||
}
|
||||
}
|
||||
|
||||
return Object.freeze({ cursor: Object.freeze(cursor), events: Object.freeze(events) });
|
||||
}
|
||||
Reference in new issue
Block a user