feat(arena): add switchAndCastSkill and hero class avatar overlay to ?arena=1

This commit is contained in:
troytt 2026-09-22 03:30:22 +00:00
parent 550787cb0a
commit a727343eb3
1 changed files with 36 additions and 6 deletions

View File

@ -3842,7 +3842,7 @@ export async function initBrowserArenaMode(): Promise<void> {
const { WorldArena } = await import('../game/engine/world-arena.ts')
const registry = await getSharedDataRegistry('samples/d2')
const arena = new WorldArena({
let arena = new WorldArena({
registry,
classCode: classParam,
skillId,
@ -3851,10 +3851,13 @@ export async function initBrowserArenaMode(): Promise<void> {
if (autocast) {
arena.triggerCast()
arena.stepTicks(15)
}
const syncWindowArena = () => {
const snap = arena.getDebugState()
const snap = arena.getDebugState() as ReturnType<typeof arena.getDebugState> & {
switchAndCastSkill?: (nextClassCode: string, nextSkillId: number, nextSlvl?: number) => unknown
}
const origTrigger = snap.triggerCast
const origStep = snap.stepTicks
snap.triggerCast = (tx?: number, ty?: number) => {
@ -3868,6 +3871,19 @@ export async function initBrowserArenaMode(): Promise<void> {
syncWindowArena()
renderArenaVisualOverlay(arena)
}
snap.switchAndCastSkill = (nextClassCode: string, nextSkillId: number, nextSlvl = 20) => {
arena = new WorldArena({
registry,
classCode: nextClassCode,
skillId: nextSkillId,
slvl: nextSlvl,
})
arena.triggerCast()
arena.stepTicks(15)
syncWindowArena()
renderArenaVisualOverlay(arena)
return arena.getDebugState()
}
;(window as unknown as { __d2webArena?: unknown }).__d2webArena = snap
}
@ -3892,13 +3908,27 @@ export async function initBrowserArenaMode(): Promise<void> {
const cx = w * 0.5
const cy = h * 0.52
// 1. Draw Active Aura / Cast Ring around Hero
// 1. Draw Active Aura / Cast Ring & Class Hero Avatar around Hero
const classHue = ((dbg.skillId * 37) % 360)
ctx.save()
ctx.strokeStyle = dbg.activeStates.length > 0 ? 'rgba(255, 210, 80, 0.85)' : 'rgba(110, 180, 255, 0.7)'
ctx.lineWidth = 3
ctx.strokeStyle = dbg.activeStates.length > 0 ? 'rgba(255, 210, 80, 0.9)' : `hsla(${classHue}, 85%, 65%, 0.85)`
ctx.lineWidth = 3.5
ctx.beginPath()
ctx.ellipse(cx, cy + 16, 62, 32, 0, 0, Math.PI * 2)
ctx.ellipse(cx, cy + 16, 62 + (dbg.skillId % 18), 32 + (dbg.skillId % 9), 0, 0, Math.PI * 2)
ctx.stroke()
// Hero class figure + active weapon/spell glow
ctx.fillStyle = `hsla(${classHue}, 75%, 55%, 0.85)`
ctx.strokeStyle = '#fff3d1'
ctx.lineWidth = 2
ctx.beginPath()
ctx.arc(cx, cy - 6, 18, 0, Math.PI * 2)
ctx.fill()
ctx.stroke()
ctx.fillStyle = '#ffe9a8'
ctx.font = 'bold 11px monospace'
ctx.textAlign = 'center'
ctx.fillText(`${dbg.classCode.toUpperCase()}:${dbg.charToken.toUpperCase()} [${dbg.playerAnimMode}:${dbg.playerAnimFrame}]`, cx, cy + 35)
ctx.restore()
// 2. Draw Target Dummies (`dummy-normal`, `dummy-undead`, `dummy-demon`, `dummy-immune`)