Release Healer Man 0.1.53
This commit is contained in:
1 parent
d0a02487db
commit
d6976e6ef6
17 files changed
+555
-69
No files matched your search
+51
-9
@@ -31,7 +31,12 @@ import type { RuntimeTalentRanks as TalentRanks } from "./talentRuntimeCatalog";
|
||||
import type { EnemyControlMechanic } from "./enemyAttacks";
|
||||
import type { ContentCategoryId } from "../app/contentCategories";
|
||||
import type { PartyRole, PartySize } from "./partyRoles";
|
||||
import { resourceProfileForClass, type ResourceType } from "./abilityCatalog";
|
||||
import {
|
||||
abilitiesForCharacter,
|
||||
learnedAbilityForBuild,
|
||||
resourceProfileForClass,
|
||||
type ResourceType,
|
||||
} from "./abilityCatalog";
|
||||
import { createDeathKnightRunes, type CombatActorCastState, type DeathKnightRuneState } from "./combatActors";
|
||||
|
||||
export {
|
||||
@@ -222,6 +227,43 @@ function memberMaxResource(
|
||||
: profile.maximum;
|
||||
}
|
||||
|
||||
function secondaryResourceMaximum(type: ResourceType): number {
|
||||
if (type === "nature-power") return 10;
|
||||
if (type === "psi") return 6;
|
||||
return 100;
|
||||
}
|
||||
|
||||
function initialSecondaryResource(type: ResourceType, maximum: number): number {
|
||||
return type === "rage" || type === "runic-power" || type === "nature-power" || type === "psi"
|
||||
? 0
|
||||
: maximum;
|
||||
}
|
||||
|
||||
/** Keeps every resource used by the member's learned kit available to companion AI. */
|
||||
function withMemberAbilityResourcePools(member: PartyMember): PartyMember {
|
||||
const types = new Set<ResourceType>([member.resourceType]);
|
||||
for (const ability of abilitiesForCharacter(member.classId, member.secondaryClassId)) {
|
||||
const learned = learnedAbilityForBuild(ability, member.level, member.talentRanks);
|
||||
if (!learned) continue;
|
||||
for (const cost of learned.costs?.length ? learned.costs : [learned.cost]) {
|
||||
if (cost.resource !== "health") types.add(cost.resource);
|
||||
}
|
||||
}
|
||||
const resourcePools: Partial<Record<ResourceType, number>> = {};
|
||||
for (const type of types) {
|
||||
if (type === member.resourceType) {
|
||||
resourcePools[type] = member.resource;
|
||||
continue;
|
||||
}
|
||||
const maximum = secondaryResourceMaximum(type);
|
||||
resourcePools[type] = Math.max(0, Math.min(
|
||||
maximum,
|
||||
member.resourcePools[type] ?? initialSecondaryResource(type, maximum),
|
||||
));
|
||||
}
|
||||
return { ...member, resourcePools: Object.freeze(resourcePools) };
|
||||
}
|
||||
|
||||
function withMemberGearStats(member: PartyMember, gearStats: ItemStats): PartyMember {
|
||||
const maxHealth = memberMaxHealth(
|
||||
member.level,
|
||||
@@ -237,7 +279,7 @@ function withMemberGearStats(member: PartyMember, gearStats: ItemStats): PartyMe
|
||||
const resource = Math.max(0, Math.round(
|
||||
member.resource / Math.max(1, member.maxResource) * maxResource,
|
||||
));
|
||||
return {
|
||||
return withMemberAbilityResourcePools({
|
||||
...member,
|
||||
gearStats,
|
||||
health,
|
||||
@@ -245,7 +287,7 @@ function withMemberGearStats(member: PartyMember, gearStats: ItemStats): PartyMe
|
||||
resource,
|
||||
maxResource,
|
||||
resourcePools: Object.freeze({ ...member.resourcePools, [member.resourceType]: resource }),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function createMember(
|
||||
@@ -286,7 +328,7 @@ function createMember(
|
||||
const resource = Math.round(
|
||||
maxResource * (resourceProfile.maximum > 0 ? resourceProfile.initial / resourceProfile.maximum : 0),
|
||||
);
|
||||
return {
|
||||
return withMemberAbilityResourcePools({
|
||||
id,
|
||||
name: template.name,
|
||||
raceId: race.id,
|
||||
@@ -323,7 +365,7 @@ function createMember(
|
||||
tauntReadyAt: 0,
|
||||
controlledUntil: 0,
|
||||
controlMechanic: null,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/** Creates one exact companion while retaining the live party stat/equipment path. */
|
||||
@@ -339,12 +381,12 @@ export function createConfiguredPartyMember(
|
||||
specialization: configuration.specialization,
|
||||
talentTreeId: configuration.talentTreeId ?? configuration.specializationId ?? "",
|
||||
}, configuration.role, level, index, seed, configuration.talentRanks);
|
||||
return Object.freeze({
|
||||
return Object.freeze(withMemberAbilityResourcePools({
|
||||
...member,
|
||||
secondaryClassId: configuration.secondaryClassId ?? null,
|
||||
specializationId: configuration.specializationId ?? member.specializationId,
|
||||
talentRanks: configuration.talentRanks ?? member.talentRanks,
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -571,7 +613,7 @@ export const usePartyStore = create<PartyState>((set, get) => ({
|
||||
const resource = Math.max(0, Math.round(
|
||||
member.resource / Math.max(1, member.maxResource) * maxResource,
|
||||
));
|
||||
return {
|
||||
return withMemberAbilityResourcePools({
|
||||
...member,
|
||||
level: safeLevel,
|
||||
health,
|
||||
@@ -582,7 +624,7 @@ export const usePartyStore = create<PartyState>((set, get) => ({
|
||||
talentRanks: isRomClassId(member.classId)
|
||||
? Object.freeze({})
|
||||
: runtimePartyTalentRanksForLevel(member.classId, member.specialization, safeLevel),
|
||||
};
|
||||
});
|
||||
}),
|
||||
};
|
||||
}),
|
||||
|
||||
Reference in new issue
Block a user