(function () {
'use strict';
var BASE = typeof appPath === 'function' ? appPath('/Game') : '/Game';
var SERVER = (typeof GAME_SERVER !== 'undefined' ? GAME_SERVER : '') + '/Game';
var CHAR_KEY = 'gameCharacterId';
/** รูป composite idle ทิศ down จากหน้า Character (preview-idle-layer-down) — ตรงกับ character.js */
var LOBBY_IDLE_DOWN_PREFIX = 'jdCharLobbyIdleDown:';
function getStoredLobbyIdleDownDataUrl(safeId) {
if (!safeId) return '';
try {
var v = localStorage.getItem(LOBBY_IDLE_DOWN_PREFIX + safeId) || '';
if (typeof v === 'string' && v.indexOf('data:image/') === 0 && v.length > 80) return v;
} catch (e) { /* ignore */ }
return '';
}
var GUIDE_KEY = 'mainLobbyGuideDone';
var MAX_GUIDE = 5;
var ML_GUIDE = typeof appPath === 'function' ? appPath('/Main-Lobby/IMAGE/guide') : '/Main-Lobby/IMAGE/guide';
/**
* ตำแหน่งแถบคำแนะนำ + จุดไฮไลต์ต่อ guide-01…05 (ปรับลำดับให้ตรงไฟล์รูป)
* position: 'bottom' | 'top' — ตาม mock แถบล่าง/บน
* highlight: selector ของปุ่มใน lobby (null = ไม่วงกรอบ)
*/
var GUIDE_STEPS = [
{ position: 'bottom', highlight: null, pad: 10 },
{ position: 'top', highlight: '.lobby-footer-center', pad: 10 },
{ position: 'top', highlight: '#btn-ai-chat', pad: 8 },
{ position: 'bottom', highlight: '#btn-cloth', pad: 10 },
{ position: 'bottom', highlight: '#btn-daily', pad: 10 },
];
function checkLogin() {
if (localStorage.getItem('isLoggedIn') !== 'true') {
window.location.href = typeof appPath === 'function' ? appPath('/Login/') : '/Login/';
return false;
}
return true;
}
if (!checkLogin()) return;
function toast(msg) {
var el = document.getElementById('lobby-toast');
if (!el) return;
el.textContent = msg;
el.classList.add('lobby-toast--show');
clearTimeout(toast._t);
toast._t = setTimeout(function () {
el.classList.remove('lobby-toast--show');
}, 2600);
}
function padAgent(n) {
var s = String(n);
while (s.length < 6) s = '0' + s;
return s;
}
function ensureAgentId() {
var k = 'agentDisplayId';
var v = localStorage.getItem(k);
if (!v || !/^\d{6}$/.test(v)) {
v = padAgent(100000 + Math.floor(Math.random() * 899999));
try {
localStorage.setItem(k, v);
} catch (e) { /* ignore */ }
}
return v;
}
function getSelectedCharacterId() {
try {
return (localStorage.getItem(CHAR_KEY) || '').trim();
} catch (e) {
return '';
}
}
/** ใช้เฉพาะ id ที่ปลอดเป็น segment ใน URL — กันพาธแปลก/อักขระที่เซิร์ฟไม่มีไฟล์ */
function normalizeCharacterAssetId(id) {
var s = String(id == null ? '' : id).trim();
if (!s) return '';
if (s.length > 96) s = s.slice(0, 96);
if (!/^[a-zA-Z0-9._-]+$/.test(s)) return '';
return s;
}
function mainMenuCharFallbackUrl() {
return typeof appPath === 'function' ? appPath('/Main-Menu/char-main.png') : '/Main-Menu/char-main.png';
}
/**
* URL รูปโลบี้ — ลองทิศ down ก่อน (idle แล้ว walk) เพื่อไม่ยิง _up_idle_ ฯลฯ โดยไม่จำเป็น
* ถ้า down ไม่มีค่อยลอง up / left / right
* @param {string} safeId
* @param {boolean} preferIdle
*/
function characterSpriteCandidateUrls(safeId, preferIdle) {
if (!safeId) return [];
var enc = encodeURIComponent(safeId);
var q = '?ch=' + encodeURIComponent(safeId);
var dirsPrimary = ['down'];
var dirsFallback = ['up', 'left', 'right'];
var wantIdle = preferIdle !== false;
var urls = [];
function pushForDir(d) {
if (wantIdle) {
urls.push(SERVER + '/img/characters/' + enc + '_' + d + '_idle.png' + q);
urls.push(SERVER + '/img/characters/' + enc + '_' + d + '_idle_0.png' + q);
}
urls.push(SERVER + '/img/characters/' + enc + '_' + d + '.png' + q);
urls.push(SERVER + '/img/characters/' + enc + '_' + d + '_0.png' + q);
}
for (var a = 0; a < dirsPrimary.length; a++) pushForDir(dirsPrimary[a]);
for (var b = 0; b < dirsFallback.length; b++) pushForDir(dirsFallback[b]);
return urls;
}
/** หลังลองครบแล้วไม่มีรูป — ลดการยิงซ้ำในเซสชัน (ไม่บล็อกการลองใหม่หลังอัปโหลดไฟล์แล้ว — ลบคีย์ตอนโหลดสำเร็จ) */
var CHAR_ASSET_MISS_PREFIX = 'jdCharAssetMissing:';
function markCharacterDownAssetMissing(safeId) {
if (!safeId) return;
try {
sessionStorage.setItem(CHAR_ASSET_MISS_PREFIX + safeId, '1');
} catch (e) { /* ignore */ }
}
function clearCharacterDownAssetMissing(safeId) {
if (!safeId) return;
try {
sessionStorage.removeItem(CHAR_ASSET_MISS_PREFIX + safeId);
} catch (e) { /* ignore */ }
}
/**
* ลอง URL ตามลำดับด้วย Image — ตรงกับพฤติกรรม
ใน character-grid
* @param {string[]} urls
* @param {(url: string | null) => void} cb
*/
function probeFirstLoadableImageUrl(urls, cb) {
var i = 0;
function next() {
if (i >= urls.length) {
cb(null);
return;
}
var u = urls[i++];
var img = new Image();
img.onload = function () {
if (img.naturalWidth > 0) cb(u);
else next();
};
img.onerror = function () {
next();
};
img.src = u;
}
next();
}
/**
* @param {string} safeId
* @param {(url: string | null) => void} cb
*/
function characterLobbySpriteFirstLiveUrl(safeId, cb) {
if (!safeId) {
cb(null);
return;
}
var urls = characterSpriteCandidateUrls(safeId, true);
if (!urls.length) {
cb(null);
return;
}
probeFirstLoadableImageUrl(urls, function (url) {
if (url) {
clearCharacterDownAssetMissing(safeId);
cb(url);
} else {
markCharacterDownAssetMissing(safeId);
cb(null);
}
});
}
/**
* id จาก localStorage หรือถ้าว่าง — ตัวสุดท้ายในรายการ API (ใหม่สุดตามลำดับเซิร์ฟ)
* @param {(safeId: string) => void} callback
*/
function resolveLobbyCharacterId(callback) {
var norm = normalizeCharacterAssetId(getSelectedCharacterId());
if (norm) {
callback(norm);
return;
}
fetch(BASE + '/api/characters', { credentials: 'same-origin', cache: 'no-store' })
.then(function (r) { return r.json(); })
.then(function (list) {
if (!Array.isArray(list) || !list.length) {
callback('');
return;
}
var last = list[list.length - 1];
var id = last && last.id ? normalizeCharacterAssetId(String(last.id)) : '';
callback(id || '');
})
.catch(function () {
callback('');
});
}
var PLAYER_KEY = 'jdPlayerKey';
var DISPLAY_NAME_STORAGE_KEY = 'roomLobbyDisplayName';
function ensurePlayerKey() {
var k;
try {
k = localStorage.getItem(PLAYER_KEY);
} catch (e) {
k = '';
}
if (!k || String(k).length < 8) {
k = 'p_' + Date.now() + '_' + Math.random().toString(36).slice(2, 14);
try {
localStorage.setItem(PLAYER_KEY, k);
} catch (e2) { /* ignore */ }
}
return k;
}
/** ดึง COINS จากเซิร์ฟ (บัญชี guest สร้างอัตโนมัติถ้ายังไม่มี) */
function syncCoinsFromServer() {
var key = ensurePlayerKey();
fetch((typeof appPath === 'function' ? appPath('/Admin/api/player-coins.php') : '/Admin/api/player-coins.php') + '?playerKey=' + encodeURIComponent(key), { credentials: 'omit' })
.then(function (r) { return r.json(); })
.then(function (d) {
if (!d || !d.ok) return;
var c = String(Math.max(0, parseInt(d.coins, 10) || 0));
try {
localStorage.setItem('jdCoins', c);
} catch (e) { /* ignore */ }
var coinsEl = document.getElementById('lobby-profile-coins');
if (coinsEl) coinsEl.textContent = c;
})
.catch(function () { /* offline */ });
}
/** รีเฟรชหลังเลือกตัวละคร / สลับแท็บ / ย้อนกลับบน tablet (bfcache) */
function syncMainLobbyCharacterUi() {
applyProfileTexts();
syncCoinsFromServer();
function applyCharAssets(urlOrNull) {
applyProfileAvatar(urlOrNull);
applyCenterCharacterResolved(urlOrNull);
}
resolveLobbyCharacterId(function (id) {
if (!id) {
applyCharAssets(null);
return;
}
var idleCached = getStoredLobbyIdleDownDataUrl(id);
if (idleCached) {
applyCharAssets(idleCached);
return;
}
characterLobbySpriteFirstLiveUrl(id, applyCharAssets);
});
}
function getProfileDisplayName() {
if (typeof window.jdReadDisplayName === 'function') {
return window.jdReadDisplayName();
}
var fromRoomLobby = '';
var fromPlayerName = '';
try {
fromRoomLobby = (localStorage.getItem(DISPLAY_NAME_STORAGE_KEY) || '').trim();
fromPlayerName = (localStorage.getItem('playerName') || '').trim();
} catch (e) { /* ignore */ }
return fromRoomLobby || fromPlayerName || 'MONE';
}
function applyProfileTexts() {
var name = getProfileDisplayName();
var coins = localStorage.getItem('jdCoins') || '0';
var nameEl = document.getElementById('lobby-profile-name');
var agentEl = document.getElementById('lobby-profile-agent-id');
var coinsEl = document.getElementById('lobby-profile-coins');
if (nameEl) nameEl.textContent = name.toUpperCase();
if (agentEl) agentEl.textContent = ensureAgentId();
if (coinsEl) coinsEl.textContent = coins;
}
/** @param {string | null} urlOrNull — URL ที่ HEAD ผ่านแล้ว หรือ null = ใช้ char-main */
function applyProfileAvatar(urlOrNull) {
var av = document.getElementById('lobby-profile-avatar');
if (!av) return;
var fb = mainMenuCharFallbackUrl();
av.onerror = null;
if (!urlOrNull) {
av.src = fb;
return;
}
av.onerror = function () {
av.onerror = null;
av.src = fb;
};
av.src = urlOrNull;
}
function applyCenterCharacterResolved(urlOrNull) {
var centerEl = document.getElementById('lobby-character-img');
if (!centerEl) return;
function showSceneOnly() {
centerEl.classList.remove('lobby-character-img--visible');
centerEl.removeAttribute('src');
}
function revealChar() {
centerEl.classList.add('lobby-character-img--visible');
}
function showFallbackCenterCharacter() {
var fb = mainMenuCharFallbackUrl();
centerEl.onload = revealChar;
centerEl.onerror = function () {
centerEl.onerror = null;
showSceneOnly();
};
centerEl.src = fb;
if (centerEl.complete && centerEl.naturalWidth > 0) {
revealChar();
}
}
function showWithChar(url) {
centerEl.onload = revealChar;
centerEl.onerror = function () {
showFallbackCenterCharacter();
};
centerEl.src = url;
if (centerEl.complete && centerEl.naturalWidth > 0) {
revealChar();
}
}
if (!urlOrNull) {
showFallbackCenterCharacter();
return;
}
showWithChar(urlOrNull);
}
// คำนวณ offset จากความสูงจอด้วย linear interpolation:
// 1080 -> 18cqh, 650 -> 25cqh
function applyCharacterFootOffsetByViewport() {
var root = document.documentElement;
if (!root) return;
var h = Math.max(1, window.innerHeight || 0);
var h1 = 650;
var y1 = 25;
var h2 = 1080;
var y2 = 18;
var t = (h - h1) / (h2 - h1);
var cqhValue = y1 + ((y2 - y1) * t);
// กันหลุดช่วงเมื่อจอเล็ก/ใหญ่เกินช่วงอ้างอิง
cqhValue = Math.max(18, Math.min(25, cqhValue));
root.style.setProperty('--lobby-character-foot-offset', cqhValue.toFixed(3) + 'cqh');
}
function syncLeaderboardScrollbarThumb() {
var scrollEl = document.querySelector('.lobby-leaderboard-scroll');
var thumbEl = document.getElementById('lobby-leaderboard-scroll-thumb');
var trackEl = document.getElementById('lobby-leaderboard-scroll-track');
if (!scrollEl || !thumbEl) return;
var styles = window.getComputedStyle(thumbEl);
var topInset = parseFloat(styles.top) || 0;
var minThumb = parseFloat(styles.minHeight) || 18;
var maxScroll = Math.max(0, scrollEl.scrollHeight - scrollEl.clientHeight);
if (maxScroll <= 0) {
thumbEl.style.display = 'none';
if (trackEl) trackEl.style.display = 'none';
return;
}
if (trackEl) trackEl.style.display = 'block';
thumbEl.style.display = 'block';
var trackHeight = (trackEl && trackEl.clientHeight) ? trackEl.clientHeight : scrollEl.clientHeight;
var visibleRatio = scrollEl.clientHeight / Math.max(1, scrollEl.scrollHeight);
var thumbHeight = Math.max(minThumb, Math.round(trackHeight * visibleRatio));
var maxY = Math.max(0, trackHeight - topInset - thumbHeight);
var y = topInset + (maxY * (scrollEl.scrollTop / maxScroll));
thumbEl.style.height = thumbHeight + 'px';
thumbEl.style.transform = 'translateY(' + y.toFixed(2) + 'px)';
}
// วาง leaderboard ให้ต่อจากปุ่ม daily โดยไม่ทับกัน
function placeLeaderboardBelowDaily() {
var dailyBtn = document.getElementById('btn-daily');
var leaderboard = document.querySelector('.lobby-leaderboard');
var lobbyUi = document.querySelector('.lobby-ui');
if (!dailyBtn || !leaderboard || !lobbyUi) return;
var boardStyle = window.getComputedStyle(leaderboard);
if (boardStyle.position !== 'absolute') {
leaderboard.style.top = '';
return;
}
var uiRect = lobbyUi.getBoundingClientRect();
var dailyRect = dailyBtn.getBoundingClientRect();
var boardRect = leaderboard.getBoundingClientRect();
var cssGap = boardStyle.getPropertyValue('--lobby-daily-leaderboard-gap').trim();
var gapPx = 8;
if (cssGap) {
var n = parseFloat(cssGap);
if (!Number.isNaN(n)) {
if (cssGap.endsWith('cqh')) gapPx = (uiRect.height * n) / 100;
else if (cssGap.endsWith('px') || /^[+-]?\d+(\.\d+)?$/.test(cssGap)) gapPx = n;
else if (cssGap.endsWith('vh')) gapPx = ((window.innerHeight || 0) * n) / 100;
else if (cssGap.endsWith('%')) gapPx = (uiRect.height * n) / 100;
}
}
var nextTop = (dailyRect.bottom - uiRect.top) + gapPx;
var maxTop = Math.max(0, uiRect.height - boardRect.height - Math.max(0, gapPx));
var clampedTop = Math.max(0, Math.min(nextTop, maxTop));
leaderboard.style.top = clampedTop.toFixed(2) + 'px';
}
var leaderboardLayoutRaf = 0;
function scheduleLeaderboardPlacement() {
if (leaderboardLayoutRaf) cancelAnimationFrame(leaderboardLayoutRaf);
leaderboardLayoutRaf = requestAnimationFrame(function () {
leaderboardLayoutRaf = 0;
placeLeaderboardBelowDaily();
syncLeaderboardScrollbarThumb();
});
}
function bindLeaderboardScrollSync() {
var scrollEl = document.querySelector('.lobby-leaderboard-scroll');
if (!scrollEl || scrollEl.dataset.scrollSyncBound === '1') return;
scrollEl.addEventListener('scroll', syncLeaderboardScrollbarThumb, { passive: true });
scrollEl.dataset.scrollSyncBound = '1';
}
function bindLeaderboardWheelSupport() {
var scrollEl = document.querySelector('.lobby-leaderboard-scroll');
if (!scrollEl || scrollEl.dataset.wheelSupportBound === '1') return;
scrollEl.addEventListener('wheel', function (e) {
var maxScroll = Math.max(0, scrollEl.scrollHeight - scrollEl.clientHeight);
if (maxScroll <= 0) return;
scrollEl.scrollTop += e.deltaY;
syncLeaderboardScrollbarThumb();
e.preventDefault();
}, { passive: false });
scrollEl.dataset.wheelSupportBound = '1';
}
function bindLeaderboardThumbDrag() {
var scrollEl = document.querySelector('.lobby-leaderboard-scroll');
var thumbEl = document.getElementById('lobby-leaderboard-scroll-thumb');
var trackEl = document.getElementById('lobby-leaderboard-scroll-track');
if (!scrollEl || !thumbEl || !trackEl || thumbEl.dataset.dragBound === '1') return;
var dragging = false;
var dragOffsetY = 0;
function getThumbMetrics() {
var styles = window.getComputedStyle(thumbEl);
var topInset = parseFloat(styles.top) || 0;
var thumbHeight = thumbEl.clientHeight || parseFloat(thumbEl.style.height) || 18;
var trackHeight = trackEl.clientHeight || scrollEl.clientHeight || 1;
var maxTranslate = Math.max(topInset, trackHeight - thumbHeight);
var travel = Math.max(1, maxTranslate - topInset);
return { topInset: topInset, thumbHeight: thumbHeight, trackHeight: trackHeight, maxTranslate: maxTranslate, travel: travel };
}
function stopDrag() {
if (!dragging) return;
dragging = false;
thumbEl.classList.remove('is-dragging');
document.body.classList.remove('lobby-leaderboard-dragging');
}
thumbEl.addEventListener('mousedown', function (e) {
if (e.button !== 0) return;
var maxScroll = Math.max(0, scrollEl.scrollHeight - scrollEl.clientHeight);
if (maxScroll <= 0) return;
var metrics = getThumbMetrics();
var thumbRect = thumbEl.getBoundingClientRect();
dragOffsetY = Math.max(0, Math.min(metrics.thumbHeight, e.clientY - thumbRect.top));
dragging = true;
thumbEl.classList.add('is-dragging');
document.body.classList.add('lobby-leaderboard-dragging');
e.preventDefault();
e.stopPropagation();
});
window.addEventListener('mousemove', function (e) {
if (!dragging) return;
var maxScroll = Math.max(0, scrollEl.scrollHeight - scrollEl.clientHeight);
if (maxScroll <= 0) {
stopDrag();
return;
}
var metrics = getThumbMetrics();
var trackRect = trackEl.getBoundingClientRect();
var pointerY = e.clientY - trackRect.top;
var nextTranslate = pointerY - dragOffsetY;
nextTranslate = Math.max(metrics.topInset, Math.min(metrics.maxTranslate, nextTranslate));
var ratio = (nextTranslate - metrics.topInset) / metrics.travel;
scrollEl.scrollTop = ratio * maxScroll;
syncLeaderboardScrollbarThumb();
e.preventDefault();
});
window.addEventListener('mouseup', stopDrag);
window.addEventListener('blur', stopDrag);
thumbEl.dataset.dragBound = '1';
}
function bindLeaderboardDragScroll() {
var scrollEl = document.querySelector('.lobby-leaderboard-scroll');
if (!scrollEl || scrollEl.dataset.dragScrollBound === '1') return;
var dragging = false;
var moved = false;
var startY = 0;
var startScrollTop = 0;
function stopDrag() {
if (!dragging) return;
dragging = false;
window.setTimeout(function () { moved = false; }, 0);
document.body.classList.remove('lobby-leaderboard-dragging');
scrollEl.classList.remove('is-dragging');
}
scrollEl.addEventListener('mousedown', function (e) {
if (e.button !== 0) return;
var maxScroll = Math.max(0, scrollEl.scrollHeight - scrollEl.clientHeight);
if (maxScroll <= 0) return;
dragging = true;
moved = false;
startY = e.clientY;
startScrollTop = scrollEl.scrollTop;
document.body.classList.add('lobby-leaderboard-dragging');
scrollEl.classList.add('is-dragging');
e.preventDefault();
});
window.addEventListener('mousemove', function (e) {
if (!dragging) return;
var deltaY = e.clientY - startY;
if (Math.abs(deltaY) > 2) moved = true;
scrollEl.scrollTop = startScrollTop - deltaY;
syncLeaderboardScrollbarThumb();
e.preventDefault();
});
window.addEventListener('mouseup', stopDrag);
window.addEventListener('blur', stopDrag);
scrollEl.addEventListener('mouseleave', function (e) {
if (!dragging) return;
if (e.buttons === 0) stopDrag();
});
scrollEl.addEventListener('click', function (e) {
if (!moved) return;
e.preventDefault();
e.stopPropagation();
}, true);
scrollEl.dataset.dragScrollBound = '1';
}
var guideStep = 1;
var guideImg = document.getElementById('guide-img');
var guideBar = document.getElementById('lobby-guide-bar');
var guideDim = document.getElementById('lobby-guide-dim');
var guideFocus = document.getElementById('lobby-guide-focus');
function getGuideStepConfig(step) {
return GUIDE_STEPS[step - 1] || { position: 'bottom', highlight: null, pad: 10 };
}
function hideGuideFocus() {
if (!guideFocus) return;
guideFocus.classList.add('hidden');
guideFocus.style.left = '0';
guideFocus.style.top = '0';
guideFocus.style.width = '0';
guideFocus.style.height = '0';
}
function scheduleGuideFocusUpdate() {
requestAnimationFrame(function () {
requestAnimationFrame(updateGuideFocus);
});
}
function updateGuideFocus() {
if (!guideFocus || !guideBar || guideBar.classList.contains('hidden')) {
hideGuideFocus();
return;
}
var cfg = getGuideStepConfig(guideStep);
if (!cfg.highlight) {
hideGuideFocus();
return;
}
var target = document.querySelector(cfg.highlight);
if (!target) {
hideGuideFocus();
return;
}
var pad = typeof cfg.pad === 'number' ? cfg.pad : 8;
var r = target.getBoundingClientRect();
if (r.width < 4 || r.height < 4) {
hideGuideFocus();
return;
}
var cs = window.getComputedStyle(target);
var br = parseInt(cs.borderRadius, 10) || 0;
var radius = Math.max(br + 4, 14);
guideFocus.classList.remove('hidden');
guideFocus.style.left = (r.left - pad) + 'px';
guideFocus.style.top = (r.top - pad) + 'px';
guideFocus.style.width = (r.width + pad * 2) + 'px';
guideFocus.style.height = (r.height + pad * 2) + 'px';
guideFocus.style.borderRadius = radius + 'px';
}
function syncGuideBodyClass() {
if (!guideBar) return;
var open = !guideBar.classList.contains('hidden');
if (open) {
document.body.classList.add('lobby-guide-active');
var cfg = getGuideStepConfig(guideStep);
document.body.classList.toggle('lobby-guide-top-step', cfg.position === 'top');
var hasFocus = !!cfg.highlight;
if (guideDim) guideDim.classList.toggle('hidden', hasFocus);
} else {
document.body.classList.remove('lobby-guide-active');
document.body.classList.remove('lobby-guide-top-step');
if (guideDim) guideDim.classList.add('hidden');
}
if (open) {
scheduleGuideFocusUpdate();
} else {
hideGuideFocus();
}
}
function showGuideStep(n) {
if (!guideImg || !guideBar) return;
if (n < 1 || n > MAX_GUIDE) {
guideBar.classList.add('hidden');
guideBar.classList.remove('lobby-guide-bar--top');
hideGuideFocus();
try {
localStorage.setItem(GUIDE_KEY, '1');
} catch (e) { /* ignore */ }
syncGuideBodyClass();
return;
}
guideStep = n;
var cfg = getGuideStepConfig(guideStep);
guideImg.src = ML_GUIDE + '/guide-' + (n < 10 ? '0' + n : String(n)) + '.png';
guideImg.alt = 'คำแนะนำ ขั้นที่ ' + n;
guideBar.classList.toggle('lobby-guide-bar--top', cfg.position === 'top');
var nextBtn = document.getElementById('btn-guide-next');
if (nextBtn) {
nextBtn.setAttribute('aria-label', n >= MAX_GUIDE ? 'รับทราบ' : 'ถัดไป');
}
syncGuideBodyClass();
guideImg.onload = function () {
scheduleGuideFocusUpdate();
};
guideImg.onerror = function () {
scheduleGuideFocusUpdate();
};
scheduleGuideFocusUpdate();
}
function initGuide() {
if (!guideBar || !guideImg) return;
try {
if (localStorage.getItem(GUIDE_KEY) === '1') {
guideBar.classList.add('hidden');
syncGuideBodyClass();
return;
}
} catch (e) { /* ignore */ }
guideBar.classList.remove('hidden');
showGuideStep(1);
}
document.getElementById('btn-guide-next')?.addEventListener('click', function () {
if (guideStep >= MAX_GUIDE) {
if (guideBar) {
guideBar.classList.add('hidden');
guideBar.classList.remove('lobby-guide-bar--top');
}
try {
localStorage.setItem(GUIDE_KEY, '1');
} catch (e) { /* ignore */ }
syncGuideBodyClass();
return;
}
showGuideStep(guideStep + 1);
});
document.addEventListener('keydown', function (e) {
if (e.key !== 'Escape') return;
if (!guideBar || guideBar.classList.contains('hidden')) return;
e.preventDefault();
guideBar.classList.add('hidden');
guideBar.classList.remove('lobby-guide-bar--top');
hideGuideFocus();
syncGuideBodyClass();
});
window.addEventListener('resize', function () {
if (guideBar && !guideBar.classList.contains('hidden')) {
scheduleGuideFocusUpdate();
}
});
window.addEventListener('orientationchange', function () {
setTimeout(scheduleGuideFocusUpdate, 350);
});
/* ใช้ capture + data-href บน .lobby-footer-center — ลดโอกาสถูกเลเยอร์อื่นแย่งคลิกก่อนถึงปุ่ม */
var footerCenter = document.querySelector('.lobby-footer-center');
if (footerCenter) {
footerCenter.addEventListener('click', function (e) {
var btn = e.target.closest('button[data-href]');
if (!btn || !footerCenter.contains(btn)) return;
var href = btn.getAttribute('data-href');
if (!href) return;
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
window.location.href = href;
}, true);
}
document.getElementById('btn-cloth')?.addEventListener('click', function () {
if (typeof window.openCustomizePopup === 'function') {
window.openCustomizePopup();
return;
}
window.location.href = BASE + '/character.html';
});
document.getElementById('btn-daily')?.addEventListener('click', function () {
if (typeof window.openDailyPopup === 'function') {
window.openDailyPopup();
return;
}
toast('รางวัลประจำวัน — เข้าเกมทุกวันเพื่อรับรางวัลต่อเนื่อง!');
});
document.getElementById('btn-myprofile')?.addEventListener('click', function () {
if (typeof window.openProfilePopup === 'function') {
window.openProfilePopup();
return;
}
window.location.href = typeof appPath === 'function' ? appPath('/Main-Menu/') : '/Main-Menu/';
});
function getMlAiSessionId() {
try {
var k = 'mlAiChatSession';
var v = localStorage.getItem(k);
if (!v) {
v = 'ml-' + Date.now() + '-' + Math.random().toString(36).slice(2, 11);
localStorage.setItem(k, v);
}
return v;
} catch (e) {
return 'ml-' + String(Date.now());
}
}
var aiChatCloseBtn = document.getElementById('lobby-ai-chat-close-btn');
var aiChatPanel = document.getElementById('lobby-ai-chat-panel');
var aiChatToggleImg = document.getElementById('lobby-ai-chat-toggle-img');
var btnAiChat = document.getElementById('btn-ai-chat');
function syncAiChatPanelUi() {
if (!aiChatPanel) return;
var hidden = aiChatPanel.classList.contains('lobby-ai-chat-hidden');
if (btnAiChat) btnAiChat.style.display = hidden ? '' : 'none';
if (hidden || !aiChatToggleImg || !aiChatCloseBtn) return;
aiChatToggleImg.src = BASE + '/img/chat-close-btn.png';
aiChatToggleImg.alt = 'ปิด';
aiChatCloseBtn.setAttribute('title', 'ปิดแชท AI');
aiChatCloseBtn.setAttribute('aria-label', 'ปิดแชท AI');
}
if (aiChatCloseBtn && aiChatPanel) {
aiChatCloseBtn.addEventListener('click', function () {
aiChatPanel.classList.add('lobby-ai-chat-hidden');
aiChatPanel.classList.remove('chat-panel-collapsed');
syncAiChatPanelUi();
});
}
if (btnAiChat && aiChatPanel) {
btnAiChat.addEventListener('click', function () {
if (aiChatPanel.classList.contains('lobby-ai-chat-hidden')) {
aiChatPanel.classList.remove('lobby-ai-chat-hidden');
aiChatPanel.classList.remove('chat-panel-collapsed');
syncAiChatPanelUi();
var inp = document.getElementById('lobby-ai-chat-input');
if (inp) {
try {
inp.focus();
} catch (e) { /* ignore */ }
}
} else {
aiChatPanel.classList.add('lobby-ai-chat-hidden');
syncAiChatPanelUi();
}
});
}
syncAiChatPanelUi();
var aiChatForm = document.getElementById('lobby-ai-chat-form');
var aiChatInput = document.getElementById('lobby-ai-chat-input');
var aiChatSendBtn = aiChatForm ? aiChatForm.querySelector('button[type="submit"]') : null;
var aiChatLoadingEl = null;
function appendAiMessage(text, isAi) {
var el = document.getElementById('lobby-ai-chat-messages');
if (!el) return;
if (isAi) removeAiChatLoading();
var div = document.createElement('div');
div.className = 'lobby-ai-chat-msg ' + (isAi ? 'lobby-ai-chat-msg-ai' : 'lobby-ai-chat-msg-user');
div.textContent = (isAi ? 'AI: ' : '') + text;
el.appendChild(div);
el.scrollTop = 1e9;
}
function showAiChatLoading() {
var el = document.getElementById('lobby-ai-chat-messages');
if (!el || aiChatLoadingEl) return;
aiChatLoadingEl = document.createElement('div');
aiChatLoadingEl.className = 'lobby-ai-chat-msg lobby-ai-chat-msg-ai lobby-ai-chat-typing';
aiChatLoadingEl.setAttribute('aria-label', 'กำลังพิมพ์');
aiChatLoadingEl.innerHTML = '';
el.appendChild(aiChatLoadingEl);
el.scrollTop = 1e9;
}
function removeAiChatLoading() {
if (aiChatLoadingEl && aiChatLoadingEl.parentNode) {
aiChatLoadingEl.parentNode.removeChild(aiChatLoadingEl);
aiChatLoadingEl = null;
}
}
function setAiChatWaiting(waiting) {
if (aiChatInput) aiChatInput.disabled = waiting;
if (aiChatSendBtn) aiChatSendBtn.disabled = waiting;
if (waiting) showAiChatLoading();
else removeAiChatLoading();
}
if (aiChatForm && aiChatInput) {
aiChatForm.addEventListener('submit', function (e) {
e.preventDefault();
var text = (aiChatInput.value || '').trim();
if (!text) return;
appendAiMessage(text, false);
setAiChatWaiting(true);
aiChatInput.value = '';
fetch(SERVER + '/api/ai-chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: text, sessionId: getMlAiSessionId() }),
})
.then(function (r) { return r.json(); })
.then(function (data) {
if (data.response != null) appendAiMessage(data.response, true);
else if (data.error) appendAiMessage('[ข้อผิดพลาด: ' + data.error + ']', true);
})
.catch(function () {
appendAiMessage('[ส่งไม่สำเร็จ]', true);
})
.finally(function () {
setAiChatWaiting(false);
});
});
}
var howto = document.getElementById('lobby-howto-overlay');
function openHowto() {
if (howto) howto.classList.remove('hidden');
}
function closeHowto() {
if (howto) howto.classList.add('hidden');
}
/** ปุ่ม ? — คู่มือทีละขั้น ตาม /Main-Lobby/IMAGE/guide */
function openGuideTutorial() {
if (!guideBar || !guideImg) return;
closeHowto();
guideBar.classList.remove('hidden');
showGuideStep(1);
}
document.getElementById('btn-tutorial')?.addEventListener('click', openGuideTutorial);
document.getElementById('btn-howto-got-it')?.addEventListener('click', closeHowto);
howto?.addEventListener('click', function (e) {
if (e.target === howto) closeHowto();
});
applyCharacterFootOffsetByViewport();
syncMainLobbyCharacterUi();
bindLeaderboardScrollSync();
bindLeaderboardWheelSupport();
bindLeaderboardDragScroll();
bindLeaderboardThumbDrag();
scheduleLeaderboardPlacement();
initGuide();
window.addEventListener('pageshow', function () {
applyCharacterFootOffsetByViewport();
syncMainLobbyCharacterUi();
scheduleLeaderboardPlacement();
});
window.addEventListener('resize', function () {
applyCharacterFootOffsetByViewport();
bindLeaderboardScrollSync();
bindLeaderboardWheelSupport();
bindLeaderboardDragScroll();
bindLeaderboardThumbDrag();
scheduleLeaderboardPlacement();
});
window.addEventListener('orientationchange', function () {
setTimeout(function () {
applyCharacterFootOffsetByViewport();
scheduleLeaderboardPlacement();
}, 250);
});
window.addEventListener('load', function () {
bindLeaderboardScrollSync();
bindLeaderboardWheelSupport();
bindLeaderboardDragScroll();
bindLeaderboardThumbDrag();
scheduleLeaderboardPlacement();
});
document.addEventListener('visibilitychange', function () {
if (document.visibilityState === 'visible') {
applyCharacterFootOffsetByViewport();
syncMainLobbyCharacterUi();
scheduleLeaderboardPlacement();
}
});
window.addEventListener('storage', function (e) {
if (e.key == null || e.key === CHAR_KEY || e.key === 'playerName' || e.key === DISPLAY_NAME_STORAGE_KEY) {
syncMainLobbyCharacterUi();
return;
}
if (e.key && String(e.key).indexOf(LOBBY_IDLE_DOWN_PREFIX) === 0) {
syncMainLobbyCharacterUi();
}
});
})();