Update Healer Man server

This commit is contained in:
phenom committed 2026-10-02 10:38:12 -04:00
1 parent 4c768fbec6
commit b16821e92e
330 files changed
+35406 -1760

No files matched your search

+55 -8
View File
@@ -1,9 +1,14 @@
import { PLAYER_AGGRO_ID } from "../game/aggro";
import { useCombatStore } from "../game/combatStore";
export function SummonFrames({ now }: { readonly now: number }) {
const summons = useCombatStore((state) => state.summons);
const selectedFriendlyActorId = useCombatStore((state) => state.selectedFriendlyActorId);
const selectedTargetId = useCombatStore((state) => state.selectedTargetId);
const selectFriendlyActor = useCombatStore((state) => state.selectFriendlyActor);
const commandHunterPet = useCombatStore((state) => state.commandHunterPet);
const setHunterPetReactMode = useCombatStore((state) => state.setHunterPetReactMode);
const setHunterPetGrowlAutocast = useCombatStore((state) => state.setHunterPetGrowlAutocast);
if (!summons.length) return null;
return (
<section className="summon-frames" aria-label="Pets, totems, and summons">
@@ -12,18 +17,60 @@ export function SummonFrames({ now }: { readonly now: number }) {
const remaining = summon.expiresAt >= Number.MAX_SAFE_INTEGER
? "∞"
: `${Math.max(0, Math.ceil((summon.expiresAt - now) / 1_000))}s`;
const playerHunterPet = Boolean(summon.hunterPet && summon.ownerActorId === PLAYER_AGGRO_ID);
const command = summon.hunterPetCommand ?? "follow";
const reactMode = summon.hunterPetReactMode ?? "defensive";
return (
<button
type="button"
<div
className={`summon-frame summon-frame--${summon.kind}${selectedFriendlyActorId === summon.id ? " is-selected" : ""}`}
key={summon.id}
aria-pressed={selectedFriendlyActorId === summon.id}
onClick={() => selectFriendlyActor(selectedFriendlyActorId === summon.id ? null : summon.id)}
>
<header><strong>{summon.name}</strong><span>{summon.kind} · {remaining}</span></header>
<div><i style={{ width: `${healthPercent}%` }} /></div>
<small>{Math.ceil(summon.health)} / {summon.maxHealth}</small>
</button>
<button
type="button"
className="summon-frame__select"
aria-pressed={selectedFriendlyActorId === summon.id}
onClick={() => selectFriendlyActor(selectedFriendlyActorId === summon.id ? null : summon.id)}
>
<header><strong>{summon.name}</strong><span>{summon.kind} · {remaining}</span></header>
<div><i style={{ width: `${healthPercent}%` }} /></div>
<small>{Math.ceil(summon.health)} / {summon.maxHealth}</small>
</button>
{playerHunterPet && (
<div className="hunter-pet-controls" aria-label={`${summon.name} controls`}>
<div className="hunter-pet-controls__commands" role="group" aria-label="Pet command">
{(["attack", "follow", "stay"] as const).map((petCommand) => (
<button
key={petCommand}
type="button"
aria-pressed={command === petCommand}
disabled={petCommand === "attack" && !selectedTargetId}
onClick={() => commandHunterPet(summon.id, petCommand)}
>{petCommand}</button>
))}
</div>
<label className="hunter-pet-controls__react">
<span>React</span>
<select
aria-label="Pet reaction"
value={reactMode}
onChange={(event) => setHunterPetReactMode(summon.id, event.currentTarget.value as "defensive" | "aggressive" | "passive")}
>
<option value="defensive">Defensive</option>
<option value="aggressive">Aggressive</option>
<option value="passive">Passive</option>
</select>
</label>
<label className="hunter-pet-controls__growl">
<input
type="checkbox"
checked={Boolean(summon.hunterPetGrowlAutocastEnabled)}
onChange={(event) => setHunterPetGrowlAutocast(summon.id, event.currentTarget.checked)}
/>
Growl auto
</label>
</div>
)}
</div>
);
})}
</section>