forked from phenom/healer-man
Release Healer Man 0.1.6
This commit is contained in:
1 parent
55cfd43d66
commit
b12fb84859
96 files changed
+10874
-609
No files matched your search
@@ -0,0 +1,137 @@
|
||||
import type { ClassId } from "../app/characterCatalog";
|
||||
import type {
|
||||
OnlineMobTransform,
|
||||
OnlineRelayEventInput,
|
||||
OnlineSessionPlayer,
|
||||
} from "../app/onlineSessionTypes";
|
||||
import {
|
||||
normalizeActorResourcePool,
|
||||
type CombatActorState,
|
||||
} from "./combatActors";
|
||||
|
||||
const ONLINE_PLAYER_PREFIX = "online-player:";
|
||||
let active = false;
|
||||
let authority = true;
|
||||
let localAccountId: string | null = null;
|
||||
let playerActors = new Map<string, CombatActorState>();
|
||||
let players = new Map<string, OnlineSessionPlayer>();
|
||||
let mobTransforms = new Map<string, OnlineMobTransform>();
|
||||
let interactionSequence = 0;
|
||||
let interactions: OnlineRelayEventInput[] = [];
|
||||
|
||||
export function onlinePlayerActorId(accountId: string): string {
|
||||
return `${ONLINE_PLAYER_PREFIX}${accountId}`;
|
||||
}
|
||||
|
||||
export function onlineAccountIdFromActor(actorId: string): string | null {
|
||||
return actorId.startsWith(ONLINE_PLAYER_PREFIX)
|
||||
? actorId.slice(ONLINE_PLAYER_PREFIX.length)
|
||||
: null;
|
||||
}
|
||||
|
||||
export function isOnlinePlayerActorId(actorId: string): boolean {
|
||||
return actorId.startsWith(ONLINE_PLAYER_PREFIX);
|
||||
}
|
||||
|
||||
export function configureOnlineSessionRuntime(input: {
|
||||
readonly active: boolean;
|
||||
readonly authority: boolean;
|
||||
readonly localAccountId: string | null;
|
||||
readonly players?: readonly OnlineSessionPlayer[];
|
||||
readonly mobTransforms?: Readonly<Record<string, OnlineMobTransform>>;
|
||||
}): void {
|
||||
active = input.active;
|
||||
authority = !input.active || input.authority;
|
||||
localAccountId = input.localAccountId;
|
||||
players = new Map((input.players ?? []).map((player) => [player.accountId, player]));
|
||||
mobTransforms = new Map(Object.entries(input.mobTransforms ?? {}));
|
||||
const nextActors = new Map<string, CombatActorState>();
|
||||
for (const player of input.players ?? []) {
|
||||
if (player.accountId === input.localAccountId || !player.character) continue;
|
||||
const id = onlinePlayerActorId(player.accountId);
|
||||
const maximum = Math.max(0, player.maxResource);
|
||||
const resourceId = player.resourceName.toLowerCase() || "resource";
|
||||
nextActors.set(id, {
|
||||
id,
|
||||
threatActorId: id,
|
||||
kind: "companion",
|
||||
ownerId: player.accountId,
|
||||
classId: player.character.classId as ClassId,
|
||||
level: player.character.level,
|
||||
health: player.health,
|
||||
maxHealth: player.maxHealth,
|
||||
absorb: 0,
|
||||
resources: maximum > 0
|
||||
? { [resourceId]: normalizeActorResourcePool(resourceId, player.resource, maximum) }
|
||||
: {},
|
||||
cooldowns: {},
|
||||
globalCooldownEndsAt: 0,
|
||||
cast: player.activeCast ? {
|
||||
abilityId: player.activeCast.abilityId,
|
||||
school: player.activeCast.school,
|
||||
mode: player.activeCast.mode,
|
||||
startedAt: player.activeCast.startedAt,
|
||||
completesAt: player.activeCast.completesAt,
|
||||
originalDurationMs: player.activeCast.originalDurationMs,
|
||||
pushbackHits: player.activeCast.pushbackHits,
|
||||
origin: player.activeCast.origin,
|
||||
targetId: player.activeCast.targetId,
|
||||
} : null,
|
||||
controlledUntil: 0,
|
||||
schoolLockedUntil: {},
|
||||
comboPoints: 0,
|
||||
comboTargetId: null,
|
||||
runes: [],
|
||||
alive: player.health > 0,
|
||||
});
|
||||
}
|
||||
playerActors = nextActors;
|
||||
if (!input.active) interactions = [];
|
||||
}
|
||||
|
||||
export function onlineSessionIsActive(): boolean {
|
||||
return active;
|
||||
}
|
||||
|
||||
export function onlineSessionOwnsWorldSimulation(): boolean {
|
||||
return !active || authority;
|
||||
}
|
||||
|
||||
export function onlineSessionLocalAccountId(): string | null {
|
||||
return localAccountId;
|
||||
}
|
||||
|
||||
export function onlinePlayerRuntimeActors(): readonly CombatActorState[] {
|
||||
return [...playerActors.values()];
|
||||
}
|
||||
|
||||
export function onlinePlayerRuntimeActor(actorId: string): CombatActorState | null {
|
||||
return playerActors.get(actorId) ?? null;
|
||||
}
|
||||
|
||||
export function onlineSessionPlayer(accountId: string): OnlineSessionPlayer | null {
|
||||
return players.get(accountId) ?? null;
|
||||
}
|
||||
|
||||
export function onlineSynchronizedMobTransform(id: string): OnlineMobTransform | null {
|
||||
return active && !authority ? mobTransforms.get(id) ?? null : null;
|
||||
}
|
||||
|
||||
export function requestOnlineInteraction(kind: "loot" | "portal", targetActorId = ""): boolean {
|
||||
if (!active || authority) return false;
|
||||
interactionSequence += 1;
|
||||
interactions.push({
|
||||
clientEventId: `interaction:${kind}:${Date.now()}:${interactionSequence}`,
|
||||
kind,
|
||||
sourceActorId: localAccountId ? onlinePlayerActorId(localAccountId) : "",
|
||||
targetActorId,
|
||||
occurredAt: Date.now(),
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
export function drainOnlineInteractions(): readonly OnlineRelayEventInput[] {
|
||||
const pending = interactions;
|
||||
interactions = [];
|
||||
return pending;
|
||||
}
|
||||
Reference in new issue
Block a user