From 39b91fa81e66fe67b01a54c28a525a3c1c3ef117 Mon Sep 17 00:00:00 2001 From: giteaadmin Date: Mon, 4 May 2026 08:09:53 +0000 Subject: [PATCH] minigame 1 add more design 1.2 --- www/html/Game/public/js/play.js | 99 ++++++++++++++++++++++++------ www/html/Game/public/js/version.js | 2 +- www/html/Game/public/play.html | 7 ++- www/html/Game/server.js | 17 +++-- 4 files changed, 99 insertions(+), 26 deletions(-) diff --git a/www/html/Game/public/js/play.js b/www/html/Game/public/js/play.js index b23c27c..3d3e327 100644 --- a/www/html/Game/public/js/play.js +++ b/www/html/Game/public/js/play.js @@ -4726,21 +4726,29 @@ gauntletCrownHowtoVisible = true; ov.classList.remove('is-hidden'); const st = document.getElementById('gauntlet-crown-howto-status'); - if (st) { - st.textContent = ''; - st.classList.remove('gch-status--jumper'); - st.classList.add('is-hidden'); - } + if (st) st.classList.remove('gch-status--jumper'); const btn = document.getElementById('btn-gch-ready'); - if (btn) { - const humans = quizCarryPregameHumanIds(); - const soleHuman = humans.length === 1; - const canGo = soleHuman || isMePlayHost(); - btn.classList.remove('is-start-phase'); - btn.classList.toggle('is-read-only', !canGo); - btn.disabled = !canGo; - btn.title = canGo ? 'READY — เริ่มนับถอยหลัง' : 'รอโฮสต์ · Wait for host'; - btn.setAttribute('aria-pressed', 'false'); + const humans = quizCarryPregameHumanIds(); + const totPlayers = Math.max(1, quizCarryPregameTotalPlayers()); + /** ผู้เล่นจริงในห้องคนเดียว และไม่มีบอท/peer อื่นในนับรวม — เท่านั้นที่ข้าม lobby */ + const soleParticipant = totPlayers === 1; + if (soleParticipant) { + if (st) { + st.textContent = ''; + st.classList.add('is-hidden'); + } + if (btn) { + const canGo = isMePlayHost() || humans.length === 1; + btn.classList.remove('is-start-phase'); + btn.classList.toggle('is-read-only', !canGo); + btn.disabled = !canGo; + btn.title = canGo ? 'READY — เริ่มนับถอยหลัง' : 'รอโฮสต์ · Wait for host'; + btn.setAttribute('aria-pressed', 'false'); + } + } else { + if (socket && socket.connected) socket.emit('gauntlet-crown-lobby-sync-request'); + gauntletCrownSyncGuestReadyIfNeeded(); + updateQuizQuestionMissionHowtoHud(); } } @@ -8117,7 +8125,8 @@ } function gauntletCrownSyncGuestReadyIfNeeded() { - if (gauntletCrownPregamePhase !== 'howto') return; + const inQuizQuestionHowto = isQuizQuestionMissionUiMapPlay() && quizQuestionMissionPhase === 'howto'; + if (gauntletCrownPregamePhase !== 'howto' && !inQuizQuestionHowto) return; if (myId == null || isMePlayHost()) return; const sid = String(myId); if (gauntletCrownLobbyReadyMap[sid]) return; @@ -8125,6 +8134,27 @@ if (socket && socket.connected) socket.emit('gauntlet-crown-lobby-ready', { ready: true }); } + /** ภารกิจคำถาม mng8a80o — Ready Status / ปุ่ม แบบเดียวกับ Mega Virus (gauntlet-crown-lobby-sync) */ + function updateQuizQuestionMissionHowtoHud() { + if (!isQuizQuestionMissionUiMapPlay() || quizQuestionMissionPhase !== 'howto') return; + const st = document.getElementById('gauntlet-crown-howto-status'); + const btn = document.getElementById('btn-gch-ready'); + if (!st || !btn) return; + const humans = quizCarryPregameHumanIds(); + const tot = Math.max(1, quizCarryPregameTotalPlayers()); + const num = gauntletCrownPregameReadyNumerator(); + st.classList.remove('is-hidden'); + st.textContent = 'Ready Status : ' + num + '/' + tot; + const humansReady = humans.length > 0 && humans.every((id) => !!gauntletCrownLobbyReadyMap[id]); + btn.classList.toggle('is-start-phase', humansReady); + btn.classList.toggle('is-read-only', !isMePlayHost()); + btn.disabled = !isMePlayHost(); + btn.setAttribute('aria-pressed', humansReady ? 'false' : ((myId && gauntletCrownLobbyReadyMap[String(myId)]) ? 'true' : 'false')); + btn.title = isMePlayHost() + ? (humansReady ? 'START' : ((myId && gauntletCrownLobbyReadyMap[String(myId)]) ? 'ยกเลิก READY' : 'READY')) + : (humansReady ? 'START (โฮสต์เท่านั้น)' : 'READY (โฮสต์เท่านั้น)'); + } + function updateGauntletCrownHowtoHud() { const st = document.getElementById('gauntlet-crown-howto-status'); const btn = document.getElementById('btn-gch-ready'); @@ -11628,10 +11658,12 @@ }); if (previewFillBots) rebalancePreviewBots(); if (quizCarryPregameActive && isQuizCarry()) updateQuizCarryPregameHud(); + if (isQuizQuestionMissionUiMapPlay() && quizQuestionMissionPhase === 'howto') updateQuizQuestionMissionHowtoHud(); }); socket.on('host-changed', (d) => { if (d && d.hostId != null) playHostId = d.hostId; if (quizCarryPregameActive && isQuizCarry()) updateQuizCarryPregameHud(); + if (isQuizQuestionMissionUiMapPlay() && quizQuestionMissionPhase === 'howto') updateQuizQuestionMissionHowtoHud(); }); socket.on('quiz-carry-lobby-sync', (d) => { if (!d || typeof d.readyMap !== 'object') return; @@ -11651,9 +11683,16 @@ if (gauntletCrownPregamePhase === 'howto') { gauntletCrownSyncGuestReadyIfNeeded(); updateGauntletCrownHowtoHud(); + } else if (isQuizQuestionMissionUiMapPlay() && quizQuestionMissionPhase === 'howto') { + gauntletCrownSyncGuestReadyIfNeeded(); + updateQuizQuestionMissionHowtoHud(); } }); socket.on('gauntlet-crown-lobby-started', () => { + if (isQuizQuestionMissionUiMapPlay() && quizQuestionMissionPhase === 'howto') { + beginQuizQuestionMissionCountdownThenRun(); + return; + } if (!usesCrownLobbyShellPlay()) return; beginGauntletCrownCountdownThenRun(); }); @@ -11760,6 +11799,7 @@ if (!data || isPreviewBotId(data.id)) return; others.delete(data.id); if (previewFillBots) rebalancePreviewBots(); + if (isQuizQuestionMissionUiMapPlay() && quizQuestionMissionPhase === 'howto') updateQuizQuestionMissionHowtoHud(); }); socket.on('chat', (data) => { const box = document.getElementById('chat-messages'); @@ -14797,9 +14837,32 @@ } if (isQuizQuestionMissionUiMapPlay()) { if (quizQuestionMissionPhase !== 'howto') return; - const humansQ = quizCarryPregameHumanIds(); - if (!(humansQ.length === 1 || isMePlayHost())) return; - beginQuizQuestionMissionCountdownThenRun(); + const humans = quizCarryPregameHumanIds(); + const totPlayers = Math.max(1, quizCarryPregameTotalPlayers()); + if (totPlayers === 1) { + beginQuizQuestionMissionCountdownThenRun(); + return; + } + if (!isMePlayHost()) { + if (myId == null) return; + const sid = String(myId); + const next = !gauntletCrownLobbyReadyMap[sid]; + gauntletCrownLobbyReadyMap[sid] = next; + updateQuizQuestionMissionHowtoHud(); + if (socket && socket.connected) socket.emit('gauntlet-crown-lobby-ready', { ready: next }); + return; + } + if (myId == null) return; + const humansReady = humans.length > 0 && humans.every((id) => !!gauntletCrownLobbyReadyMap[id]); + if (humansReady) { + socket.emit('gauntlet-crown-lobby-start', {}, (r) => { if (!r || !r.ok) { /* ignore */ } }); + return; + } + const sidH = String(myId); + const nextH = !gauntletCrownLobbyReadyMap[sidH]; + gauntletCrownLobbyReadyMap[sidH] = nextH; + updateQuizQuestionMissionHowtoHud(); + if (socket && socket.connected) socket.emit('gauntlet-crown-lobby-ready', { ready: nextH }); return; } if (isStackTowerMissionUiMapPlay()) { diff --git a/www/html/Game/public/js/version.js b/www/html/Game/public/js/version.js index fad0f59..5a29e61 100644 --- a/www/html/Game/public/js/version.js +++ b/www/html/Game/public/js/version.js @@ -1,6 +1,6 @@ // ทุกครั้งที่มีการเพิ่มหรือเปลี่ยน ให้เพิ่ม v +0.0001 // หลังแก้ค่าแล้วต้อง copy ไป path ที่ Nginx ชี้ (หรือรัน copy-frogger-files-only.sh) ถึงจะเห็นบนเว็บ -window.APP_VERSION = '0.0191'; +window.APP_VERSION = '0.0195'; document.addEventListener('DOMContentLoaded', function () { var t = document.querySelector('.version-tag'); if (t) t.textContent = 'v ' + window.APP_VERSION; diff --git a/www/html/Game/public/play.html b/www/html/Game/public/play.html index 4c927b9..8e996f4 100644 --- a/www/html/Game/public/play.html +++ b/www/html/Game/public/play.html @@ -1071,6 +1071,9 @@ margin: 0; max-width: 100%; text-align: center; + font-weight: 800; + color: #f8fafc; + font-size: clamp(0.75rem, 2vw, 0.9rem); text-shadow: 0 1px 4px rgba(0, 0, 0, 0.85), 0 0 14px rgba(0, 0, 0, 0.55); } .gch-inner.gch-inner--art .btn-gch-ready { @@ -2014,8 +2017,8 @@ - - + +
v —
diff --git a/www/html/Game/server.js b/www/html/Game/server.js index d483a3e..25cb65c 100644 --- a/www/html/Game/server.js +++ b/www/html/Game/server.js @@ -2908,8 +2908,15 @@ function isBalloonBossMissionShellSpace(space) { return !!(md && md.gameType === 'balloon_boss'); } +/** ภารกิจคำถาม quiz + แมป mng8a80o — lobby READY เดียวกับ Mega Virus */ +function isQuizQuestionMissionShellSpace(space) { + if (!space || !space.mapId || String(space.mapId) !== SUSPECT_INVESTIGATION_QUIZ_MAP_ID) return false; + const md = (space.mapId && maps.get(space.mapId)) || space.mapData; + return !!(md && md.gameType === 'quiz'); +} + function isCrownLobbyShellSpace(space) { - return isGauntletCrownHeistMapBySpace(space) || isBalloonBossMissionShellSpace(space); + return isGauntletCrownHeistMapBySpace(space) || isBalloonBossMissionShellSpace(space) || isQuizQuestionMissionShellSpace(space); } function newBalloonBossShellGauntletRunState() { @@ -3703,7 +3710,7 @@ io.on('connection', (socket) => { io.to(spaceId).emit('gauntlet-crown-lobby-sync', { readyMap: { ...space.gauntletCrownLobbyReady } }); } startGauntletTicker(spaceId, space); - } else if (isBalloonBossMissionShellSpace(space)) { + } else if (isBalloonBossMissionShellSpace(space) || isQuizQuestionMissionShellSpace(space)) { if (!space.gauntletCrownLobbyReady || typeof space.gauntletCrownLobbyReady !== 'object') space.gauntletCrownLobbyReady = {}; space.gauntletCrownLobbyReady[socket.id] = false; if (!space.gauntletRun) space.gauntletRun = newBalloonBossShellGauntletRunState(); @@ -3752,7 +3759,7 @@ io.on('connection', (socket) => { if (mdJoin.gameType === 'gauntlet' && space.gauntletRun) { joinCb.gauntletEndsAt = space.gauntletRun.endsAt != null ? space.gauntletRun.endsAt : null; } - if (isBalloonBossMissionShellSpace(space) && space.gauntletRun) { + if ((isBalloonBossMissionShellSpace(space) || isQuizQuestionMissionShellSpace(space)) && space.gauntletRun) { joinCb.gauntletCrownRunHeld = !!space.gauntletRun.crownRunHeld; } if (typeof cb === 'function') cb(joinCb); @@ -4017,7 +4024,7 @@ io.on('connection', (socket) => { gauntletEliminated: !!p.gauntletEliminated, })); } - if (md && isBalloonBossMissionShellSpace(space)) { + if (md && (isBalloonBossMissionShellSpace(space) || isQuizQuestionMissionShellSpace(space))) { if (!space.gauntletCrownLobbyReady || typeof space.gauntletCrownLobbyReady !== 'object') space.gauntletCrownLobbyReady = {}; space.peers.forEach((_p, id) => { space.gauntletCrownLobbyReady[id] = false; @@ -4032,7 +4039,7 @@ io.on('connection', (socket) => { peersSnap: peersSnap || undefined, }; if (peersSnap) gameStartPayload.gauntletEndsAt = gauntletEndsAtEmit != null ? gauntletEndsAtEmit : null; - if (mapId && maps.has(mapId) && isBalloonBossMissionShellSpace(space)) { + if (mapId && maps.has(mapId) && (isBalloonBossMissionShellSpace(space) || isQuizQuestionMissionShellSpace(space))) { const grs = space.gauntletRun; gameStartPayload.gauntletCrownRunHeld = !!(grs && grs.crownRunHeld); }