diff --git a/www/html/Game/public/img/gauntlet-assets/score.png b/www/html/Game/public/img/gauntlet-assets/score.png
index 7d629c9..db271f3 100644
Binary files a/www/html/Game/public/img/gauntlet-assets/score.png and b/www/html/Game/public/img/gauntlet-assets/score.png differ
diff --git a/www/html/Game/public/js/play.js b/www/html/Game/public/js/play.js
index 4a6509d..0311eff 100644
--- a/www/html/Game/public/js/play.js
+++ b/www/html/Game/public/js/play.js
@@ -960,6 +960,7 @@
return alignWorld;
}
+
/**
* คอลัมน์บนกริดที่เส้น FINISH ต้องแนบ (map world px)
* gauntletCrownRunwayBg.finishAlignMapTileX | finishAlignMapTileFrac — ถ้าไม่ตั้ง ใช้ตำแหน่งตัวนำ
@@ -9589,7 +9590,7 @@
if (mg2Jump) {
const hud = document.getElementById('play-cyber-hud');
if (hud && hud.classList.contains('play-cyber-hud--quiz-tf-mock')) updateQuizTfMockScale(hud);
- else syncMg2MockJumpButtonBoundsPlay();
+ syncMg2MockJumpButtonBoundsPlay();
} else {
btn.classList.remove('mg2-jump');
}
@@ -11134,13 +11135,80 @@
const jm = Math.max(4, jumpTicksMax || 16);
const a = Math.max(0, Math.min(jm, Number(air) || 0));
const t = a / jm;
- const peakAt = 0.28;
- if (t >= peakAt) {
- const span = 1 - peakAt;
- const u = span > 0 ? (t - peakAt) / span : 0;
- return Math.max(0, 1 - u * u * 1.2);
+ /* อาร์คกระโดดนุ่มแบบ design (rn-jump): sine โค้งสมมาตร ease-in-out peak กลางอากาศ
+ เดิม: ขาขึ้น quadratic / ขาลง linear (อสมมาตร peak ~72% เวลา → ขาลงกระตุก) */
+ const p = Math.max(0, Math.min(1, 1 - t)); /* 0 = เริ่มกระโดด, 1 = แตะพื้น */
+ return Math.sin(Math.PI * p);
+ }
+
+ /* ===== Minigame-2: ชื่อ+คะแนนใต้ตัวละคร + เลข -10 เป็น DOM overlay (sync world→screen) แทนวาดบน canvas =====
+ เรียกทุกเฟรมจาก draw() (ส่ง worldToScreen/zDraw/tileSize เข้ามา) — container map buffer→display ด้วย transform:scale */
+ const gauntletDomLabelPool = new Map(); /* id -> .gnt-label (pool ไว้ reuse) */
+ const gauntletPenaltySeenById = new Map(); /* id -> ts penalty ล่าสุด (กัน spawn float ซ้ำ) */
+ function syncGauntletNameDom(worldToScreenFn, zDrawVal, tileSizePx) {
+ const ov = document.getElementById('gauntlet-name-overlay');
+ if (!ov) return;
+ const live = isGauntletCrownHeistMapPlay() && gauntletCrownPregamePhase === 'live';
+ if (!live || typeof worldToScreenFn !== 'function') {
+ if (!ov.classList.contains('is-hidden')) {
+ ov.classList.add('is-hidden');
+ gauntletDomLabelPool.forEach((el) => { if (el.parentNode) el.parentNode.removeChild(el); });
+ gauntletDomLabelPool.clear();
+ }
+ return;
}
- return Math.min(1, t / peakAt);
+ ov.classList.remove('is-hidden');
+ const canvas = document.getElementById('game-canvas');
+ const stage = document.getElementById('play-canvas-stage');
+ if (!canvas || !stage) return;
+ const cr = canvas.getBoundingClientRect();
+ const srect = stage.getBoundingClientRect();
+ const dispScale = canvas.width > 0 ? cr.width / canvas.width : 1;
+ ov.style.left = Math.round(cr.left - srect.left) + 'px';
+ ov.style.top = Math.round(cr.top - srect.top) + 'px';
+ ov.style.width = canvas.width + 'px';
+ ov.style.height = canvas.height + 'px';
+ ov.style.transform = 'scale(' + dispScale + ')';
+ const fp = (typeof getCharacterFootprintWH === 'function') ? getCharacterFootprintWH(mapData) : { cw: 1, ch: 1 };
+ const cwv = fp.cw || 1, chv = fp.ch || 1;
+ function v(n) { const x = Number(n); return Number.isFinite(x) ? x : 0; }
+ const seen = new Set();
+ function place(id, ent, isMe) {
+ if (!ent) return;
+ if (typeof shouldGauntletCrownHeistSkipAvatarDrawPlay === 'function'
+ && shouldGauntletCrownHeistSkipAvatarDrawPlay(ent, isMe, 0, 0)) return;
+ seen.add(id);
+ const air = isMe ? (meGauntletJumpVis || 0) : ((ent.gauntletJumpVis != null ? ent.gauntletJumpVis : ent.gauntletJumpTicks) || 0);
+ const liftWorldY = air > 0 ? gauntletLiftHeightNorm(air, gauntletRuntimeJumpTicks) * tileSizePx * 0.52 : 0;
+ const cxWorld = (v(ent.x) + cwv * 0.5) * tileSizePx;
+ const cyBottomWorld = (v(ent.y) + chv) * tileSizePx - liftWorldY;
+ const scr = worldToScreenFn(cxWorld, cyBottomWorld);
+ const sx = scr[0], sy = scr[1];
+ /* ชื่อ/คะแนนใต้ตัวละคร: ตัดออกตาม mock — mock โชว์ชื่อ+คะแนนเฉพาะ "แถบคะแนนบน" เท่านั้น ไม่มีใต้ตัวละคร
+ (กันดูเหมือน 2 layer ทับกัน) — คงไว้เฉพาะ -10 penalty float ที่ mock มี */
+ const pen = Number(ent.gauntletCrownPenaltyFxUntil) || 0;
+ /* -10 float ต้องอยู่ "ใต้แถบคะแนนบน" เท่านั้น — กันผู้เล่นที่จุดเริ่ม (project ใกล้แถบคะแนน เช่น AFK) ทำ float โผล่ทับ SCORE label */
+ var sbEl = document.querySelector('.play-cyber-scoreboard');
+ var sbBottomBuf = sbEl ? ((sbEl.getBoundingClientRect().bottom - cr.top) / (dispScale || 1) + 6) : 0;
+ if (pen > (gauntletPenaltySeenById.get(id) || 0) && (sy - 28) > sbBottomBuf) {
+ gauntletPenaltySeenById.set(id, pen);
+ /* -10 float = design asset score-.png (รูป "-10" สำเร็จรูป) ไม่ใช่ text สไตล์เอง */
+ const pf = document.createElement('img');
+ pf.className = 'gnt-pen';
+ pf.src = GAUNTLET_CROWN_SCORE_POP_URL;
+ pf.alt = '-10';
+ pf.decoding = 'async';
+ pf.style.left = Math.round(sx) + 'px';
+ pf.style.top = Math.round(sy - 28) + 'px';
+ ov.appendChild(pf);
+ setTimeout(function () { if (pf.parentNode) pf.parentNode.removeChild(pf); }, 900);
+ } else if (pen > (gauntletPenaltySeenById.get(id) || 0)) {
+ /* อยู่บริเวณแถบคะแนน — บันทึกว่าเห็นแล้ว ไม่ต้องสร้าง float (กัน spawn ซ้ำตอนเลื่อนลงมา) */
+ gauntletPenaltySeenById.set(id, pen);
+ }
+ }
+ if (others && typeof others.forEach === 'function') others.forEach((o, id) => place(id, o, false));
+ place('__me', me, true);
}
function getGauntletObsDrawPositionsAt(nowMs) {
@@ -11454,6 +11522,42 @@
if (socket && socket.connected) socket.emit('gauntlet-crown-lobby-ready', { ready: true });
}
+ /** Minigame-2 mno9kb07 — HOW TO PLAY ใช้ layout mock 01-howto (canvas = mg-bg) */
+ function gauntletCrownHowtoUsesMg2LayoutPlay() {
+ return !!isGauntletCrownHeistMapPlay();
+ }
+ function getGauntletCrownHowtoStatusEl() {
+ if (gauntletCrownHowtoUsesMg2LayoutPlay()) {
+ return document.getElementById('gauntlet-crown-howto-status-mg2');
+ }
+ return document.getElementById('gauntlet-crown-howto-status');
+ }
+ function getGauntletCrownHowtoBtnEl() {
+ if (gauntletCrownHowtoUsesMg2LayoutPlay()) {
+ return document.getElementById('btn-gch-ready-mg2');
+ }
+ return document.getElementById('btn-gch-ready');
+ }
+ function setPlayMg2HowtoLivePlay(on) {
+ document.documentElement.classList.toggle('play-mg2-howto-live', !!on);
+ }
+ function clearGchMg2OverlayBoundsPlay(ov) {
+ ov = ov || document.getElementById('gauntlet-crown-howto-overlay');
+ if (!ov) return;
+ ['position', 'left', 'top', 'width', 'height', 'right', 'bottom', 'transform'].forEach((p) => {
+ ov.style.removeProperty(p);
+ });
+ }
+ function dismissGauntletCrownHowtoOverlayPlay() {
+ const howto = document.getElementById('gauntlet-crown-howto-overlay');
+ if (howto) {
+ howto.classList.add('is-hidden');
+ setPlayMg2HowtoLivePlay(false);
+ clearGchMg2OverlayBoundsPlay(howto);
+ }
+ gauntletCrownHowtoVisible = false;
+ }
+
/** ภารกิจคำถาม mng8a80o — Ready Status / ปุ่ม แบบเดียวกับ Mega Virus (gauntlet-crown-lobby-sync) */
function updateQuizQuestionMissionHowtoHud() {
if (!isQuizQuestionMissionUiMapPlay() || quizQuestionMissionPhase !== 'howto') return;
@@ -11476,8 +11580,8 @@
}
function updateGauntletCrownHowtoHud() {
- const st = document.getElementById('gauntlet-crown-howto-status');
- const btn = document.getElementById('btn-gch-ready');
+ const st = getGauntletCrownHowtoStatusEl();
+ const btn = getGauntletCrownHowtoBtnEl();
if (!btn || !usesCrownLobbyShellPlay() || gauntletCrownPregamePhase !== 'howto') return;
const humans = quizCarryPregameHumanIds();
const tot = Math.max(1, quizCarryPregameTotalPlayers());
@@ -11488,6 +11592,15 @@
}
const humansReady = humans.length > 0 && humans.every((id) => !!gauntletCrownLobbyReadyMap[id]);
btn.classList.toggle('is-start-phase', humansReady);
+ if (gauntletCrownHowtoUsesMg2LayoutPlay()) {
+ const btnImg = document.getElementById('btn-gch-ready-mg2-img');
+ if (btnImg) {
+ btnImg.src = humansReady
+ ? (missionMockHudAssetUrl('btn-start.png') || (BASE + '/img/gauntlet-assets/btn-start.png'))
+ : (missionMockHudAssetUrl('btn-ready.png') || (BASE + '/img/gauntlet-assets/btn-ready.png'));
+ btnImg.alt = humansReady ? 'START' : 'READY';
+ }
+ }
btn.classList.toggle('is-read-only', !isMePlayHost());
btn.disabled = !isMePlayHost();
btn.setAttribute('aria-pressed', humansReady ? 'false' : ((myId && gauntletCrownLobbyReadyMap[String(myId)]) ? 'true' : 'false'));
@@ -11507,9 +11620,7 @@
applyGauntletPreviewSpawnLayout(false);
}
trySnapGauntletCrownRunwayScrollToSpawnsPlay();
- const howto = document.getElementById('gauntlet-crown-howto-overlay');
- if (howto) howto.classList.add('is-hidden');
- gauntletCrownHowtoVisible = false;
+ dismissGauntletCrownHowtoOverlayPlay();
const cd = document.getElementById('gauntlet-crown-countdown');
const numEl = document.getElementById('gauntlet-crown-countdown-num');
function applyMegaBalloonLiveStartPlay() {
@@ -11600,6 +11711,11 @@
if (!ov) return;
gauntletCrownHowtoVisible = true;
ov.classList.remove('is-hidden');
+ if (isGauntletCrownHeistMapPlay()) {
+ setPlayMg2HowtoLivePlay(true);
+ updateGchTfMockScale(ov);
+ trySnapGauntletCrownRunwayScrollToSpawnsPlay();
+ }
if (socket && socket.connected) socket.emit('gauntlet-crown-lobby-sync-request');
gauntletCrownSyncGuestReadyIfNeeded();
updateGauntletCrownHowtoHud();
@@ -11683,7 +11799,7 @@
if (nick !== 0) return nick;
return String(a.id).localeCompare(String(b.id));
});
- const top = baseRows.slice(0, 5);
+ const top = baseRows.slice(0, 6); /* Last Light รองรับ 6 ผู้เล่น — summary ต้องครบ 6 */
const ranked = top.map((row, idx) => {
const pos = idx + 1;
const rankBonus = gauntletCrownRankBonusLocal(pos);
@@ -11757,6 +11873,17 @@
eliminated: !!o.gauntletEliminated,
});
});
+ /* รวมตัวเรา (human) ถ้ายังไม่อยู่ — บาง mission (preview/จาก server) มีแต่บอท ทำให้ตัวเราตกหายจาก summary */
+ if (myId != null && !seen.has(String(myId))) {
+ seen.add(String(myId));
+ baseRows.push({
+ id: myId,
+ nickname: (me.nickname || nick || 'คุณ').trim() || 'คุณ',
+ characterId: me.characterId ?? null,
+ baseScore: me.gauntletEliminated ? 0 : Math.max(0, Number(me.gauntletScore) | 0),
+ eliminated: !!me.gauntletEliminated,
+ });
+ }
baseRows.sort((a, b) => {
if (b.baseScore !== a.baseScore) return b.baseScore - a.baseScore;
@@ -11764,7 +11891,7 @@
if (nick !== 0) return nick;
return String(a.id).localeCompare(String(b.id));
});
- const top = baseRows.slice(0, 5);
+ const top = baseRows.slice(0, 6); /* Last Light รองรับ 6 ผู้เล่น — summary ต้องครบ 6 รวมตัวเรา (เดิม 5 ตัดคนคะแนนต่ำสุด/ตายออก) */
const ranked = top.map((row, idx) => {
const pos = idx + 1;
const rankBonus = gauntletCrownRankBonusLocal(pos);
@@ -19075,6 +19202,10 @@
/* ตัวละครที่ไม่มีไฟล์เลเยอร์สี (เช่น defaultChar) — compose คืน Image ดิบ → crop หน้าจากรูปดิบตรง ๆ กันช่องว่าง */
let drawSrc = srcCanvas;
if (!drawSrc && raw && raw.complete && raw.naturalWidth > 0 && raw.naturalHeight > 0) {
+ /* ตัวที่มีไฟล์เลเยอร์สี (tintable) แต่ composite ยังไม่พร้อม หรือ API characters ยังโหลดไม่เสร็จ →
+ คืน '' ให้ applyCyberHudScoreAvatarImgWithRetry retry รอเลเยอร์โหลด (avatar bot จะไม่ถูกรับจนกว่าจะเป็น data URL ที่ย้อมสีแล้ว)
+ อย่า fallback raw ที่ "ไม่มีสี" ไม่งั้น avatar ทุกคนเหมือนกัน = "สีไม่ขึ้น"; ใช้ raw เฉพาะตัวที่ API ยืนยันว่าไม่มีเลเยอร์ (defaultChar) */
+ if (playCharLayerApi.status !== 'done' || playCharLayerFromApi(cid) === true) return '';
drawSrc = raw;
}
if (!drawSrc) return '';
@@ -19336,6 +19467,7 @@
if (Math.abs(s - _quizTfScaleLast) < 0.0005
&& root.dataset.qtfStackW === String(Math.round(cw))
&& root.dataset.qtfStackH === String(Math.round(ch))) {
+ syncMg2MockJumpButtonBoundsPlay(r, s);
return;
}
_quizTfScaleLast = s;
@@ -19406,10 +19538,33 @@
const s = missionMockOverlayScalePlay();
if (s > 0 && isFinite(s)) ov.style.setProperty('--gcm-tf-scale', String(s));
}
- /* popup HOW TO PLAY (01-howto) — scale stage 1920×1080 ตามสูตรเดียวกัน */
+ /* popup HOW TO PLAY (01-howto) — scale stage 1920×1080 · MG2 ยึด #play-canvas-stack เหมือน HUD */
function updateGchTfMockScale(ov) {
ov = ov || document.getElementById('gauntlet-crown-howto-overlay');
if (!ov) return;
+ const mg2 = ov.classList.contains('gch-mg2-mock');
+ if (mg2) {
+ const stack = document.getElementById('play-canvas-stack');
+ if (!stack) return;
+ const r = stack.getBoundingClientRect();
+ const cw = Math.max(1, r.width || stack.clientWidth || 0);
+ const ch = Math.max(1, r.height || stack.clientHeight || 0);
+ const s = Math.min(cw / 1920, ch / 1080);
+ if (!(s > 0 && isFinite(s))) return;
+ ov.style.position = 'fixed';
+ ov.style.left = Math.round(r.left) + 'px';
+ ov.style.top = Math.round(r.top) + 'px';
+ ov.style.width = Math.round(cw) + 'px';
+ ov.style.height = Math.round(ch) + 'px';
+ ov.style.right = 'auto';
+ ov.style.bottom = 'auto';
+ ov.style.transform = 'none';
+ ov.style.setProperty('--gch-tf-scale', String(s));
+ const stage = ov.querySelector('.gch-mg2-stage');
+ if (stage) stage.setAttribute('aria-hidden', 'false');
+ return;
+ }
+ clearGchMg2OverlayBoundsPlay(ov);
const s = missionMockOverlayScalePlay();
if (s > 0 && isFinite(s)) ov.style.setProperty('--gch-tf-scale', String(s));
}
@@ -19503,7 +19658,8 @@
/** แถบ SCORE แนวนอน (mno9kb07) — ใช้รูปแบบเดียวกับ quiz_carry / พรีวิว editor */
root.classList.toggle(
'play-cyber-hud--gauntlet-crown-strip',
- !!(on && (isGauntletCrownHeistMapPlay() || isQuizCarry())),
+ !!(on && (isGauntletCrownHeistMapPlay() || isQuizCarry())
+ && !(missionMockOn && getMissionMockHudSkinPlay() === 'gauntlet_crown')),
);
root.classList.toggle('play-cyber-hud--score-flush-left', !!(on && isQuizCarry()));
root.classList.toggle('play-cyber-hud--jump-mission-hide-score', !!isJumpSurviveMissionUiMapPlay());
@@ -19895,7 +20051,9 @@
return a.y - b.y;
});
- const cap = stripScoreHud ? (isQuizCarry() ? 8 : 6) : 8;
+ /* Minigame-2 รองรับสูงสุด 6 ผู้เล่น (GAUNTLET_MAX_PLAYERS) — แถบคะแนนต้องโชว์ครบ 6 รวมตัวเรา
+ (เดิม cap 5 ตาม mockup ที่วาดตัวอย่าง 5 คน ทำให้ตัวเราคะแนนต่ำสุดถูกตัดออก) */
+ const cap = mg2MockHud ? 6 : (stripScoreHud ? (isQuizCarry() ? 8 : 6) : 8);
let hudRows = rows.slice(0, Math.min(cap, rows.length));
if (stripScoreHud) {
const mi = hudRows.findIndex((row) => row.isMe);
@@ -20719,11 +20877,17 @@
ctx.font = '10px sans-serif';
ctx.textAlign = 'center';
const nameBase = name || '';
+ /* gauntlet (Last Light) live: ชื่อ/คะแนน/-10 ใช้ DOM overlay (syncGauntletNameDom) — ไม่วาดบน canvas */
+ /* crown map (Minigame-2): ไม่วาดชื่อ/คะแนน/-10 ใต้ตัวละครบน canvas "ทุกเฟส" (ตรง mock — โชว์เฉพาะแถบคะแนนบน)
+ เดิมเช็คเฉพาะ phase==='live' → ตอน summary/howto canvas วาดชื่อกลับมา ทับแถบคะแนน (ดูเหมือน avatar ซ้อน) */
+ const gntDomLabel = isGauntletCrownHeistMapPlay();
const withScore = isGauntlet() && typeof gauntletScoreLabel === 'number' && gauntletScoreLabel >= 0
? (nameBase + ' · ' + gauntletScoreLabel)
: nameBase;
- ctx.fillText(withScore, sx, sy + 10);
- if (isGauntletCrownHeistMapPlay()
+ if (!gntDomLabel) ctx.fillText(withScore, sx, sy + 10);
+ if (!gntDomLabel
+ && isGauntletCrownHeistMapPlay()
+ && gauntletCrownPregamePhase === 'live'
&& typeof crownPenaltyFxUntil === 'number'
&& crownPenaltyFxUntil > timeMs) {
const penImg = ensureGauntletCrownScorePenaltyImgPlay();
@@ -20847,7 +21011,10 @@
const ga = _quizGhostScreenAnchorPlay(axO, ayO, worldToScreen, zDraw);
drawQuizWrongGhostOverlayPlay(ga.sx, ga.sy, ga.sizeH, id, peerName);
} else {
- drawAvatar(axO, ayO, false, peerName, o.characterId, faceDirOther, otherWalk, ot, (o.gauntletJumpVis != null ? o.gauntletJumpVis : o.gauntletJumpTicks) || 0, o.gauntletScore || 0, quizCarrySignForEntity(o), isGauntletCrownHeistMapPlay() ? (o.gauntletCrownPenaltyFxUntil || 0) : 0);
+ drawAvatar(axO, ayO, false, peerName, o.characterId, faceDirOther, otherWalk, ot, (o.gauntletJumpVis != null ? o.gauntletJumpVis : o.gauntletJumpTicks) || 0,
+ (isGauntletCrownHeistMapPlay() && gauntletCrownPregamePhase === 'live') ? (o.gauntletScore || 0) : undefined,
+ quizCarrySignForEntity(o),
+ (isGauntletCrownHeistMapPlay() && gauntletCrownPregamePhase === 'live') ? (o.gauntletCrownPenaltyFxUntil || 0) : 0);
}
if (botOut) ctx.restore();
} else {
@@ -20863,11 +21030,16 @@
const gam = _quizGhostScreenAnchorPlay(axMe, ayMe, worldToScreen, zDraw);
drawQuizWrongGhostOverlayPlay(gam.sx, gam.sy, gam.sizeH, myId, me.nickname + meTag);
} else {
- drawAvatar(axMe, ayMe, true, me.nickname + meTag, me.characterId, faceDirMe, meWalking, mt, meGauntletJumpVis, me.gauntletScore || 0, quizCarrySignForEntity(me), isGauntletCrownHeistMapPlay() ? (me.gauntletCrownPenaltyFxUntil || 0) : 0);
+ drawAvatar(axMe, ayMe, true, me.nickname + meTag, me.characterId, faceDirMe, meWalking, mt, meGauntletJumpVis,
+ (isGauntletCrownHeistMapPlay() && gauntletCrownPregamePhase === 'live') ? (me.gauntletScore || 0) : undefined,
+ quizCarrySignForEntity(me),
+ (isGauntletCrownHeistMapPlay() && gauntletCrownPregamePhase === 'live') ? (me.gauntletCrownPenaltyFxUntil || 0) : 0);
}
if (isJumpSurvive() && jumpSurviveEliminated) ctx.restore();
}
});
+ /* Minigame-2: อัปเดต DOM overlay (ชื่อ/คะแนน/-10) ให้ตรงตำแหน่งตัวละครบน canvas */
+ try { syncGauntletNameDom(worldToScreen, zDraw, tileSize); } catch (eGntDom) { /* ignore */ }
}
/* ไอคอนคำถามพิเศษในฉาก (วาดทับ map/ผู้เล่น) + ตรวจการเดินชน */
if (specialQuizIcon) {
@@ -20896,10 +21068,8 @@
ctx.font = 'bold 14px sans-serif';
ctx.textAlign = 'left';
if (isGauntletCrownHeistMapPlay()) {
- ctx.fillText('พรมแดงสุดท้าย | คะแนน ' + (me.gauntletScore || 0) + ' · ชน -10 · ขอบซ้ายตาย · สูงสุด 6 คน', 10, 24);
- ctx.font = '12px sans-serif';
- ctx.fillStyle = '#c0caf5';
- ctx.fillText('Space / W / ↑ = กระโดด · เลน + เลเซอร์ · จบเกมมีโบนัสอันดับ + เกรดทีม', 10, 42);
+ /* Minigame-2 (Last Light): ใช้ cyber HUD + DOM overlay แล้ว — ไม่วาด debug text (คะแนน · ชน -10 · ขอบซ้ายตาย) บน canvas
+ (เดิมโผล่มุมซ้ายบนทับ SCORE label เวลา useCyberPlayHud() = false ใน preview embed) */
} else {
ctx.fillText('พรมแดงสุดท้าย | คะแนน: ' + (me.gauntletScore || 0) + ' (ข้าม 1 ชิ้น +1) · สูงสุด 6 คน', 10, 24);
ctx.font = '12px sans-serif';
@@ -21508,9 +21678,7 @@
})();
(function wireGauntletCrownHowtoPrimary() {
- const btn = document.getElementById('btn-gch-ready');
- if (!btn) return;
- btn.addEventListener('click', () => {
+ function onHowtoPrimaryClick() {
if (isJumpSurviveMissionUiMapPlay()) {
if (jumpSurviveMissionPhase !== 'howto') return;
const humans = quizCarryPregameHumanIds();
@@ -21654,6 +21822,10 @@
gauntletCrownLobbyReadyMap[sid] = next;
updateGauntletCrownHowtoHud();
socket.emit('gauntlet-crown-lobby-ready', { ready: next });
+ }
+ ['btn-gch-ready', 'btn-gch-ready-mg2'].forEach((id) => {
+ const btn = document.getElementById(id);
+ if (btn) btn.addEventListener('click', onHowtoPrimaryClick);
});
})();
diff --git a/www/html/Game/public/play.html b/www/html/Game/public/play.html
index c6e0ac5..b517701 100644
--- a/www/html/Game/public/play.html
+++ b/www/html/Game/public/play.html
@@ -21,6 +21,9 @@
+
+
+