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,105 @@
|
||||
import { resourceProfileForClass, type ResourceType } from "./abilityCatalog";
|
||||
import {
|
||||
normalizeActorResourcePool,
|
||||
type CombatActorState,
|
||||
} from "./combatActors";
|
||||
import type { PartyMember } from "./partyStore";
|
||||
|
||||
/**
|
||||
* Creates the authoritative companion actor. Existing actor values win over
|
||||
* the party-frame compatibility record once the actor has entered combat.
|
||||
*/
|
||||
export function companionActorFromMember(
|
||||
member: PartyMember,
|
||||
absorb = 0,
|
||||
existing?: CombatActorState | null,
|
||||
): CombatActorState {
|
||||
const profile = resourceProfileForClass(member.classId);
|
||||
const resources = existing?.kind === "companion"
|
||||
? existing.resources
|
||||
: Object.fromEntries(Object.entries(member.resourcePools).map(([id, current]) => [id,
|
||||
normalizeActorResourcePool(
|
||||
id,
|
||||
current ?? 0,
|
||||
id === member.resourceType ? member.maxResource : 100,
|
||||
id === member.resourceType ? profile.regenerationPerSecond : 0,
|
||||
member.lastResourceSpentAt[id as ResourceType] ?? 0,
|
||||
),
|
||||
]));
|
||||
const actor = existing?.kind === "companion" ? existing : null;
|
||||
return Object.freeze({
|
||||
id: member.id,
|
||||
threatActorId: member.id,
|
||||
kind: "companion" as const,
|
||||
classId: member.classId,
|
||||
level: member.level,
|
||||
health: actor?.health ?? member.health,
|
||||
maxHealth: actor?.maxHealth ?? member.maxHealth,
|
||||
absorb,
|
||||
resources,
|
||||
cooldowns: actor?.cooldowns ?? member.cooldowns,
|
||||
globalCooldownEndsAt: actor?.globalCooldownEndsAt ?? member.globalCooldownEndsAt,
|
||||
cast: actor?.cast ?? member.activeCast,
|
||||
controlledUntil: actor?.controlledUntil ?? member.controlledUntil,
|
||||
schoolLockedUntil: actor?.schoolLockedUntil ?? member.schoolLockedUntil,
|
||||
comboPoints: actor?.comboPoints ?? 0,
|
||||
comboTargetId: actor?.comboTargetId ?? null,
|
||||
runes: actor?.runes ?? member.runes,
|
||||
abilityIds: actor?.abilityIds,
|
||||
alive: (actor?.health ?? member.health) > 0,
|
||||
});
|
||||
}
|
||||
|
||||
/** Party and scene consumers receive a read-compatible mirror of actor state. */
|
||||
export function memberFromCompanionActor(member: PartyMember, actor?: CombatActorState | null): PartyMember {
|
||||
if (!actor || actor.kind !== "companion") return member;
|
||||
const resourcePools = Object.fromEntries(Object.entries(actor.resources).map(([id, pool]) => [id, pool.current])) as Partial<Record<ResourceType, number>>;
|
||||
const lastResourceSpentAt = Object.fromEntries(Object.entries(actor.resources).map(([id, pool]) => [id, pool.lastSpentAt])) as Partial<Record<ResourceType, number>>;
|
||||
const primary = actor.resources[member.resourceType];
|
||||
return {
|
||||
...member,
|
||||
health: actor.health,
|
||||
maxHealth: actor.maxHealth,
|
||||
resource: primary?.current ?? member.resource,
|
||||
maxResource: primary?.maximum ?? member.maxResource,
|
||||
resourcePools,
|
||||
lastResourceSpentAt,
|
||||
cooldowns: actor.cooldowns,
|
||||
globalCooldownEndsAt: actor.globalCooldownEndsAt,
|
||||
activeCast: actor.cast,
|
||||
activeCastTargetId: actor.cast?.targetId ?? member.activeCastTargetId,
|
||||
schoolLockedUntil: actor.schoolLockedUntil,
|
||||
runes: actor.runes,
|
||||
controlledUntil: actor.controlledUntil,
|
||||
status: actor.health <= 0 ? "down" : member.status,
|
||||
};
|
||||
}
|
||||
|
||||
export function companionActorWithMemberRuntime(
|
||||
actor: CombatActorState,
|
||||
member: PartyMember,
|
||||
): CombatActorState {
|
||||
const profile = resourceProfileForClass(member.classId);
|
||||
const resources = Object.fromEntries(Object.entries(member.resourcePools).map(([id, current]) => [id,
|
||||
normalizeActorResourcePool(
|
||||
id,
|
||||
current ?? 0,
|
||||
id === member.resourceType ? member.maxResource : actor.resources[id]?.maximum ?? 100,
|
||||
id === member.resourceType ? profile.regenerationPerSecond : actor.resources[id]?.regenerationPerSecond ?? 0,
|
||||
member.lastResourceSpentAt[id as ResourceType] ?? actor.resources[id]?.lastSpentAt ?? 0,
|
||||
),
|
||||
]));
|
||||
return Object.freeze({
|
||||
...actor,
|
||||
health: member.health,
|
||||
maxHealth: member.maxHealth,
|
||||
resources,
|
||||
cooldowns: member.cooldowns,
|
||||
globalCooldownEndsAt: member.globalCooldownEndsAt,
|
||||
cast: member.activeCast ? { ...member.activeCast, targetId: member.activeCastTargetId } : null,
|
||||
controlledUntil: member.controlledUntil,
|
||||
schoolLockedUntil: member.schoolLockedUntil,
|
||||
runes: member.runes,
|
||||
alive: member.health > 0,
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user