From 0f50ea58b862134a54ad63310498027628dd8f2e Mon Sep 17 00:00:00 2001 From: giteaadmin Date: Sat, 2 May 2026 06:56:22 +0000 Subject: [PATCH] minigame 1 question 1.3 --- www/html/Game/public/js/play.js | 41 ++++++++++++++++++++++++++++++++- www/html/Game/public/play.html | 2 +- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/www/html/Game/public/js/play.js b/www/html/Game/public/js/play.js index 95de77f..99173be 100644 --- a/www/html/Game/public/js/play.js +++ b/www/html/Game/public/js/play.js @@ -84,9 +84,17 @@ /** จนกว่าโหลด /api/characters — placeholder ชั่วคราวก่อน join */ const LEGACY_PLACEHOLDER_CHARACTER_ID = 'Chatest'; let firstCharacterDefaultResolved = null; + /** รหัสตัวละครจาก GET /api/characters — ใช้สลับบอทพรีวิวให้ไม่ซ้ำรูปกับผู้เล่น */ + let playCharacterIdRoster = []; const firstCharacterDefaultPromise = fetch(BASE + '/api/characters') .then((r) => r.json()) .then((list) => { + playCharacterIdRoster = []; + if (Array.isArray(list)) { + list.forEach((c) => { + if (c && c.id) playCharacterIdRoster.push(String(c.id)); + }); + } if (Array.isArray(list) && list.length > 0 && list[0] && list[0].id) { firstCharacterDefaultResolved = String(list[0].id); } else { @@ -95,6 +103,12 @@ }) .catch(() => { firstCharacterDefaultResolved = ''; + playCharacterIdRoster = []; + }) + .finally(() => { + try { + if (previewFillBots && mapData) rebalancePreviewBots(); + } catch (e) { /* map ยังไม่พร้อม */ } }); const lobbyLevelParam = params.get('lobbyLevel'); const lobbyCaseParam = params.get('case'); @@ -451,9 +465,11 @@ .then((r) => r.json()) .then((list) => { const map = Object.create(null); + playCharacterIdRoster = []; if (Array.isArray(list)) { list.forEach((c) => { if (!c || !c.id) return; + playCharacterIdRoster.push(String(c.id)); map[c.id] = !!c.hasLayerFiles; if (Array.isArray(c.layers) && c.layers.length) { const st = new Set(); @@ -470,6 +486,7 @@ playCharLayerApi = { status: 'done', map }; }) .catch(() => { + playCharacterIdRoster = []; playCharLayerApi = { status: 'done', map: Object.create(null) }; }); } @@ -854,6 +871,17 @@ } return getStoredCharacterId(); } + + /** บอทพรีวิว: เลือกรหัสคนละตัวจาก roster (ไม่ซ้ำผู้เล่นถ้ามีตัวเลือก) */ + function pickPreviewBotCharacterId(botSlotIndex) { + const idx = Math.max(0, Math.floor(Number(botSlotIndex)) || 0); + const roster = playCharacterIdRoster; + const humanId = String(getPlayCharacterId() || ''); + if (!roster.length) return humanId || LEGACY_PLACEHOLDER_CHARACTER_ID; + const alts = roster.filter((id) => id !== humanId); + const pool = alts.length ? alts : roster.slice(); + return pool[idx % pool.length] || humanId || roster[0]; + } const MOVE_SPEED = 0.15; /** quiz_carry — ค่าเริ่มเมื่อไม่มี override จาก Admin (รหัสฉากตรงกันใน quiz-settings.json) */ const QUIZ_CARRY_WALK_SPEED_MULT = 1.42; @@ -2482,7 +2510,7 @@ x, y, tx: x, ty: y, direction: ['down', 'up', 'left', 'right'][Math.floor(Math.random() * 4)], nickname: 'บอท', - characterId: getPlayCharacterId(), + characterId: pickPreviewBotCharacterId(botIds.length), spawnJoinOrder: joinIdx, playTint: playTintFromPeerId(id), botTier, @@ -2514,6 +2542,10 @@ const tag = o.botTier === 'sharp' ? '(ฉลาด)' : o.botTier === 'weak' ? '(พลาดบ่อย)' : '(กลาง)'; o.nickname = 'บอท ' + (++k) + ' ' + tag; }); + [...others.keys()].filter(isPreviewBotId).sort().forEach((bid, botIdx) => { + const o = others.get(bid); + if (o) o.characterId = pickPreviewBotCharacterId(botIdx); + }); if (mapData.gameType === 'quiz_battle' && quizBattlePathModeActive(mapData)) { [...others.keys()].filter(isPreviewBotId).forEach((bid) => { const o = others.get(bid); @@ -7148,15 +7180,22 @@ bonusEl.appendChild(pl); } } + const gcmHead = document.getElementById('gcm-heading'); + if (gcmHead) { + if (mission && mission.uiSkin === 'question_mission') gcmHead.classList.add('sr-only'); + else gcmHead.classList.remove('sr-only'); + } ov.classList.remove('is-hidden'); function goLobby() { ov.classList.add('is-hidden'); + if (gcmHead) gcmHead.classList.remove('sr-only'); window.location.href = 'room-lobby.html?space=' + encodeURIComponent(spaceId) + '&nick=' + encodeURIComponent(nick); } if (btn) { btn.onclick = function () { if (previewMode && editorEmbedReturn) { ov.classList.add('is-hidden'); + if (gcmHead) gcmHead.classList.remove('sr-only'); if (mission && mission.uiSkin === 'question_mission') { cancelQuizCarryResultEndAfterTimeup(); hideQuizCarryTimeupOnDeskLayer(); diff --git a/www/html/Game/public/play.html b/www/html/Game/public/play.html index 3b2f11c..b56fc2a 100644 --- a/www/html/Game/public/play.html +++ b/www/html/Game/public/play.html @@ -1966,7 +1966,7 @@ - +
v —