diff --git a/src/app/components/LiveRadar.tsx b/src/app/components/LiveRadar.tsx index 31f5716..89da528 100644 --- a/src/app/components/LiveRadar.tsx +++ b/src/app/components/LiveRadar.tsx @@ -344,8 +344,48 @@ export default function LiveRadar({ matchId }: Props) { if (kind.includes('molotov') || kind.includes('incen') || kind.includes('fire')) removeEffect('fire', { id }) markEnded() } + syncNadePaths() } + // Server: sofort nach Spawn eines Projektils + const handleNadeCreate = (m: any) => { + const id = String(m?.id ?? '') + if (!id) return + const kind = String(m?.kind ?? '').toLowerCase() + const pos = m.pos ?? {} + const t = Number(m?.t ?? Date.now()) + + upsertNadeTrace({ id, kind, t, pos, state: 'spawn' }) + syncNadePaths() + } + + // Server: periodischer Snapshot aller aktiven Projektile + const handleNadesSnapshot = (snap: any) => { + const t = Number(snap?.t ?? Date.now()) + const arr = Array.isArray(snap?.nades) ? snap.nades : [] + for (const n of arr) { + const id = String(n?.id ?? '') + if (!id) continue + const kind = String(n?.kind ?? '').toLowerCase() + const pos = n.pos ?? {} + // optional: Geschwindigkeit als „s“ (Segment) mitgeben – hier nicht zwingend nötig + upsertNadeTrace({ id, kind, t, pos }) + } + syncNadePaths() + } + + // Server: Detonation (HE/Flash/Smoke/Molly/Decoy) + const handleNadeExplode = (m: any) => { + const id = m?.id != null ? String(m.id) : '' + const kind = String(m?.kind ?? '').toLowerCase() + const pos = m.pos ?? m + const t = Number(m?.t ?? Date.now()) + upsertNadeTrace({ id, kind, t, pos, state: 'detonate' }) + // Effekte bei Smoke / Fire starten (wird in upsertNadeTrace ohnehin getan) + syncNadePaths() + } + + const connect = () => { if (!alive) return setWsStatus('connecting') @@ -357,8 +397,12 @@ export default function LiveRadar({ matchId }: Props) { let msg: any = null try { msg = JSON.parse(ev.data as string) } catch {} - const handleEvent = (e: any) => { + const dispatch = (e: any) => { if (!e) return + + if (e.type === 'nade_create') { handleNadeCreate(e); return } + if (e.type === 'nades' && Array.isArray(e.nades)) { handleNadesSnapshot(e); return } + if (e.type === 'nade_explode') { handleNadeExplode(e); return } // Map wechseln if (e.type === 'map' || e.type === 'level' || e.map) { @@ -378,6 +422,8 @@ export default function LiveRadar({ matchId }: Props) { // Grenade-Traces if (e.type === 'nade' || e.kind || e.nade || e.weapon) { upsertNadeTrace(e) + syncNadePaths() + return } // Spieler @@ -405,7 +451,7 @@ export default function LiveRadar({ matchId }: Props) { const yawDegRaw = deriveYawDeg(rawYaw, prev, x, y) // Sanftes Smoothing, damit kleine Änderungen sichtbar & stabil sind - const YAW_SMOOTH = 0.01 + const YAW_SMOOTH = 0.30 const yawDeg = prev ? lerpAngleDeg(prev.yaw, yawDegRaw, YAW_SMOOTH) : yawDegRaw const p: PlayerState = { @@ -420,11 +466,11 @@ export default function LiveRadar({ matchId }: Props) { } if (Array.isArray(msg)) { - for (const e of msg) handleEvent(e) + for (const e of msg) dispatch(e) } else if (msg?.type === 'tick' && Array.isArray(msg.players)) { - for (const p of msg.players) handleEvent(p) + for (const p of msg.players) dispatch(p) } else { - handleEvent(msg) + dispatch(msg) } scheduleFlush()