import { useMemo } from "react"; import type { CharacterProfile } from "../app/types"; import { arenaCharacterAbilities, arenaAbilityIsLearned, createArenaCharacterKit } from "../game/arenaCharacter"; import { ACTION_CONTROLS, actionBindingId, type ActionBindingLayer, type ActionBindingControl } from "../game/actionBindings"; import type { ArenaActorSnapshot } from "../game/arenaTypes"; import { actionKeyLabel } from "../game/uiLayout"; import { currentUiDevice, useUiLayoutStore } from "../game/uiLayoutStore"; import { ActionBar, ActionIcon, type ActionBarItem, type ActionBarItems } from "./ActionBar"; import { useInputBindingLabels } from "../input/useInputBindingLabels"; import { useArenaStore } from "../game/arenaStore"; import { AbilityTooltipTarget } from "./AbilityTooltip"; const PC_ACTION_CONTROLS = ["face-bottom", "face-left", "face-top", "face-right", "r1", "r2", "dpad-left", "dpad-right"] as const; export function ArenaActionBar({ character, actor, layer, inputMode, blocked, onCast, feedback }: { character: CharacterProfile; actor: ArenaActorSnapshot | null; layer: ActionBindingLayer; inputMode: "keyboard" | "gamepad"; blocked: boolean; onCast: (abilityId: string) => void; feedback: string; }) { const ui = useUiLayoutStore(); const bindingLabel = useInputBindingLabels(); const level = actor?.level ?? character.level; const kit = useMemo(() => createArenaCharacterKit(character, level), [character, level]); const abilities = useMemo(() => arenaCharacterAbilities(character, level), [character, level]); const layout = ui.preferences.current[currentUiDevice()]; const bindings = actor?.actionBindings ?? kit.actionBindings; const desktopBars = layout.wowBars ? layout.bars.slice(0, layout.barCount).map((bar) => ({ ...bar, slots: bar.slots.map((slot) => ({ ...slot, label: actionKeyLabel(slot.key) })) })) : [{ columns: 8, slots: PC_ACTION_CONTROLS.map((control) => ({ abilityId: bindings[actionBindingId(layer, control)], label: bindingLabel("pc", `ability:${layer}:${control}`) })) }]; const items = Object.fromEntries(abilities.map((ability): [string, ActionBarItem] => { const learned = actor?.abilityIds ? actor.abilityIds.includes(ability.id) : arenaAbilityIsLearned(ability, character, level); const remaining = Math.max(actor?.cooldowns[ability.id] ?? 0, actor?.gcdRemainingMs ?? 0) / 1000; return [ability.id, { id: ability.id, name: ability.name, iconUrl: ability.icon, shortLabel: ability.sigil, description: ability.description, target: ability.target, resourceCost: ability.cost.amount, resourceLabel: kit.resource.name, cooldownDuration: Math.max(ability.cooldownMs, ability.gcdMs) / 1000, cooldownRemaining: remaining, cooldownSeconds: ability.cooldownMs / 1000, castSeconds: ability.castTimeMs / 1000, range: ability.range.max, disabled: blocked || !actor?.alive || !learned || remaining > 0 || actor.effects.some((effect) => effect.id.startsWith("casting:")), lockedUntilLevel: learned ? undefined : ability.unlockLevel, }]; })); const casting = actor?.effects.find((effect) => effect.id.startsWith("casting:")); const castName = casting ? items[casting.id.slice(8)]?.name : null; const castBinding = (control: ActionBindingControl) => { const id = bindings[actionBindingId(layer, control)]; if (id) onCast(id); }; return