Update Healer Man server

This commit is contained in:
phenom committed 2026-09-26 17:51:56 -04:00
1 parent 9c5fb4c614
commit bd073fb00f
113 files changed
+4902 -273

No files matched your search

+56 -16
View File
@@ -1,4 +1,6 @@
import { create } from "zustand";
import { permanentBuffEffects } from "./partyBuffPolicy";
import { usePartyBuffPolicyStore } from "./partyBuffPolicyStore";
import { combatNow } from "./combatClock";
import { useDungeonSimulationStore } from "./dungeonSimulationStore";
import { useGameStore } from "./store";
@@ -2166,7 +2168,7 @@ function auraDefinitionForAbility(
description: definition.description ?? ability.description,
icon: definition.icon ?? ability.icon,
durationMs,
...(defaultPartyBuffFamily ? {
...(defaultPartyBuffFamily && !definition.exclusiveGroup ? {
uniqueBySource: false,
exclusiveGroup: `default-party-buff:${defaultPartyBuffFamily}`,
} : {}),
@@ -4699,19 +4701,50 @@ export const useCombatStore = create<CombatState>((set, get) => ({
},
applyDefaultPartyBuffs: (now = combatNow()) => {
get().synchronizeActors();
const state = get();
const partyMembers = usePartyStore.getState().members;
set((state) => {
const auras = state.auras.filter((aura) => !aura.definition.exclusiveGroup?.startsWith("gm-party-buff:"));
if (auras.length === state.auras.length) return state;
const maxHealth = auraAdjustedPlayerMaxHealth(state.classId, state.level, state.talentModifiers,
state.gearStats, state.raceId, state.secondaryClassId, auras);
const health = state.health <= 0 ? 0 : clamp(state.health + maxHealth - state.maxHealth, 1, maxHealth);
const actors = { ...state.actors };
if (actors[PLAYER_AURA_ENTITY_ID]) actors[PLAYER_AURA_ENTITY_ID] = {
...actors[PLAYER_AURA_ENTITY_ID], health, maxHealth,
};
for (const member of partyMembers) {
const actor = actors[member.id];
if (!actor) continue;
const base = deriveCharacterStats(member.classId, member.level, member.gearStats, member.raceId);
const delta = auraMaximumHealthBonus(base, auras, member.id)
- auraMaximumHealthBonus(base, state.auras, member.id);
const memberMaxHealth = Math.max(1, actor.maxHealth + delta);
actors[member.id] = {
...actor,
maxHealth: memberMaxHealth,
health: actor.health <= 0 ? 0 : clamp(actor.health + delta, 1, memberMaxHealth),
};
}
return { auras, health, maxHealth, actors };
});
get().synchronizeActors();
const state = get();
const rules = usePartyBuffPolicyStore.getState().config.rules;
const includePlayer = useDungeonSimulationStore.getState().sessionMode === "play";
const sources = [
...(includePlayer ? [{
id: PLAYER_AURA_ENTITY_ID,
classId: state.classId,
role: state.gearRole,
level: state.level,
abilities: state.abilities,
}] : []),
...partyMembers.filter((member) => member.health > 0).map((member) => ({
id: member.id,
classId: member.classId,
role: member.role,
level: member.level,
abilities: abilitiesForClass(member.classId),
abilities: abilitiesForCharacter(member.classId, member.secondaryClassId),
})),
];
const selected = new Map<string, {
@@ -4719,34 +4752,33 @@ export const useCombatStore = create<CombatState>((set, get) => ({
ability: AbilityDefinition;
effects: readonly Extract<AbilityEffect, { kind: "apply-aura" }>[];
potency: number;
scope: "party" | "tank" | "healer";
}>();
for (const source of sources) {
for (const catalogAbility of source.abilities) {
const family = DEFAULT_PARTY_BUFF_FAMILY.get(catalogAbility.name.toLowerCase());
if (!family || catalogAbility.passive || !isAbilityUnlocked(catalogAbility, source.level)) continue;
for (const rule of rules) {
for (const source of sources) {
const catalogAbility = source.abilities.find((ability) => ability.id === rule.abilityId);
if (!catalogAbility || !isAbilityUnlocked(catalogAbility, source.level)) continue;
const ability = abilityAtLevel(catalogAbility, source.level);
const effects = ability.effects.filter((effect): effect is Extract<AbilityEffect, { kind: "apply-aura" }> => (
effect.kind === "apply-aura" && effect.aura.disposition === "buff"
));
const effects = permanentBuffEffects(ability);
if (!effects.length) continue;
const family = DEFAULT_PARTY_BUFF_FAMILY.get(ability.name.toLowerCase()) ?? ability.id;
const potency = defaultPartyBuffPotency(effects);
if ((selected.get(family)?.potency ?? Number.NEGATIVE_INFINITY) >= potency) continue;
selected.set(family, { sourceId: source.id, ability, effects, potency });
selected.set(family, { sourceId: source.id, ability, effects, potency, scope: rule.scope });
}
}
const recipients = [
...(includePlayer ? [PLAYER_AURA_ENTITY_ID] : []),
...partyMembers.filter((member) => member.health > 0).map((member) => member.id),
];
for (const [family, buff] of selected) {
const recipients = sources.filter((source) => buff.scope === "party" || source.role === buff.scope)
.map((source) => source.id);
for (const recipientId of recipients) {
for (const effect of buff.effects) {
get().applyActorAura(buff.sourceId, recipientId, buff.ability, {
...effect,
aura: {
...effect.aura,
durationMs: null,
uniqueBySource: false,
exclusiveGroup: `default-party-buff:${family}`,
exclusiveGroup: `gm-party-buff:${family}`,
},
}, now);
}
@@ -6040,6 +6072,9 @@ export const useCombatStore = create<CombatState>((set, get) => ({
: [targetId ?? PLAYER_AURA_ENTITY_ID];
for (const recipientId of recipients.filter((id) => !effect.excludeCaster || id !== PLAYER_AURA_ENTITY_ID)) {
const previousAuras = work.auras;
const family = DEFAULT_PARTY_BUFF_FAMILY.get(ability.name.toLowerCase()) ?? ability.id;
if (previousAuras.some((aura) => aura.targetId === recipientId
&& aura.definition.exclusiveGroup === `gm-party-buff:${family}`)) continue;
if (effect.control && work.mobs[recipientId]?.characterDefender && work.mobs[recipientId].mechanicImmunities.includes(effect.control.kind as AzerothCoreMechanic)) continue;
const auraResult = applyCombatAura(previousAuras, {
definition: auraDefinition,
@@ -7396,6 +7431,11 @@ export const useCombatStore = create<CombatState>((set, get) => ({
const state = get();
if (!state.actors[sourceActorId] || (!state.actors[targetActorId] && !state.mobs[targetActorId])) return false;
if (ability.name === "Power Word: Shield" && hasWeakenedSoul(state.auras, targetActorId, now)) return false;
const family = DEFAULT_PARTY_BUFF_FAMILY.get(ability.name.toLowerCase()) ?? ability.id;
const gmGroup = `gm-party-buff:${family}`;
if (effect.aura.exclusiveGroup !== gmGroup && state.auras.some((aura) => (
aura.targetId === targetActorId && aura.definition.exclusiveGroup === gmGroup
))) return true;
const durationMs = effect.aura.durationMs;
const definition = auraDefinitionForAbility(effect.aura, ability, durationMs);
const applied = applyCombatAura(state.auras, {