From 390f0e3a5e66a640538d6710273c0eb9b4b09321 Mon Sep 17 00:00:00 2001 From: giteaadmin Date: Wed, 24 Jun 2026 09:37:03 +0000 Subject: [PATCH] fixgame 1 and 2 and 3 --- www/html/Admin/private/store.json | 18 ++--- www/html/Game/public/js/play.js | 129 ++++++++++++++++++++++++------ www/html/Game/public/play.html | 2 +- www/html/Game/server.js | 37 ++++++++- 4 files changed, 148 insertions(+), 38 deletions(-) diff --git a/www/html/Admin/private/store.json b/www/html/Admin/private/store.json index 7aba89d..7c6101b 100644 --- a/www/html/Admin/private/store.json +++ b/www/html/Admin/private/store.json @@ -51,9 +51,9 @@ "providerUserId": "p_1775109142385_wq7wfy1p32j", "notes": "auto: player-coins", "blocked": false, - "coins": 1358, + "coins": 1422, "createdAt": "2026-04-02T05:52:21+00:00", - "updatedAt": "2026-06-24T08:45:00+00:00", + "updatedAt": "2026-06-24T09:36:08+00:00", "daily": { "anchorMs": 1781197200000, "claimedDays": [ @@ -67,13 +67,13 @@ ], "lockUntilMs": 1782320400000 }, - "score": 1208, + "score": 1252, "scoreByCase": { "1": 16, "10": 358, "8": 238, "11": 20, - "13": 96, + "13": 140, "14": 20, "9": 40, "12": 272, @@ -619,21 +619,21 @@ "providerUserId": "p_1782016990238_0u37bv7pxlxs", "notes": "auto: player-coins", "blocked": false, - "coins": 58, + "coins": 124, "createdAt": "2026-06-21T04:43:11+00:00", - "updatedAt": "2026-06-24T08:45:00+00:00", + "updatedAt": "2026-06-24T09:36:08+00:00", "lobbyColorThemeIndex": 8, "lobbySkinToneIndex": 1, - "score": 48, + "score": 94, "scoreByCase": { - "13": 10, + "13": 56, "10": 20, "6": 8, "8": 10 }, "lbName": "MONE", "achievements": { - "d1_minigame_solver": 4 + "d1_minigame_solver": 9 } }, { diff --git a/www/html/Game/public/js/play.js b/www/html/Game/public/js/play.js index 2b7776a..40e8ff8 100644 --- a/www/html/Game/public/js/play.js +++ b/www/html/Game/public/js/play.js @@ -1065,6 +1065,10 @@ const GAUNTLET_CROWN_RUNWAY_BG_MAP_ID = 'mno9kb07'; /** หลังหยุดเลื่อนที่จุด FINISH — รอก่อน latch + โฟลว์สรุป (มิลลิวิ) */ const GAUNTLET_CROWN_RUNWAY_POST_STOP_MS = 2000; + /** ความเร็วเดินเข้าเส้นชัยตอนจบ (ช่อง/วินาที) — ค่อยๆ เดินแทนกระพริบ snap */ + const GAUNTLET_FINISH_WALK_TILES_PER_SEC = 7; + /** เพดานเวลาเดินเข้าเส้นชัย (กันค้างถ้าใครติด) — ต้อง < server grace (GAUNTLET_FINISH_WALK_MS) */ + const GAUNTLET_FINISH_WALK_MAX_MS = 2600; const GAUNTLET_CROWN_RUNWAY_BG_DEFAULT_START = BASE + '/img/editor-bg-mno9kb07/start.png'; const GAUNTLET_CROWN_RUNWAY_BG_DEFAULT_LOOP2 = BASE + '/img/editor-bg-mno9kb07/loop2.png'; const GAUNTLET_CROWN_RUNWAY_BG_DEFAULT_LOOP3 = BASE + '/img/editor-bg-mno9kb07/loop3.png'; @@ -1077,6 +1081,10 @@ let gauntletCrownRunwayBgFinishLatched = false; /** ส่งสัญญาณ "ถึงเส้นชัย" ให้ server แล้วหรือยัง (กันส่งซ้ำ) — server จะหยุด obstacle/collision */ let gauntletFinishPhaseSignaled = false; + /** กำลังเดินค่อยๆ เข้าเส้นชัย (ก่อน freeze) — true ระหว่างทุกคนทยอยเดินมาที่เส้น */ + let gauntletCrownRunwayWalkActive = false; + /** เวลาเริ่มเดินเข้าเส้นชัย (ms) — ใช้เพดานเวลา GAUNTLET_FINISH_WALK_MAX_MS */ + let gauntletCrownRunwayWalkStartMs = 0; /** >0 = หยุดเลื่อนแล้ว (timestamp ms) รอ POST_STOP ก่อน latch */ let gauntletCrownRunwayBgStripFreezeSinceMs = 0; /** คอลัมน์แผนที่ที่ล็อกตอน freeze — แนบตัวนำแทนขอบขวาสูงสุดของแมป */ @@ -1205,7 +1213,7 @@ } function gauntletCrownRunwayStripFrozenPlay() { - return gauntletCrownRunwayBgStripFreezeSinceMs > 0 || gauntletCrownRunwayBgFinishLatched; + return gauntletCrownRunwayWalkActive || gauntletCrownRunwayBgStripFreezeSinceMs > 0 || gauntletCrownRunwayBgFinishLatched; } /** จุดอ้างอิงกลางตัวนำ (map world px) — ใช้หยุด FINISH ตรงตัวละคร ไม่ใช่ขอบขวาแมป */ @@ -1267,6 +1275,73 @@ others.forEach((o, id) => { if (!playBotsEnabled() && isPreviewBotId(id)) return; snap(o); }); } + /** tx เป้าหมายที่เส้นชัย (คอลัมน์ที่ทุกคนต้องมายืน) — null ถ้าคำนวณไม่ได้ */ + function gauntletFinishTargetTxPlay() { + if (!mapData || !isGauntletCrownHeistMapPlay()) return null; + const ts = mapData.tileSize || 32; + const { cw } = getCharacterFootprintWH(mapData); + if (gauntletCrownRunwayFinishAlignLatchedWorldX != null) { + return gauntletCrownRunwayFinishAlignLatchedWorldX / ts - cw * 0.5; + } + let leadTx = -Infinity; + const consider = (ent) => { + if (!ent || ent.gauntletEliminated) return; + const tx = Number.isFinite(ent.tx) ? ent.tx : Number(ent.x); + if (Number.isFinite(tx)) leadTx = Math.max(leadTx, tx); + }; + consider(me); + others.forEach((o, id) => { if (!playBotsEnabled() && isPreviewBotId(id)) return; consider(o); }); + return (Number.isFinite(leadTx) && leadTx !== -Infinity) ? leadTx : null; + } + + /** เดินทุกคนที่ยังไม่ตาย "ค่อยๆ" เข้าหาเส้นชัยทีละเฟรม (แทน snap กระพริบ) + คืน true เมื่อทุกคนถึงเส้นแล้ว (เริ่ม freeze→จบเกมต่อ) */ + function gauntletWalkLivingToFinishStepPlay(dtSec) { + const targetTx = gauntletFinishTargetTxPlay(); + if (targetTx == null || !Number.isFinite(targetTx)) return true; + const step = Math.max(0.04, GAUNTLET_FINISH_WALK_TILES_PER_SEC * Math.max(0, Number(dtSec) || 0)); + const eps = 0.06; + let allArrived = true; + const walk = (ent) => { + if (!ent || ent.gauntletEliminated) return; + let x = Number.isFinite(ent.x) ? ent.x : (Number.isFinite(ent.tx) ? ent.tx : targetTx); + if (x < targetTx - eps) { + x = Math.min(targetTx, x + step); + ent.direction = 'right'; + ent.isWalking = true; + allArrived = false; + } else { + x = targetTx; /* ไม่ให้ใครเลยเส้นชัย (เลยมา → ดึงกลับมาที่เส้น) */ + ent.isWalking = false; + } + ent.x = x; + ent.tx = x; + }; + walk(me); + others.forEach((o, id) => { if (!playBotsEnabled() && isPreviewBotId(id)) return; walk(o); }); + return allArrived; + } + + /** เริ่มเฟส "เดินเข้าเส้นชัย": ล็อก align → snap scroll → แจ้ง server หยุด obstacle ทันที (กันตายระหว่างเดิน) + จากนั้น tick จะค่อยๆ เดินทุกคนมาที่เส้น แล้วค่อยเข้า freeze→จบเกม */ + function gauntletCrownRunwayBeginWalkToFinishPlay() { + if (gauntletCrownRunwayWalkActive || gauntletCrownRunwayBgStripFreezeSinceMs > 0 || gauntletCrownRunwayBgFinishLatched) return; + if (gauntletCrownRunwayFinishAlignLatchedWorldX == null) { + const leadAlign = gauntletCrownRunwayLeadingEntityAlignWorldXPlay(); + if (leadAlign != null) gauntletCrownRunwayFinishAlignLatchedWorldX = leadAlign; + } + gauntletCrownRunwaySnapScrollToFinishStopPlay(); + gauntletCrownRunwayWalkActive = true; + gauntletCrownRunwayWalkStartMs = Date.now(); + /* แจ้ง server ครั้งเดียว: เข้าโซนเส้นชัย → หยุด obstacle + collision (กันโดนชน/-10 ตอนกำลังเดินเข้าเส้น) + server จะรอ grace (GAUNTLET_FINISH_WALK_MS) ให้เดินครบก่อนค่อยจบ */ + if (!gauntletFinishPhaseSignaled) { + gauntletFinishPhaseSignaled = true; + try { socket.emit('gauntlet-finish-phase'); } catch (_e) { /* ignore */ } + } + try { syncGauntletCrownJumpButton(); } catch (_sj) { /* ignore */ } + } + /** * คอลัมน์บนกริดที่เส้น FINISH ต้องแนบ (map world px) @@ -1573,21 +1648,10 @@ gauntletCrownRunwayBgScrollPx = t; } - /** ลำดับการหยุดที่เส้นชัย: ล็อก align (ครั้งเดียว) → snap เป๊ะ → เริ่ม freeze → (latch+mission ทีหลังใน tick) */ + /** ลำดับการหยุดที่เส้นชัย: ล็อก align (ครั้งเดียว) → เริ่มเฟสเดินค่อยๆ เข้าเส้นชัย (ไม่ snap กระพริบ) + tick จะเดินทุกคนมาที่เส้นจนครบแล้วค่อยเข้า freeze→จบเกม */ function gauntletCrownRunwayBeginFinishStopPlay() { - if (gauntletCrownRunwayFinishAlignLatchedWorldX == null) { - const leadAlign = gauntletCrownRunwayLeadingEntityAlignWorldXPlay(); - if (leadAlign != null) gauntletCrownRunwayFinishAlignLatchedWorldX = leadAlign; - } - gauntletSnapLivingToFinishPlay(); /* ทุกคนที่ยังไม่ตายมายืนที่เส้นชัย ไม่มีใครเลยเส้น */ - gauntletCrownRunwaySnapScrollToFinishStopPlay(); - gauntletCrownRunwayBgStripFreezeSinceMs = Date.now(); - /* แจ้ง server ครั้งเดียว: ถึงเส้นชัยแล้ว → หยุด obstacle + collision (กัน -10 ตอน obstacle หายแล้ว) */ - if (!gauntletFinishPhaseSignaled) { - gauntletFinishPhaseSignaled = true; - try { socket.emit('gauntlet-finish-phase'); } catch (_e) { /* ignore */ } - } - try { syncGauntletCrownJumpButton(); } catch (_sj) { /* ignore */ } + gauntletCrownRunwayBeginWalkToFinishPlay(); try { draw(); } catch (_d) { /* ignore */ } } @@ -1639,6 +1703,8 @@ gauntletCrownRunwayBgScrollPx = 0; gauntletCrownRunwayBgFinishLatched = false; gauntletFinishPhaseSignaled = false; + gauntletCrownRunwayWalkActive = false; + gauntletCrownRunwayWalkStartMs = 0; gauntletCrownRunwayBgStripFreezeSinceMs = 0; gauntletCrownRunwayFinishAlignLatchedWorldX = null; gauntletCrownRunwayClientMissionShown = false; @@ -1684,6 +1750,20 @@ if (usesCrownLobbyShellPlay() && gauntletCrownPregamePhase !== 'live') return; if (gauntletCrownRunwayBgFinishLatched) { gauntletSnapLivingToFinishPlay(); return; } + /* เฟส "เดินเข้าเส้นชัย" — ค่อยๆ เดินทุกคนมาที่เส้นแทน snap กระพริบ แล้วค่อยเข้า freeze→จบ */ + if (gauntletCrownRunwayWalkActive) { + const forceDone = (Date.now() - gauntletCrownRunwayWalkStartMs) >= GAUNTLET_FINISH_WALK_MAX_MS; + const arrived = gauntletWalkLivingToFinishStepPlay(dtSec); + if (arrived || forceDone) { + gauntletCrownRunwayWalkActive = false; + gauntletSnapLivingToFinishPlay(); /* จัดเป๊ะที่เส้นชัยครั้งเดียว */ + gauntletCrownRunwayBgStripFreezeSinceMs = Date.now(); + } + try { syncGauntletCrownJumpButton(); } catch (_sj) { /* ignore */ } + try { draw(); } catch (_d) { /* ignore */ } + return; + } + if (gauntletCrownRunwayBgStripFreezeSinceMs > 0) { gauntletCrownRunwayMaintainFinishScrollPlay(); gauntletSnapLivingToFinishPlay(); /* ตรึงทุกคนที่ยังไม่ตายไว้ที่เส้นชัยทุกเฟรม กันบอทไหลหลุด */ @@ -1719,16 +1799,7 @@ } if (gauntletCrownRunwayBgMapEligiblePlay() && gauntletCrownRunwayScrollStripStopZoneReachedPlay()) { - if (gauntletCrownRunwayFinishAlignLatchedWorldX == null) { - const leadAlign = gauntletCrownRunwayLeadingEntityAlignWorldXPlay(); - if (leadAlign != null) gauntletCrownRunwayFinishAlignLatchedWorldX = leadAlign; - } - gauntletSnapLivingToFinishPlay(); /* ทุกคนที่ยังไม่ตายมายืนที่เส้นชัย ไม่มีใครเลยเส้น */ - gauntletCrownRunwaySnapScrollToFinishStopPlay(); - gauntletCrownRunwayBgStripFreezeSinceMs = Date.now(); - try { - syncGauntletCrownJumpButton(); - } catch (_sj) { /* ignore */ } + gauntletCrownRunwayBeginWalkToFinishPlay(); /* เริ่มเดินค่อยๆ เข้าเส้นชัย (แทน snap+freeze ทันที) */ try { draw(); } catch (_d) { /* ignore */ } @@ -20473,7 +20544,8 @@ nickname: p.nickname || 'ผู้เล่น', characterId: p.characterId ?? null, spawnJoinOrder: 0, - playTint: playTintForPreviewBotId(p.id) || resolvePlayTintForPeer(p.id, p), + /* สีจาก lobby (theme/skin index ที่ server พ่วงมาใน gauntlet-sync) ก่อน — กันได้สี hash สุ่มไม่ตรง lobbyB */ + playTint: playTintFromJoinPeer(p) || playTintForPreviewBotId(p.id) || resolvePlayTintForPeer(p.id, p), gauntletJumpTicks: 0, gauntletJumpVis: 0, gauntletScore: 0, gauntletEliminated: !!p.gauntletEliminated, jumpSurviveEliminated: false, @@ -20493,6 +20565,9 @@ if (Number.isFinite(py)) o.ty = py; if (p.direction) o.direction = p.direction; if (o.characterId == null && p.characterId != null) o.characterId = p.characterId; + /* รีเฟรชสีจาก lobby index ที่ server ส่งมา — กัน peer ที่เคยได้สี hash (re-create เก่า) ค้างสีผิด */ + const lobbyTint = playTintFromJoinPeer(p); + if (lobbyTint) o.playTint = lobbyTint; const jt = Number(p.gauntletJumpTicks); o.gauntletJumpTicks = Number.isFinite(jt) ? jt : 0; if (o.gauntletJumpVis == null) o.gauntletJumpVis = o.gauntletJumpTicks; @@ -20554,6 +20629,8 @@ gauntletEndsAtMs = null; gauntletCrownRunwayBgFinishLatched = false; gauntletFinishPhaseSignaled = false; + gauntletCrownRunwayWalkActive = false; + gauntletCrownRunwayWalkStartMs = 0; gauntletCrownRunwayBgStripFreezeSinceMs = 0; gauntletCrownRunwayFinishAlignLatchedWorldX = null; gauntletCrownRunwayClientMissionShown = false; diff --git a/www/html/Game/public/play.html b/www/html/Game/public/play.html index f8bc839..50132e3 100644 --- a/www/html/Game/public/play.html +++ b/www/html/Game/public/play.html @@ -5371,7 +5371,7 @@ - +
v —