Update class mechanics, stat rulesets, and CoA reference catalogs
This commit is contained in:
1 parent
b16821e92e
commit
39458d5de6
221 files changed
+2584962
-568
No files matched your search
@@ -4,12 +4,19 @@ import {
|
||||
type CombatActorState,
|
||||
} from "./combatActors";
|
||||
import type { PartyMember } from "./partyStore";
|
||||
import { baseClassFor, isRomClassId } from "../app/characterCatalog";
|
||||
import { isRomClassId } from "../app/characterCatalog";
|
||||
import { deriveCharacterStats } from "./wotlkStats";
|
||||
|
||||
export function companionResourceMaximum(member: PartyMember, id: string): number {
|
||||
return id === member.resourceType ? member.maxResource : id === "mana" && !isRomClassId(member.classId)
|
||||
? deriveCharacterStats(baseClassFor(member.classId), member.level, member.gearStats, member.raceId).mana
|
||||
if (id === member.resourceType) return member.maxResource;
|
||||
const mirroredMaximum = member.resourceMaximums?.[id as ResourceType];
|
||||
if (mirroredMaximum !== undefined) return mirroredMaximum;
|
||||
return id === "mana"
|
||||
&& (member.statRuleset === "rom" || !isRomClassId(member.classId))
|
||||
? deriveCharacterStats(
|
||||
member.classId, member.level, member.gearStats, member.raceId, {},
|
||||
member.secondaryClassId, member.gender, member.statRuleset ?? "wow",
|
||||
).mana
|
||||
: id === "nature-power" ? naturePowerMaximumForCharacter(member.classId, member.secondaryClassId, member.level)
|
||||
: id === "psi" ? 6
|
||||
: 100;
|
||||
@@ -25,23 +32,47 @@ export function companionActorFromMember(
|
||||
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,
|
||||
companionResourceMaximum(member, id),
|
||||
id === member.resourceType ? profile.regenerationPerSecond : 0,
|
||||
member.lastResourceSpentAt[id as ResourceType] ?? 0,
|
||||
),
|
||||
]));
|
||||
let resources: CombatActorState["resources"];
|
||||
if (existing?.kind === "companion" && member.statRuleset === "rom" && isRomClassId(member.classId)) {
|
||||
const previousResources = existing.resources;
|
||||
const nextResources: Record<string, ReturnType<typeof normalizeActorResourcePool>> = {};
|
||||
const resourceIds = new Set([...Object.keys(previousResources), ...Object.keys(member.resourcePools)]);
|
||||
for (const id of resourceIds) {
|
||||
const previous = previousResources[id];
|
||||
const nextMaximum = companionResourceMaximum(member, id);
|
||||
const hasChangedMaximum = previous !== undefined && Math.abs(previous.maximum - nextMaximum) > 1e-6;
|
||||
const current = hasChangedMaximum
|
||||
? member.resourcePools[id as ResourceType] ?? previous.current
|
||||
: previous?.current ?? member.resourcePools[id as ResourceType] ?? 0;
|
||||
nextResources[id] = normalizeActorResourcePool(
|
||||
id,
|
||||
current,
|
||||
nextMaximum,
|
||||
id === member.resourceType ? profile.regenerationPerSecond : previous?.regenerationPerSecond ?? 0,
|
||||
member.lastResourceSpentAt[id as ResourceType] ?? previous?.lastSpentAt ?? 0,
|
||||
);
|
||||
}
|
||||
resources = nextResources;
|
||||
} else if (existing?.kind === "companion") {
|
||||
resources = existing.resources;
|
||||
} else {
|
||||
resources = Object.fromEntries(Object.entries(member.resourcePools).map(([id, current]) => [id,
|
||||
normalizeActorResourcePool(
|
||||
id,
|
||||
current ?? 0,
|
||||
companionResourceMaximum(member, id),
|
||||
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,
|
||||
statRuleset: member.statRuleset,
|
||||
level: member.level,
|
||||
health: actor?.health ?? member.health,
|
||||
maxHealth: actor?.maxHealth ?? member.maxHealth,
|
||||
@@ -64,6 +95,7 @@ export function companionActorFromMember(
|
||||
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 resourceMaximums = Object.fromEntries(Object.entries(actor.resources).map(([id, pool]) => [id, pool.maximum])) 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 {
|
||||
@@ -73,6 +105,7 @@ export function memberFromCompanionActor(member: PartyMember, actor?: CombatActo
|
||||
resource: primary?.current ?? member.resource,
|
||||
maxResource: primary?.maximum ?? member.maxResource,
|
||||
resourcePools,
|
||||
resourceMaximums,
|
||||
lastResourceSpentAt,
|
||||
comboPoints: actor.comboPoints,
|
||||
comboTargetId: actor.comboTargetId,
|
||||
|
||||
Reference in new issue
Block a user