design and bot on lobby

This commit is contained in:
2026-05-21 15:06:52 +00:00
parent c1cc9739d9
commit ccda2babd5
5 changed files with 17275 additions and 5 deletions
+33 -5
View File
@@ -267,6 +267,8 @@
anim.frames.push(frame0);
}
var phase = walkAnimPhaseIndex(now, isWalking);
// ยืนนิ่ง → ใช้รูป idle (_idle.png) ก่อน
if (!isWalking && anim.fallback && anim.fallback.complete && anim.fallback.naturalWidth) return anim.fallback;
var fi = pickLoadedWalkFrameIndex(anim, phase);
if (fi >= 0) return anim.frames[fi];
const fb = anim.fallback;
@@ -549,6 +551,23 @@
var rlCharManifest = null;
var rlManifestId = null;
/** ตัวละคร default — ใช้เมื่อผู้เล่น/บอทไม่มี characterId (กันตัวละครหายเป็นวงกลม blob) */
var rlDefaultCharId = '';
(function rlLoadDefaultChar() {
try {
fetch(SERVER + '/api/characters', { cache: 'no-store' })
.then(function (r) { return r.ok ? r.json() : null; })
.then(function (list) {
if (!Array.isArray(list) || !list.length) return;
var pick = list.filter(function (x) { return x && x.hasLayerFiles; })[0] || list[0];
if (pick && pick.id) {
rlDefaultCharId = pick.id;
if (typeof mapData !== 'undefined' && mapData && typeof canvas !== 'undefined' && canvas) drawLobbyMap();
}
})
.catch(function () { /* ignore */ });
} catch (e) { /* ignore */ }
})();
function rlEnsureManifest(cb) {
var id = getStoredCharacterId();
@@ -620,6 +639,8 @@
}
}
var phase = walkAnimPhaseIndex(now, isWalking);
// ยืนนิ่ง → ใช้เฟรม idle (byDirIdle) ก่อน ไม่ใช่เฟรมเดินเฟรมแรก
if (!isWalking && anim.fallback && anim.fallback.complete && anim.fallback.naturalWidth) return anim.fallback;
for (var k = Math.min(phase, CHARACTER_ANIM_FRAMES - 1); k >= 0; k--) {
var f = anim.frames[k];
if (f && f.complete && f.naturalWidth) return f;
@@ -982,7 +1003,9 @@
const dir = p.direction || 'down';
const isWalking = id === socket.id
? !!(me && me.isWalking)
: !!((p.tx != null && Math.abs((p.tx || p.x) - p.x) > 0.02) || (p.ty != null && Math.abs((p.ty || p.y) - p.y) > 0.02));
: (p.tx != null || p.ty != null)
? !!((p.tx != null && Math.abs((p.tx || p.x) - p.x) > 0.02) || (p.ty != null && Math.abs((p.ty || p.y) - p.y) > 0.02))
: !!p.isWalking; /* บอท (ไม่มี tx/ty) ใช้ flag isWalking ที่ stepLobbyCaseBots ตั้ง */
const peerLockedOut = quizModeActive && (
quizPeersLocked[id] ||
(id === socket.id && quizPlayerLocal && quizPlayerLocal.cannotTrue && quizPlayerLocal.cannotFalse)
@@ -994,7 +1017,8 @@
}
const peerTheme = (id === socket.id) ? myTintTheme : (p.colorTheme || null);
const peerSkin = (id === socket.id) ? myTintSkin : (p.colorSkin || null);
const charImg = getAvatarImgColored(p.characterId, peerTheme, peerSkin, dir, timeMs, isWalking);
const cid = p.characterId || rlDefaultCharId; // กันตัวละครหายเป็นวงกลม blob เมื่อ characterId ว่าง
const charImg = getAvatarImgColored(cid, peerTheme, peerSkin, dir, timeMs, isWalking);
const iw = charImg && charImg.complete && charImg.naturalWidth ? charImg.naturalWidth : 0;
const ih = charImg && charImg.complete && charImg.naturalWidth ? charImg.naturalHeight : 0;
const imgScale = (iw && ih) ? Math.min(boxSize / iw, boxSize / ih, 1) : 1;
@@ -1838,10 +1862,10 @@
function getStoredCharacterId() {
try {
const v = (localStorage.getItem('gameCharacterId') || '').trim();
if (v === 'Chatest') return ''; // legacy placeholder ไม่มี sprite จริง
return v;
if (v && v !== 'Chatest') return v; // 'Chatest' = legacy placeholder ไม่มี sprite จริง
return rlDefaultCharId || ''; // ไม่มีตัวที่เลือก → ใช้ตัว default ที่มี sprite จริง
} catch (e) {
return '';
return rlDefaultCharId || '';
}
}
@@ -3922,6 +3946,8 @@
if (!mapData.quizTrueArea) mapData.quizTrueArea = [];
if (!mapData.quizFalseArea) mapData.quizFalseArea = [];
if (!mapData.quizQuestionArea) mapData.quizQuestionArea = [];
ROOM_CZ_SPOT = null; // รีเซ็ตจุดแต่งตัวก่อน แล้วคำนวณใหม่ตาม map ใหม่ (LobbyB ไม่มี customizeSpot → ไม่แสดง icon)
markRoomCzInteractiveCell();
(data.peersSnap || []).forEach(function (row) {
if (!row || !row.id) return;
const p = peers.get(row.id);
@@ -4047,6 +4073,8 @@
if (!mapData.quizTrueArea) mapData.quizTrueArea = [];
if (!mapData.quizFalseArea) mapData.quizFalseArea = [];
if (!mapData.quizQuestionArea) mapData.quizQuestionArea = [];
ROOM_CZ_SPOT = null; // คำนวณจุดแต่งตัวใหม่ตาม map เกมที่โหลด
markRoomCzInteractiveCell();
if (mapData.backgroundImage) {
mapBackgroundImg = new Image();
mapBackgroundImg.onload = function () { resizeAndDraw(); };
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff