diff --git a/www/html/Admin/admin.css b/www/html/Admin/admin.css index 6ed5dc8..ad6093d 100644 --- a/www/html/Admin/admin.css +++ b/www/html/Admin/admin.css @@ -2369,3 +2369,41 @@ code { font-variant-numeric: tabular-nums; padding-bottom: 0.2rem; } + +/* Space shooter admin — per-slot ship image URLs */ +.space-shooter-ship-grid { + display: flex; + flex-direction: column; + gap: 0.65rem; + margin-top: 0.5rem; +} +.space-shooter-ship-row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem 0.75rem; +} +.space-shooter-ship-slot { + flex: 0 0 1.5rem; + font-weight: 800; + font-variant-numeric: tabular-nums; + color: var(--accent); + text-align: center; +} +.space-shooter-ship-url-label { + flex: 1 1 220px; + min-width: 160px; + margin: 0; +} +.space-shooter-ship-url-label input[type='text'] { + width: 100%; + max-width: 560px; + margin-top: 0.2rem; +} +.space-shooter-ship-prev { + flex: 0 0 48px; + object-fit: contain; + background: rgba(0, 0, 0, 0.35); + border: 1px solid var(--border); + border-radius: 8px; +} diff --git a/www/html/Admin/admin.js b/www/html/Admin/admin.js index 115dd5e..4b16960 100644 --- a/www/html/Admin/admin.js +++ b/www/html/Admin/admin.js @@ -2630,6 +2630,50 @@ }); } + function updateSpaceShooterShipPreview(slot) { + var img = el('space-shooter-ship-prev-' + slot); + var inp = el('space-shooter-ship-url-' + slot); + if (!img) return; + var v = inp && inp.value ? String(inp.value).trim() : ''; + if (!v) { + img.removeAttribute('src'); + img.alt = ''; + return; + } + if (!/^https?:\/\//i.test(v) && v.charAt(0) !== '/') v = '/' + v.replace(/^\/+/, ''); + img.alt = 'Ship slot ' + slot; + img.src = v; + } + + function bindSpaceShooterShipUrlInputs() { + for (var s = 1; s <= 6; s++) { + (function (slot) { + var inp = el('space-shooter-ship-url-' + slot); + var btn = el('btn-space-shooter-ship-clear-' + slot); + if (inp) { + inp.addEventListener('change', function () { updateSpaceShooterShipPreview(slot); }); + inp.addEventListener('blur', function () { updateSpaceShooterShipPreview(slot); }); + } + if (btn) { + btn.addEventListener('click', function () { + var i = el('space-shooter-ship-url-' + slot); + if (i) i.value = ''; + updateSpaceShooterShipPreview(slot); + }); + } + })(s); + } + } + + function readSpaceShooterShipImageUrlsFromForm() { + var urls = []; + for (var i = 1; i <= 6; i++) { + var inp = el('space-shooter-ship-url-' + i); + urls.push(inp && inp.value ? String(inp.value).trim() : ''); + } + return urls; + } + function loadSpaceShooterTimingPanel() { gameTimingFetch('GET') .then(function (data) { @@ -2638,6 +2682,13 @@ var ss = Number(data.spaceShooterMissionTimeSec); inpT.value = String(Number.isFinite(ss) && ss > 0 ? Math.floor(ss) : 0); } + var urls = data.spaceShooterShipImageUrls; + if (!Array.isArray(urls)) urls = []; + for (var k = 1; k <= 6; k++) { + var inpU = el('space-shooter-ship-url-' + k); + if (inpU) inpU.value = urls[k - 1] != null ? String(urls[k - 1]) : ''; + updateSpaceShooterShipPreview(k); + } setMsg('space-shooter-timing-msg', '', ''); }) .catch(function (e) { @@ -2649,9 +2700,11 @@ var limSs = el('space-shooter-mission-sec') ? parseInt(String(el('space-shooter-mission-sec').value), 10) : 0; if (Number.isNaN(limSs) || limSs < 0) limSs = 0; limSs = limSs <= 0 ? 0 : Math.max(10, Math.min(7200, limSs)); + var shipUrls = readSpaceShooterShipImageUrlsFromForm(); gameTimingFetch('GET') .then(function (data) { data.spaceShooterMissionTimeSec = limSs; + data.spaceShooterShipImageUrls = shipUrls; return gameTimingFetch('PUT', data); }) .then(function () { @@ -2887,6 +2940,7 @@ if (btnSpaceShooterSave) { btnSpaceShooterSave.addEventListener('click', saveSpaceShooterTimingPanel); } + bindSpaceShooterShipUrlInputs(); var btnStackGameSave = el('btn-stack-game-save'); if (btnStackGameSave) { btnStackGameSave.addEventListener('click', saveStackGamePanel); diff --git a/www/html/Admin/index.html b/www/html/Admin/index.html index f935c15..e085068 100644 --- a/www/html/Admin/index.html +++ b/www/html/Admin/index.html @@ -9,7 +9,7 @@ - +
ข้ามไปเนื้อหา @@ -466,14 +466,26 @@เก็บที่ /Game/data/game-timing.json ฟิลด์ spaceShooterMissionTimeSec · ผู้เล่นได้ค่าใหม่เมื่อโหลดหน้าเล่น / GET /api/game-timing · รูปเกมอัปโหลดไปที่ /Game/public/img/ViolentCrime/ (ชื่อโฟลเดอร์ไม่มีช่องว่าง — FTP หลายตัวจะ 550 ถ้าใช้ Violent Crime)
เก็บที่ /Game/data/game-timing.json ฟิลด์ spaceShooterMissionTimeSec · spaceShooterShipImageUrls (รูปยาน 6 ช่อง) · ผู้เล่นได้ค่าใหม่เมื่อโหลดหน้าเล่น / GET /api/game-timing · รูปเกมอัปโหลดไปที่ /Game/public/img/ViolentCrime/ (ชื่อโฟลเดอร์ไม่มีช่องว่าง — FTP หลายตัวจะ 550 ถ้าใช้ Violent Crime)
นับจากเริ่มรอบในเกม · ถ้าในแมปตั้ง spaceShooterTimeSec > 0 จะใช้ค่าบนแมปแทนทั้งหมด · ตั้ง spaceShooterTimeSec = 0 บนแมป = ไม่จับเวลา