human fight sequence fix
This commit is contained in:
@@ -48,8 +48,8 @@ const {
|
||||
humanChallenge, humanAnswer, humanTimer, humanSubmitted, humanChoices,
|
||||
roundCooldown, pendingChallengeData,
|
||||
applyChallenge, submitChoice, startHumanPolling, stopHumanPolling,
|
||||
startCooldown, clearChallenge, resetState: resetChallengeState, handleSSEChallenge,
|
||||
setEntrancePlaying,
|
||||
startCooldown, clearChallenge, stopCooldown, resetState: resetChallengeState, handleSSEChallenge,
|
||||
setEntrancePlaying, animatingRound,
|
||||
} = challenge
|
||||
|
||||
// Live scene state
|
||||
@@ -187,6 +187,10 @@ async function initLiveScene() {
|
||||
}
|
||||
|
||||
// --- SSE event wiring ---
|
||||
// Track in-progress round animation so fight_end can wait for it
|
||||
let _roundEndPromise: Promise<void> | null = null
|
||||
let _fightEnding = false
|
||||
|
||||
function wireSSE() {
|
||||
connectSSE({
|
||||
onReaction(data) {
|
||||
@@ -208,9 +212,12 @@ function wireSSE() {
|
||||
handleSSEChallenge(sseData)
|
||||
},
|
||||
onRoundEnd(data) {
|
||||
handleRoundEnd(data).catch(() => {})
|
||||
if (_fightEnding) return // Don't start new round animations after fight is ending
|
||||
_roundEndPromise = handleRoundEnd(data).catch(() => {})
|
||||
},
|
||||
onFightEnd(data) {
|
||||
if (_fightEnding) return // Deduplicate (only process first fight_end)
|
||||
_fightEnding = true
|
||||
handleFightEnd(data).catch(() => {})
|
||||
},
|
||||
})
|
||||
@@ -238,6 +245,8 @@ async function handleRoundEnd(data: any) {
|
||||
|
||||
liveCurrentRound.value = round
|
||||
clearChallenge()
|
||||
// Block new challenges during animation (SSE/polling will queue them)
|
||||
animatingRound.value = true
|
||||
|
||||
// Update HP (server 0-200, display 0-100)
|
||||
liveHpA.value = Math.round((hp.a / 200) * 100)
|
||||
@@ -304,7 +313,11 @@ async function handleRoundEnd(data: any) {
|
||||
}
|
||||
|
||||
currentChallengeInfo.value = null
|
||||
startCooldown(3)
|
||||
animatingRound.value = false
|
||||
// Don't start cooldown if fight is ending (fight_end handler takes over)
|
||||
if (!_fightEnding) {
|
||||
startCooldown(3)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleFightEnd(data: any) {
|
||||
@@ -314,8 +327,15 @@ async function handleFightEnd(data: any) {
|
||||
return
|
||||
}
|
||||
|
||||
// Wait for any in-progress round animation to finish before KO sequence
|
||||
if (_roundEndPromise) {
|
||||
await _roundEndPromise
|
||||
_roundEndPromise = null
|
||||
}
|
||||
|
||||
clearChallenge()
|
||||
roundCooldown.value = 0
|
||||
animatingRound.value = false
|
||||
stopCooldown()
|
||||
|
||||
if (data.winnerId) {
|
||||
if (data.winnerId === fd.botA.id) liveHpB.value = 0
|
||||
@@ -400,6 +420,8 @@ async function toggleLiveSound() {
|
||||
// Watch route param changes
|
||||
watch(() => route.params.fightId, async (newId) => {
|
||||
if (!newId || newId === fightId.value) return
|
||||
_fightEnding = false
|
||||
_roundEndPromise = null
|
||||
cleanupPolling()
|
||||
stopHumanPolling()
|
||||
stopAllAudio()
|
||||
@@ -464,6 +486,15 @@ watch(liveFightData, async (val) => {
|
||||
}
|
||||
})
|
||||
|
||||
// Destroy live scene when fight transitions from live to finished (prevents kaplay instance leak)
|
||||
watch(isLive, (live, wasLive) => {
|
||||
if (!live && wasLive && liveScene) {
|
||||
liveScene.destroy()
|
||||
liveScene = null
|
||||
liveSceneReady.value = false
|
||||
}
|
||||
})
|
||||
|
||||
// --- Mount / Unmount ---
|
||||
onMounted(async () => {
|
||||
// Auto-unlock AudioContext on first user interaction (critical for mobile TTS)
|
||||
@@ -524,6 +555,8 @@ async function fightAgain(botId: string) {
|
||||
if (isRequeueing.value) return
|
||||
isRequeueing.value = true
|
||||
replayDone.value = false
|
||||
_fightEnding = false
|
||||
_roundEndPromise = null
|
||||
resetChallengeState()
|
||||
humanFightDone.value = false
|
||||
humanFightResult.value = null
|
||||
@@ -576,6 +609,21 @@ async function matchmake(botId: string) {
|
||||
if (isRequeueing.value) return
|
||||
isRequeueing.value = true
|
||||
replayDone.value = false
|
||||
_fightEnding = false
|
||||
_roundEndPromise = null
|
||||
resetChallengeState()
|
||||
humanFightDone.value = false
|
||||
humanFightResult.value = null
|
||||
if (liveScene) { liveScene.destroy(); liveScene = null }
|
||||
liveSceneReady.value = false
|
||||
liveFightData.value = null
|
||||
liveLogItems.value = []
|
||||
liveHpA.value = 100
|
||||
liveHpB.value = 100
|
||||
liveCurrentRound.value = 0
|
||||
stopHumanPolling()
|
||||
stopPolling()
|
||||
disconnectSSE()
|
||||
try {
|
||||
const res = await fetch(`/api/fights/matchmake/${botId}`, { method: 'POST' })
|
||||
if (res.ok) {
|
||||
|
||||
Reference in New Issue
Block a user