update desige 2 3 5 6 7

This commit is contained in:
2026-06-10 03:43:38 +00:00
parent 4159597e4c
commit 816538569d
2 changed files with 395 additions and 60 deletions
+263 -56
View File
@@ -641,6 +641,10 @@
let stackTowerLifeBarImg = null;
let stackTowerLifeHitImg = null;
let stackTowerLifeFullImg = null;
/** Space Shooter (violent_crime): life HUD โหลดจาก /img/ViolentCrime/ แยกจาก TowerBlock ของ Stack */
let violentCrimeLifeBarImg = null;
let violentCrimeLifeHitImg = null;
let violentCrimeLifeFullImg = null;
/** @type {{ until: number } | null} */
let stackTowerHeartMinusFx = null;
const STACK_TOWER_HEART_MINUS_FX_MS = 1500;
@@ -745,7 +749,9 @@
}
ctx.save();
ctx.imageSmoothingEnabled = false;
/* BG อวกาศเป็นภาพ illustration (loop 1024w สเกลขึ้น ~1.9x) — เปิด smoothing ไม่ให้แตกเป็นบล็อก (stack tower BG กว้าง ~1920 จึงคงปิดไว้) */
ctx.imageSmoothingEnabled = true;
ctx.imageSmoothingQuality = 'high';
ctx.beginPath();
ctx.rect(0, 0, cwR, chR);
ctx.clip();
@@ -5756,6 +5762,26 @@
}
}
/** Space Shooter (mnpz6rkp): โหลด life HUD จาก /img/ViolentCrime/ แล้วคืน image set ให้ drawStackTowerLifeIntegrityBarPlay */
function ensureViolentCrimeLifeHudImagesPlay() {
if (!violentCrimeLifeBarImg) {
violentCrimeLifeBarImg = new Image();
violentCrimeLifeBarImg.decoding = 'async';
violentCrimeLifeBarImg.src = violentCrimeAssetUrl('life-bar.png');
}
if (!violentCrimeLifeHitImg) {
violentCrimeLifeHitImg = new Image();
violentCrimeLifeHitImg.decoding = 'async';
violentCrimeLifeHitImg.src = violentCrimeAssetUrl('life-hit.png');
}
if (!violentCrimeLifeFullImg) {
violentCrimeLifeFullImg = new Image();
violentCrimeLifeFullImg.decoding = 'async';
violentCrimeLifeFullImg.src = violentCrimeAssetUrl('life-full.png');
}
return { bar: violentCrimeLifeBarImg, full: violentCrimeLifeFullImg, hit: violentCrimeLifeHitImg };
}
/**
* ดสวนสงของ life-bar.png เปนขอความ "SYSTEM INTEGRITY" (เหล = แถวหวใจแยกวาดเอง ไมบขอบ `[` `]` ใน PNG)
*/
@@ -5764,14 +5790,16 @@
/**
* วาดหวขอจาก life-bar.png (ครอปบน) + แถวหวใจ life-full / life-hit งกลาง นความสงทใชจร
*/
function drawStackTowerLifeIntegrityBarPlay(ctx, destX, destY, maxW, maxH, lifeSlots, livesRem) {
ensureStackTowerLifeHudImagesPlay();
const bar = stackTowerLifeBarImg;
const fullIm = (stackTowerLifeFullImg && stackTowerLifeFullImg.complete && stackTowerLifeFullImg.naturalWidth > 0)
? stackTowerLifeFullImg
function drawStackTowerLifeIntegrityBarPlay(ctx, destX, destY, maxW, maxH, lifeSlots, livesRem, opts) {
const imgs = (opts && opts.images)
? opts.images
: (ensureStackTowerLifeHudImagesPlay(), { bar: stackTowerLifeBarImg, full: stackTowerLifeFullImg, hit: stackTowerLifeHitImg });
const bar = imgs.bar;
const fullIm = (imgs.full && imgs.full.complete && imgs.full.naturalWidth > 0)
? imgs.full
: ensureStackTowerHeartMinusImgPlay();
const hitIm = stackTowerLifeHitImg && stackTowerLifeHitImg.complete && stackTowerLifeHitImg.naturalWidth > 0
? stackTowerLifeHitImg
const hitIm = imgs.hit && imgs.hit.complete && imgs.hit.naturalWidth > 0
? imgs.hit
: null;
const slots = Math.max(1, Math.min(20, Math.floor(lifeSlots) || 1));
const lives = Math.max(0, Math.min(slots, Math.floor(livesRem) || 0));
@@ -6371,6 +6399,7 @@
return;
}
cd.classList.remove('is-hidden');
syncGauntletCrownCountdownMg2ModePlay(cd);
let n = 3;
setCountdown321QuestionAssetGraphic(numEl, n);
const step = function () {
@@ -6691,6 +6720,7 @@
return;
}
cd.classList.remove('is-hidden');
syncGauntletCrownCountdownMg2ModePlay(cd);
let n = 3;
setCountdown321QuestionAssetGraphic(numEl, n);
const step = function () {
@@ -7088,6 +7118,7 @@
return;
}
cd.classList.remove('is-hidden');
syncGauntletCrownCountdownMg2ModePlay(cd);
let n = 3;
setCountdown321QuestionAssetGraphic(numEl, n);
const step = function () {
@@ -7622,6 +7653,7 @@
return;
}
cd.classList.remove('is-hidden');
syncGauntletCrownCountdownMg2ModePlay(cd);
let n = 3;
setCountdown321QuestionAssetGraphic(numEl, n);
const step = function () {
@@ -9571,6 +9603,19 @@
function syncGauntletCrownJumpButton() {
const btn = document.getElementById('gauntlet-crown-jump-btn');
if (!btn) return;
/* MG5 jump_survive (jumper): โชว์ปุ่ม JUMP มุมขวาล่าง (design .mg5-jump 1648/818/231) — ให้ touch กระโดดได้ (เดิม keyboard-only) */
if (mapData && isJumpSurviveMissionHudActivePlay()) {
btn.classList.remove('is-hidden');
btn.setAttribute('aria-hidden', 'false');
btn.style.pointerEvents = '';
btn.classList.add('mg2-jump');
const jimg = btn.querySelector('img');
if (jimg && jimg.src.indexOf('/Jumper/') < 0) jimg.src = jumperAssetUrl('btn-jump.png');
const hudJ = document.getElementById('play-cyber-hud');
if (hudJ && hudJ.classList.contains('play-cyber-hud--quiz-tf-mock')) updateQuizTfMockScale(hudJ);
syncMg2MockJumpButtonBoundsPlay();
return;
}
const pregameUi = gauntletCrownPregamePhase === 'howto' || gauntletCrownPregamePhase === 'countdown';
const liveUi = gauntletCrownPregamePhase === 'live' && gauntletCrownRunwayAvatarRunAllowedPlay();
const show = !!(mapData && isGauntletCrownHeistMapPlay() && !me.gauntletEliminated && (pregameUi || liveUi));
@@ -9620,6 +9665,175 @@
btn.style.pointerEvents = ok ? '' : 'none';
}
/** MG3 (mnn93hpi): ผู้เล่นตาปัจจุบัน (active node) สำหรับ host portrait ใน DOM HUD */
function mg3CurrentSeatRowPlay() {
const seat = getStackPreviewCurrentSeat();
const order = stackPreviewTurnOrder;
let entry = null;
if (order && order.length) entry = order.find((e) => e.seat === seat) || null;
if (!entry || entry.kind === 'human') {
return {
id: myId,
characterId: me.characterId || getPlayCharacterId(),
isMe: true,
playTint: me.playTint || resolvePlayTintForPeer(String(myId != null ? myId : 'me')),
};
}
const o = entry.botId ? others.get(entry.botId) : null;
return {
id: entry.botId,
characterId: o ? o.characterId : null,
isMe: false,
playTint: o ? (o.playTint || resolvePlayTintForPeer(entry.botId)) : null,
};
}
/**
* MG3 Stack Tower live HUD DOM overlay (#mg3-tower-hud) canvas object-fit:cover ครอป HUD ขอบจอ
* งยาย life bar (ขวาบน) + progress (ายลาง) + code terminal + host frame มาเป DOM สเกลตาม stage
*/
function syncStackTowerMissionDomHudPlay() {
const root = document.getElementById('mg3-tower-hud');
if (!root) return;
const on = !!(mapData && isStack() && stackMini && isStackTowerMissionHudActivePlay());
root.classList.toggle('is-hidden', !on);
root.setAttribute('aria-hidden', on ? 'false' : 'true');
if (!on) return;
if (!root.dataset.mg3Assets) {
const setSrc = (sel, file) => { const el = root.querySelector(sel); if (el) el.src = stackTowerAssetUrl(file); };
setSrc('.mg3-life-bar', 'life-bar.png');
setSrc('.mg3-host-frame', 'Avartar.png');
setSrc('.mg3-terminal-bg', 'code-bg.png');
setSrc('.mg3-progress-label', 'progress-txt.png');
setSrc('.mg3-progress-track', 'progress-bg.png');
setSrc('.mg3-progress-fill', 'progress.png');
root.dataset.mg3Assets = '1';
}
/* วาง design plane 1920×1080 → scale แบบ contain + จัดกึ่งกลางใน stage (HUD เห็นครบ ไม่โดน object-fit:cover ครอป) */
const stack = document.getElementById('play-canvas-stack');
if (stack) {
const r = stack.getBoundingClientRect();
const cw = Math.max(1, r.width || 0);
const ch = Math.max(1, r.height || 0);
const s = Math.min(cw / 1920, ch / 1080);
if (s > 0 && isFinite(s)) {
const left = Math.round(r.left + (cw - 1920 * s) / 2);
const top = Math.round(r.top + (ch - 1080 * s) / 2);
const key = left + ',' + top + ',' + s.toFixed(4);
if (root.dataset.mg3Box !== key) {
root.dataset.mg3Box = key;
root.style.left = left + 'px';
root.style.top = top + 'px';
root.style.transform = 'scale(' + s + ')';
}
}
}
const slots = Math.max(1, Math.min(20, Math.floor(Number(playStackTeamMissesMax) || 3)));
const lives = Math.max(0, Math.min(slots, Math.floor(Number(
stackMini.teamMissesLeft != null ? stackMini.teamMissesLeft : (stackMini.lives != null ? stackMini.lives : 3),
) || 0)));
const heartsEl = document.getElementById('mg3-life-hearts');
if (heartsEl) {
const hk = slots + '/' + lives;
if (heartsEl.dataset.hk !== hk) {
heartsEl.dataset.hk = hk;
heartsEl.innerHTML = '';
for (let i = 0; i < slots; i++) {
const im = document.createElement('img');
im.src = stackTowerAssetUrl(i < lives ? 'life-full.png' : 'life-hit.png');
im.alt = '';
heartsEl.appendChild(im);
}
}
}
const pct = Math.max(0, Math.min(100, Math.round(Number(stackTowerDecryptPctPlay()) || 0)));
if (root.dataset.mg3Pct !== String(pct)) {
root.dataset.mg3Pct = String(pct);
/* fill เป็น px ในระนาบ design (track ภายในจาก left:30 กว้างสุด ~358px) */
const fillEl = document.getElementById('mg3-progress-fill');
if (fillEl) fillEl.style.width = Math.round(358 * pct / 100) + 'px';
const pctEl = document.getElementById('mg3-progress-pct');
if (pctEl) pctEl.textContent = '[ ' + pct + '% ]';
}
const hostAv = document.getElementById('mg3-host-av');
if (hostAv) {
const row = mg3CurrentSeatRowPlay();
const hk = (row.id != null ? row.id : 'me') + '|' + (row.characterId || '');
if (hostAv.dataset.hk !== hk) {
hostAv.dataset.hk = hk;
setCyberHudScoreAvatarImg(hostAv, row);
}
}
const logEl = document.getElementById('mg3-terminal-log');
if (logEl) {
const lines = stackPreviewHudLog && stackPreviewHudLog.length
? stackPreviewHudLog.slice(-7)
: ['>>> DECRYPT UPLINK READY', '>>> SPACE / CLICK = DROP (ตาคุณ)'];
const txt = lines.join('\n');
if (logEl.textContent !== txt) logEl.textContent = txt;
}
}
/**
* MG6 Space Shooter life overlay #mg6-life-hud (ระนาบ design 1920×1080 scale ตาม stage แบบเดยวก MG3)
* life-bar.png + วใจ 3 ดวง (ViolentCrime) ตำแหน/ขนาดเท MG3 ไม flex ของ cyber HUD (นบ/นขอบ)
*/
function syncSpaceShooterLifeDomHudPlay() {
const root = document.getElementById('mg6-life-hud');
if (!root) return;
const on = !!(mapData && isSpaceShooter() && isSpaceShooterMissionHudActivePlay());
root.classList.toggle('is-hidden', !on);
root.setAttribute('aria-hidden', on ? 'false' : 'true');
if (!on) return;
if (!root.dataset.assets) {
const bar = root.querySelector('.mg6-life-bar');
if (bar) bar.src = violentCrimeAssetUrl('life-bar.png');
root.dataset.assets = '1';
}
const stack = document.getElementById('play-canvas-stack');
if (stack) {
const r = stack.getBoundingClientRect();
const cw = Math.max(1, r.width || 0);
const ch = Math.max(1, r.height || 0);
const s = Math.min(cw / 1920, ch / 1080);
if (s > 0 && isFinite(s)) {
const left = Math.round(r.left + (cw - 1920 * s) / 2);
const top = Math.round(r.top + (ch - 1080 * s) / 2);
const key = left + ',' + top + ',' + s.toFixed(4);
if (root.dataset.box !== key) {
root.dataset.box = key;
root.style.left = left + 'px';
root.style.top = top + 'px';
root.style.transform = 'scale(' + s + ')';
}
}
}
const slots = SPACE_SHOOTER_MISSION_MAX_ASTEROID_HITS;
const hits = Math.max(0, Math.min(slots, Number(me.spaceShooterHits) || 0));
const rem = slots - hits;
const heartsEl = document.getElementById('mg6-life-hearts');
if (heartsEl) {
const hk = slots + '/' + rem;
if (heartsEl.dataset.hk !== hk) {
heartsEl.dataset.hk = hk;
heartsEl.innerHTML = '';
for (let i = 0; i < slots; i++) {
const im = document.createElement('img');
im.src = violentCrimeAssetUrl(i < rem ? 'life-full.png' : 'life-hit.png');
im.alt = '';
im.decoding = 'async';
heartsEl.appendChild(im);
}
}
}
}
function resetQuizCarryPlayState() {
cancelQuizCarrySessionCompleteResultToSummary();
const qcmo = document.getElementById('quiz-carry-mission-overlay');
@@ -16240,6 +16454,11 @@
const jq = jumpSurviveJumpQueued;
jumpSurviveJumpQueued = false;
/* virtual joystick (touch) — แกน x ป้อนซ้าย/ขวาเหมือนคีย์ A/D (deadzone จัดการในตัว update แล้ว) */
const joyX = isJumpSurviveMissionHudActivePlay() ? (Number(quizQuestionMissionJoyVecX) || 0) : 0;
const moveLeftIn = !!(keys['ArrowLeft'] || keys['KeyA']) || joyX < -0.001;
const moveRightIn = !!(keys['ArrowRight'] || keys['KeyD']) || joyX > 0.001;
const r = jumpSurvivePhysicsIntegrate(md, {
dt,
cw,
@@ -16249,8 +16468,8 @@
vy0: jumpSurviveVy,
wasOnGround: jumpSurviveOnGround,
jumpQueued: jq,
moveLeft: !!(keys['ArrowLeft'] || keys['KeyA']),
moveRight: !!(keys['ArrowRight'] || keys['KeyD']),
moveLeft: moveLeftIn,
moveRight: moveRightIn,
});
if (r.died) {
@@ -16267,9 +16486,9 @@
stepJumpSurvivePreviewBots(dt, halfViewH);
if (!jumpSurviveEliminated) {
me.isWalking = Math.abs(jumpSurviveVy) > 40 || !!(keys['ArrowLeft'] || keys['KeyA'] || keys['ArrowRight'] || keys['KeyD']);
if (keys['ArrowRight'] || keys['KeyD']) me.direction = 'right';
else if (keys['ArrowLeft'] || keys['KeyA']) me.direction = 'left';
me.isWalking = Math.abs(jumpSurviveVy) > 40 || moveLeftIn || moveRightIn;
if (moveRightIn) me.direction = 'right';
else if (moveLeftIn) me.direction = 'left';
if (Date.now() - jumpSurviveLastEmitT > 80) {
jumpSurviveLastEmitT = Date.now();
@@ -18728,6 +18947,8 @@
const mono = '11px ui-monospace, "Cascadia Mono", Consolas, monospace';
const monoSm = '9px ui-monospace, Consolas, monospace';
const towerMapHud = isStackTowerMissionUiMapPlay();
/* MG3 live mission: HUD ย้ายไป DOM (#mg3-tower-hud) แล้ว — ไม่วาดบน canvas (object-fit:cover ครอปขอบหาย) */
if (towerMapHud) return;
const lifeSlots = towerMapHud
? Math.max(1, Math.min(20, Math.floor(Number(playStackTeamMissesMax) || 3)))
: 3;
@@ -19469,9 +19690,24 @@
function syncQuizQuestionMissionJoystickPlay() {
const root = document.getElementById('quiz-question-mission-joystick');
if (!root) return;
const on = !!(isQuizQuestionMissionHudActivePlay() && !isChatFocused());
const jumperOn = isJumpSurviveMissionHudActivePlay();
const on = !!((isQuizQuestionMissionHudActivePlay() || jumperOn) && !isChatFocused());
root.classList.toggle('is-hidden', !on);
root.setAttribute('aria-hidden', on ? 'false' : 'true');
if (on) {
/* สลับรูป joystick ตามฉาก: jumper → /img/Jumper/, quiz คำถาม → /img/QUESTION/ (เปลี่ยน src เฉพาะตอน skin เปลี่ยน) */
const skin = jumperOn ? 'jumper' : 'question';
const bg = document.getElementById('quiz-q-mission-joystick-bg');
const knobImg = document.getElementById('quiz-q-mission-joystick-knob-img');
if (bg && bg.dataset.joySkin !== skin) {
bg.src = jumperOn ? jumperAssetUrl('btn-joystick-1.png') : questionMissionAssetUrl('btn-joystick-1.png');
bg.dataset.joySkin = skin;
}
if (knobImg && knobImg.dataset.joySkin !== skin) {
knobImg.src = jumperOn ? jumperAssetUrl('btn-joystick-2.png') : questionMissionAssetUrl('btn-joystick-2.png');
knobImg.dataset.joySkin = skin;
}
}
if (!on) {
const base = document.getElementById('quiz-q-mission-joystick-base');
if (base && quizQuestionMissionJoyPointerId != null) {
@@ -19524,7 +19760,8 @@
function syncMg2MockJumpButtonBoundsPlay(stackRect, scale) {
const jumpBtn = document.getElementById('gauntlet-crown-jump-btn');
const hud = document.getElementById('play-cyber-hud');
if (!jumpBtn || !hud || hud.dataset.missionMockSkin !== 'gauntlet_crown') {
const _jbSkin = hud ? hud.dataset.missionMockSkin : '';
if (!jumpBtn || !hud || (_jbSkin !== 'gauntlet_crown' && _jbSkin !== 'jumper')) {
if (jumpBtn) {
jumpBtn.style.removeProperty('left');
jumpBtn.style.removeProperty('top');
@@ -19850,45 +20087,8 @@
}
if (statusEl) {
if (isSpaceShooterMissionHudActivePlay()) {
ensureStackTowerLifeHudImagesPlay();
const nn = String((me.nickname || nick || 'PILOT')).trim().slice(0, 24);
const hits = Math.max(0, Math.min(SPACE_SHOOTER_MISSION_MAX_ASTEROID_HITS, Number(me.spaceShooterHits) || 0));
const rem = SPACE_SHOOTER_MISSION_MAX_ASTEROID_HITS - hits;
const esc = playCyberHudEsc(nn);
const W = 220;
const H = 58;
const dpr = Math.min(2, Math.max(1, typeof window !== 'undefined' && window.devicePixelRatio ? window.devicePixelRatio : 1));
let canv = statusEl.querySelector('canvas.play-cyber-ss-integrity-canvas');
let metaEl = statusEl.querySelector('.play-cyber-ss-meta');
if (!canv || !metaEl) {
statusEl.textContent = '';
canv = document.createElement('canvas');
canv.className = 'play-cyber-ss-integrity-canvas';
canv.setAttribute('aria-hidden', 'true');
metaEl = document.createElement('div');
metaEl.className = 'play-cyber-ss-meta';
statusEl.appendChild(canv);
statusEl.appendChild(metaEl);
}
canv.width = Math.max(1, Math.floor(W * dpr));
canv.height = Math.max(1, Math.floor(H * dpr));
canv.style.width = W + 'px';
canv.style.height = H + 'px';
const ctxSs = canv.getContext('2d');
if (ctxSs) {
ctxSs.setTransform(dpr, 0, 0, dpr, 0, 0);
ctxSs.clearRect(0, 0, W + 2, H + 2);
drawStackTowerLifeIntegrityBarPlay(
ctxSs,
2,
2,
W - 4,
H - 4,
SPACE_SHOOTER_MISSION_MAX_ASTEROID_HITS,
rem,
);
}
metaEl.textContent = 'P1 · ' + esc; /* ตัด 'TEAM 0 · COMBO x0' ปลอม (ค่าไม่เปลี่ยน ไม่ตรง design) */
/* MG6 life ย้ายไป overlay เฉพาะ #mg6-life-hud (syncSpaceShooterLifeDomHudPlay) — คุมตำแหน่ง/ขนาดเท่า MG3 */
statusEl.textContent = '';
} else if (isQuizQuestionMissionHudActivePlay()) {
statusEl.textContent = 'QUIZ LINK · ประลองความรู้';
} else if (isStackTowerMissionHudActivePlay()) {
@@ -21203,6 +21403,8 @@
syncQuizCarryGrabButton();
syncGauntletCrownJumpButton();
syncStackTowerDropButtonPlay();
syncStackTowerMissionDomHudPlay();
syncSpaceShooterLifeDomHudPlay();
}
document.addEventListener('keydown', (e) => {
@@ -21654,7 +21856,10 @@
if (!btn) return;
btn.addEventListener('click', (ev) => {
ev.preventDefault();
if (!mapData || !isGauntlet() || isChatFocused()) return;
if (isChatFocused()) return;
/* MG5 jumper: click = queue jump (mirror keyboard Space/W/↑) */
if (mapData && isJumpSurviveMissionHudActivePlay()) { jumpSurviveJumpQueued = true; return; }
if (!mapData || !isGauntlet()) return;
tryRequestGauntletJumpPlay();
});
})();
@@ -21677,6 +21882,7 @@
if (!base) return;
if (bg) {
bg.src = questionMissionAssetUrl('btn-joystick-1.png');
bg.dataset.joySkin = 'question';
bg.onerror = function () {
this.onerror = null;
this.removeAttribute('src');
@@ -21684,6 +21890,7 @@
}
if (knobImg) {
knobImg.src = questionMissionAssetUrl('btn-joystick-2.png');
knobImg.dataset.joySkin = 'question';
knobImg.onerror = function () {
this.onerror = null;
this.removeAttribute('src');
@@ -21698,7 +21905,7 @@
quizQuestionMissionJoystickResetVisual();
}
base.addEventListener('pointerdown', (e) => {
if (!isQuizQuestionMissionHudActivePlay() || isChatFocused()) return;
if (!(isQuizQuestionMissionHudActivePlay() || isJumpSurviveMissionHudActivePlay()) || isChatFocused()) return;
if (e.button != null && e.button !== 0) return;
e.preventDefault();
try {
+132 -4
View File
@@ -1424,6 +1424,10 @@
#gauntlet-crown-mission-overlay.is-hidden,
#gauntlet-crown-countdown.is-hidden,
#stack-tower-result-flash.is-hidden { display: none !important; }
/* นับถอยหลังใช้ .gcc-num{display:block} ทับ — ต้องมี rule ให้ is-hidden ซ่อนเลขข้อความจริง (เดิมไม่มี → "3" รั่วในเกมที่ใช้รูปกราฟิก) */
#gauntlet-crown-countdown .gcc-num.is-hidden { display: none !important; }
/* สรุปผล: เส้นแบ่ง vrule แสดงเฉพาะ Last Light (mg2) — non-mg2 มี is-hidden แต่ไม่มี rule ซ่อน → ไปกินช่อง grid ขวา ดัน "โบนัสพิเศษ" ตกลงคอลัมน์ซ้าย */
#gcm-vrule.is-hidden { display: none !important; }
.gcc-panel {
text-align: center;
padding: 0;
@@ -2089,6 +2093,36 @@
image-rendering: pixelated;
margin-bottom: 0.28rem;
}
/* MG6 life (DOM) — life-bar.png เต็มใบ + หัวใจ 3 ดวงในวงเล็บ [ ] เหมือน MG3 */
.play-cyber-ss-life {
position: relative;
width: 100%;
margin-bottom: 0.28rem;
}
.play-cyber-ss-lifebar { width: 100%; display: block; image-rendering: pixelated; }
.play-cyber-ss-hearts {
position: absolute;
left: 24.3%; top: 50%; height: 46%;
display: flex; align-items: center; gap: 4%;
}
.play-cyber-ss-hearts img { height: 100%; width: auto; image-rendering: pixelated; }
/* MG6 Space Shooter life overlay — ระนาบ design 1920×1080 scale ตาม stage (coords/หัวใจเท่า MG3) */
.mg6-life-hud {
position: fixed;
width: 1920px; height: 1080px;
transform-origin: 0 0;
pointer-events: none;
z-index: 54;
}
.mg6-life-hud.is-hidden { display: none !important; }
.mg6-life-hud img { image-rendering: pixelated; display: block; }
.mg6-life-hud .mg6-life { position: absolute; left: 1410px; top: 63px; width: 341px; height: 111px; }
.mg6-life-hud .mg6-life-bar { width: 341px; height: 111px; display: block; }
.mg6-life-hud .mg6-life-hearts {
position: absolute; left: 83px; top: 56px; height: 52px;
display: flex; align-items: center; gap: 10px;
}
.mg6-life-hud .mg6-life-hearts img { height: 52px; width: auto; }
#play-cyber-hud.play-cyber-hud--question-mission .play-cyber-ss-meta {
font-size: 0.5rem;
letter-spacing: 0.06em;
@@ -2105,8 +2139,9 @@
max-width: min(96vw, 380px);
}
#play-cyber-hud.play-cyber-hud--ss-self-integrity-left .play-cyber-self-status {
order: 1;
flex: 1 1 auto;
order: 3;
flex: 0 0 auto;
width: auto;
min-width: 0;
}
#play-cyber-hud.play-cyber-hud--ss-self-integrity-left .play-cyber-profile-frame {
@@ -2125,6 +2160,65 @@
#play-cyber-hud.play-cyber-hud--stack-tower-canvas-hud .play-cyber-self {
display: none !important;
}
/* ===== MG3 Stack Tower live HUD — DOM overlay: 1920×1080 design plane scale+center ตาม stage (coords ตรง design game.css/game-hud.css) ===== */
.mg3-tower-hud {
position: fixed;
width: 1920px; height: 1080px;
transform-origin: 0 0;
pointer-events: none;
z-index: 54;
}
.mg3-tower-hud.is-hidden { display: none !important; }
.mg3-tower-hud > div { position: absolute; }
.mg3-tower-hud img { image-rendering: pixelated; display: block; }
/* SYSTEM INTEGRITY life bar (design .mg3-life left:1410 top:63 w:341 h:111) */
.mg3-life { left: 1410px; top: 63px; width: 341px; height: 111px; }
.mg3-life-bar { width: 341px; height: 111px; display: block; }
.mg3-life-hearts {
position: absolute; left: 83px; top: 56px;
display: flex; align-items: center; gap: 10px; height: 52px;
}
.mg3-life-hearts img { height: 52px; width: auto; }
/* host portrait frame (design .mg-host left:1729 top:21 w/h:201; face left:49 top:49 104×104) */
.mg3-host { left: 1729px; top: 21px; width: 201px; height: 201px; }
.mg3-host-frame { position: absolute; inset: 0; width: 100%; height: 100%; }
.mg3-host-face {
position: absolute; left: 49px; top: 49px; width: 104px; height: 104px;
border-radius: 8px; object-fit: cover;
}
/* code terminal (design .mg3-terminal left:40 bottom:170 w:420) */
.mg3-terminal { left: 40px; bottom: 170px; width: 420px; }
.mg3-terminal-bg { width: 100%; height: auto; }
.mg3-terminal-log {
position: absolute; left: 9%; right: 9%; top: 10%; bottom: 10%;
overflow: hidden;
font: 22px/1.4 ui-monospace, "Cascadia Mono", Consolas, monospace;
color: #8fe9ff;
text-shadow: 0 0 6px rgba(0, 200, 255, 0.5);
white-space: pre-wrap; word-break: break-word;
}
/* progress (design .mg3-progress left:43 bottom:40 w:418 h:151) — label+pct heading แล้ว track+fill */
.mg3-progress {
left: 43px; bottom: 40px; width: 418px; height: 151px;
display: flex; flex-direction: row; flex-wrap: wrap; gap: 0;
}
.mg3-progress-heading {
display: flex; align-items: center; justify-content: space-between;
width: 100%; flex: 0 0 75%; gap: 3px;
}
.mg3-progress-label { width: auto; height: 58px; display: block; flex: 0 0 auto; }
.mg3-progress-pct {
font-family: "NotoSansThai", monospace, sans-serif; font-weight: 700;
font-size: 28px; line-height: 44px; color: #8fe8ff; letter-spacing: 0.5px;
white-space: nowrap; text-shadow: 0 0 8px rgba(120, 220, 255, 0.6);
}
.mg3-progress-bar { position: relative; width: 100%; flex: 0 0 100%; }
.mg3-progress-track { width: 100%; height: auto; display: block; }
.mg3-progress-fill {
position: absolute; left: 30px; top: 30px; height: 30px; width: 0;
object-fit: cover; object-position: left center;
transition: width 0.25s ease;
}
/* Last Light (mno9kb07): แถบคะแนนแนวนอน — score.png แล้วตามด้วยสูงสุด 6 ช่อง (อวาตาร์ | ชื่อบน / คะแนนล่าง) */
#play-cyber-hud.play-cyber-hud--gauntlet-crown-strip .play-cyber-hint {
display: none !important;
@@ -3352,7 +3446,8 @@
height: 104px;
overflow: hidden;
border-radius: 8px;
z-index: 1;
/* avatar ต้องอยู่บนกรอบ Avartar.png (กรอบมีพื้นกลางทึบ ทับหน้า avatar = "ถูกบัง") — เหมือน MG3 ที่หน้าอยู่บนสุด */
z-index: 3;
}
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-profile-frame .play-cyber-portrait-img,
#play-cyber-hud.play-cyber-hud--quiz-tf-mock.play-cyber-hud--question-mission .play-cyber-profile-frame .play-cyber-portrait-img {
@@ -3385,6 +3480,7 @@
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-op-widgets {
display: none !important;
}
/* Space Shooter (MG6): life ย้ายไป overlay #mg6-life-hud แล้ว — แผง self-status คงซ่อน (ตาม rule quiz-tf-mock) */
/* mic 121px @ (1796,205) — เทียบ mg-mic */
#play-cyber-hud.play-cyber-hud--quiz-tf-mock .play-cyber-mic-img {
display: block;
@@ -4490,6 +4586,38 @@
</div>
</div>
</div>
<!-- MG3 Stack Tower (mnn93hpi) live HUD — DOM overlay (canvas object-fit:cover ครอป HUD ขอบจอ จึงย้ายมา DOM สเกลตาม stage) -->
<div id="mg3-tower-hud" class="mg3-tower-hud is-hidden" aria-hidden="true">
<div class="mg3-life">
<img class="mg3-life-bar" src="" alt="" decoding="async" />
<div class="mg3-life-hearts" id="mg3-life-hearts"></div>
</div>
<div class="mg3-host">
<img class="mg3-host-frame" src="" alt="" decoding="async" />
<img class="mg3-host-face" id="mg3-host-av" src="" alt="" decoding="async" />
</div>
<div class="mg3-terminal">
<img class="mg3-terminal-bg" src="" alt="" decoding="async" />
<div class="mg3-terminal-log" id="mg3-terminal-log"></div>
</div>
<div class="mg3-progress">
<div class="mg3-progress-heading">
<img class="mg3-progress-label" src="" alt="" decoding="async" />
<span class="mg3-progress-pct" id="mg3-progress-pct">[ 0% ]</span>
</div>
<div class="mg3-progress-bar">
<img class="mg3-progress-track" src="" alt="" decoding="async" />
<img class="mg3-progress-fill" id="mg3-progress-fill" src="" alt="" decoding="async" />
</div>
</div>
</div>
<!-- MG6 Space Shooter (mnpz6rkp) live life — DOM overlay สเกล design 1920×1080 เหมือน MG3 (ไม่พึ่ง cyber HUD flex) -->
<div id="mg6-life-hud" class="mg6-life-hud is-hidden" aria-hidden="true">
<div class="mg6-life">
<img class="mg6-life-bar" src="" alt="" decoding="async" />
<div class="mg6-life-hearts" id="mg6-life-hearts"></div>
</div>
</div>
<div id="play-quiz-scoreboard" class="is-hidden" aria-live="polite">
<div class="play-quiz-scoreboard-title">คะแนน</div>
<ul id="play-quiz-scoreboard-list" class="play-quiz-scoreboard-list"></ul>
@@ -4746,7 +4874,7 @@
<script src="/app-base.js?v=2"></script>
<script src="/Game/socket.io/socket.io.js"></script>
<script src="js/version.js?v=0.0306"></script>
<script src="js/play.js?v=0.00610200013"></script>
<script src="js/play.js?v=0.00610200020"></script>
<div class="version-tag">v —</div>
</body>
</html>