โชว์การ์ดพิเศษที่ได้ + ปุ่มไปต่อ
@@ -396,6 +396,14 @@
|
||||
title.appendChild(document.createElement('br'));
|
||||
title.appendChild(gradeEl);
|
||||
}
|
||||
var freeBonus = Math.max(0, Number(res.freeEvidenceCount) || 0);
|
||||
if (freeBonus > 0) {
|
||||
var bonusEl = document.createElement('div');
|
||||
bonusEl.style.cssText = 'font:800 15px/1.3 Kanit,system-ui,sans-serif;color:#9ece6a;margin-top:4px';
|
||||
bonusEl.textContent = '⭐ การ์ด Free Evidence: ทุกคนรับหลักฐานฟรี +' + freeBonus + ' ใบ';
|
||||
title.appendChild(document.createElement('br'));
|
||||
title.appendChild(bonusEl);
|
||||
}
|
||||
var row = document.createElement('div');
|
||||
row.style.cssText = 'display:flex;gap:18px;flex-wrap:wrap;justify-content:center;align-items:center;max-width:92vw';
|
||||
awarded.forEach(function (c, i) {
|
||||
@@ -11766,6 +11774,9 @@
|
||||
if (coins > 0 && card.effectKey === 'fund') {
|
||||
addOwnCoinsViaApi(coins);
|
||||
}
|
||||
/* ถ้า overlay ควิซยังเปิด (การ์ดเพิ่งได้จากควิซ) — แผง «เล่นต่อ» โชว์การ์ดอยู่แล้ว ไม่ต้องเด้งซ้ำ */
|
||||
const sqOv = specialQuizOverlayEl();
|
||||
if (sqOv && !sqOv.classList.contains('is-hidden')) return;
|
||||
showSpecialCardUseAnimation(card, { addSec: addSec, coins: coins });
|
||||
}
|
||||
|
||||
@@ -11835,24 +11846,66 @@
|
||||
}, 2600);
|
||||
}
|
||||
|
||||
/** ปิด overlay + คืนเวลาเล่นต่อ (เรียกตอนกด «เล่นต่อ» หรือ safety timeout) */
|
||||
function specialQuizContinueAndResume() {
|
||||
clearTimeout(endSpecialQuiz._safety);
|
||||
endSpecialQuiz._safety = 0;
|
||||
const ov = specialQuizOverlayEl();
|
||||
const award = document.getElementById('sq-ov-award');
|
||||
if (award) award.classList.add('is-hidden');
|
||||
if (ov) ov.classList.add('is-hidden');
|
||||
/* แจ้ง server ให้เล่นรอบ quiz (mng8a80o) ต่อ — มินิเกมอื่น freeze ฝั่ง client พอ */
|
||||
try { socket.emit('special-quiz-continue', {}, function () {}); } catch (e) { /* ignore */ }
|
||||
endSpecialQuizFreeze();
|
||||
}
|
||||
|
||||
function endSpecialQuiz(data) {
|
||||
cancelAnimationFrame(specialQuizTimerRaf);
|
||||
specialQuizActiveQuestion = null;
|
||||
specialQuizAnswered = false;
|
||||
endSpecialQuizFreeze();
|
||||
if (data && data.success && data.card) specialQuizAwardedCard = data.card;
|
||||
const ov = specialQuizOverlayEl();
|
||||
const success = !!(data && data.success && data.card);
|
||||
const card = success ? data.card : null;
|
||||
if (success) specialQuizAwardedCard = card;
|
||||
const status = document.getElementById('sq-ov-status');
|
||||
if (status) status.textContent = '';
|
||||
const result = document.getElementById('sq-ov-result');
|
||||
if (result) {
|
||||
result.classList.remove('is-hidden');
|
||||
result.textContent = (data && data.success)
|
||||
? 'ได้รับการ์ดพิเศษ! ดูในสรุปผลภารกิจ'
|
||||
: 'รอบนี้ไม่ได้การ์ดพิเศษ';
|
||||
result.className = 'sq-ov-result ' + ((data && data.success) ? 'sq-ov-result--ok' : 'sq-ov-result--fail');
|
||||
result.textContent = success ? 'ได้รับการ์ดพิเศษ!' : 'รอบนี้ไม่ได้การ์ดพิเศษ';
|
||||
result.className = 'sq-ov-result ' + (success ? 'sq-ov-result--ok' : 'sq-ov-result--fail');
|
||||
}
|
||||
const status = document.getElementById('sq-ov-status');
|
||||
if (status) status.textContent = '';
|
||||
if (ov) setTimeout(function () { ov.classList.add('is-hidden'); }, 1900);
|
||||
/* แผงโชว์การ์ด + ปุ่ม «เล่นต่อ» — เกมหยุดค้างจนกว่าจะกด */
|
||||
const award = document.getElementById('sq-ov-award');
|
||||
const titleEl = document.getElementById('sq-ov-award-title');
|
||||
const imgEl = document.getElementById('sq-ov-award-img');
|
||||
const nameEl = document.getElementById('sq-ov-award-name');
|
||||
const fxEl = document.getElementById('sq-ov-award-effect');
|
||||
const btn = document.getElementById('sq-ov-award-continue');
|
||||
if (award) {
|
||||
if (success) {
|
||||
if (titleEl) titleEl.textContent = 'ได้รับการ์ดพิเศษ!';
|
||||
if (imgEl) {
|
||||
imgEl.removeAttribute('hidden');
|
||||
imgEl.src = card.imageUrl || (card.cardId ? '/Game/img/special-cards/card-' + card.cardId + '.png' : '');
|
||||
}
|
||||
if (nameEl) nameEl.textContent = card.en || card.th || ('การ์ด #' + (card.cardId || ''));
|
||||
if (fxEl) fxEl.textContent = card.desc || card.th || '';
|
||||
} else {
|
||||
if (titleEl) titleEl.textContent = 'รอบนี้ไม่ได้การ์ดพิเศษ';
|
||||
if (imgEl) { imgEl.setAttribute('hidden', ''); imgEl.removeAttribute('src'); }
|
||||
if (nameEl) nameEl.textContent = '';
|
||||
if (fxEl) fxEl.textContent = 'ตอบถูกครบทุกคนเพื่อรับการ์ดพิเศษในครั้งหน้า';
|
||||
}
|
||||
if (btn) btn.onclick = specialQuizContinueAndResume;
|
||||
award.classList.remove('is-hidden');
|
||||
} else {
|
||||
/* ไม่มี element สำรอง — เล่นต่อทันที */
|
||||
specialQuizContinueAndResume();
|
||||
return;
|
||||
}
|
||||
/* กันค้าง: ถ้าไม่กดภายใน 30 วิ ให้ไปต่อเอง */
|
||||
clearTimeout(endSpecialQuiz._safety);
|
||||
endSpecialQuiz._safety = setTimeout(specialQuizContinueAndResume, 30000);
|
||||
}
|
||||
|
||||
function showGauntletCrownMissionOverlay(mission) {
|
||||
|
||||
@@ -3899,6 +3899,16 @@
|
||||
#special-quiz-overlay .sq-ov-result.is-hidden { display: none; }
|
||||
#special-quiz-overlay .sq-ov-result--ok { color: #0e1226; background: #9ece6a; }
|
||||
#special-quiz-overlay .sq-ov-result--fail { color: #fff; background: rgba(247,118,142,0.9); }
|
||||
#special-quiz-overlay .sq-ov-award { margin-top: 16px; display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; }
|
||||
#special-quiz-overlay .sq-ov-award.is-hidden { display: none; }
|
||||
#special-quiz-overlay .sq-ov-award-title { font-size: 20px; font-weight: 900; color: #ffe7a3; text-shadow: 0 0 14px rgba(255,214,102,0.55); }
|
||||
#special-quiz-overlay .sq-ov-award-img { width: 170px; max-width: 60vw; height: auto; border-radius: 14px; box-shadow: 0 0 34px rgba(255,200,90,0.55), 0 14px 40px rgba(0,0,0,0.55); animation: sqAwardPop .55s cubic-bezier(.2,.9,.3,1.45); }
|
||||
#special-quiz-overlay .sq-ov-award-img[hidden] { display: none; }
|
||||
@keyframes sqAwardPop { from { opacity: 0; transform: translateY(22px) scale(.82) rotate(-5deg); } to { opacity: 1; transform: none; } }
|
||||
#special-quiz-overlay .sq-ov-award-name { font-size: 18px; font-weight: 800; color: #fff; }
|
||||
#special-quiz-overlay .sq-ov-award-effect { font-size: 14px; color: #c0caf5; max-width: 90%; line-height: 1.4; }
|
||||
#special-quiz-overlay .sq-ov-award-btn { margin-top: 6px; cursor: pointer; border: none; border-radius: 999px; padding: 13px 40px; font-size: 17px; font-weight: 800; color: #0e1226; background: linear-gradient(180deg, #ffd666, #f0b429); box-shadow: 0 10px 28px rgba(240,180,41,0.45); transition: filter .12s, transform .08s; }
|
||||
#special-quiz-overlay .sq-ov-award-btn:hover { filter: brightness(1.06); transform: translateY(-1px); }
|
||||
#special-quiz-overlay .sq-ov-members-head { margin-top: 16px; font-size: 12px; letter-spacing: .04em; text-transform: uppercase; color: #7aa2f7; font-weight: 700; }
|
||||
#special-quiz-overlay .sq-ov-members { margin-top: 8px; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
|
||||
@media (max-width: 560px) { #special-quiz-overlay .sq-ov-members { grid-template-columns: 1fr; } }
|
||||
@@ -3949,12 +3959,19 @@
|
||||
<div class="sq-ov-members-head">สมาชิกในรอบนี้ — ต้องตอบถูกครบทุกคน</div>
|
||||
<div id="sq-ov-members" class="sq-ov-members"></div>
|
||||
<div id="sq-ov-result" class="sq-ov-result is-hidden"></div>
|
||||
<div id="sq-ov-award" class="sq-ov-award is-hidden">
|
||||
<div id="sq-ov-award-title" class="sq-ov-award-title">ได้รับการ์ดพิเศษ!</div>
|
||||
<img id="sq-ov-award-img" class="sq-ov-award-img" alt="" />
|
||||
<div id="sq-ov-award-name" class="sq-ov-award-name"></div>
|
||||
<div id="sq-ov-award-effect" class="sq-ov-award-effect"></div>
|
||||
<button type="button" id="sq-ov-award-continue" class="sq-ov-award-btn">เล่นต่อ ▶</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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.0508"></script>
|
||||
<script src="js/play.js?v=0.0509"></script>
|
||||
<div class="version-tag">v —</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -494,6 +494,11 @@ function clearSpecialQuizTimers(space) {
|
||||
space.specialQuizTimers.forEach((t) => clearTimeout(t));
|
||||
}
|
||||
space.specialQuizTimers = [];
|
||||
if (space.specialQuizContinueTimer) {
|
||||
clearTimeout(space.specialQuizContinueTimer);
|
||||
space.specialQuizContinueTimer = null;
|
||||
}
|
||||
space.specialQuizAwaitContinue = false;
|
||||
}
|
||||
|
||||
/** payload ไอคอนสำหรับ client (null = ไม่มี/ถูกทริกแล้ว) */
|
||||
@@ -775,6 +780,24 @@ function endSpecialQuizSession(sid, space, success) {
|
||||
applySpecialCardImmediate(sid, space, sq.card);
|
||||
}
|
||||
io.to(sid).emit('special-quiz-ended', { success: !!success, card: cardOut });
|
||||
/* รอ client กด «เล่นต่อ» ก่อนค่อยเล่นรอบ quiz ต่อ (กันเวลาเดินตอนค้างอ่านการ์ด)
|
||||
— มี safety timeout กันค้างถ้าไม่มีใครกด */
|
||||
space.specialQuizAwaitContinue = true;
|
||||
if (space.specialQuizContinueTimer) clearTimeout(space.specialQuizContinueTimer);
|
||||
space.specialQuizContinueTimer = setTimeout(() => {
|
||||
space.specialQuizContinueTimer = null;
|
||||
finishSpecialQuizContinue(sid, space);
|
||||
}, 32000);
|
||||
}
|
||||
|
||||
/** เล่นรอบ quiz ต่อหลังผู้เล่นกด «เล่นต่อ» (เรียกครั้งเดียว / หรือ safety timeout) */
|
||||
function finishSpecialQuizContinue(sid, space) {
|
||||
if (!space || !space.specialQuizAwaitContinue) return;
|
||||
space.specialQuizAwaitContinue = false;
|
||||
if (space.specialQuizContinueTimer) {
|
||||
clearTimeout(space.specialQuizContinueTimer);
|
||||
space.specialQuizContinueTimer = null;
|
||||
}
|
||||
resumeQuizAfterSpecialQuiz(sid, space);
|
||||
}
|
||||
|
||||
@@ -5930,6 +5953,16 @@ io.on('connection', (socket) => {
|
||||
maybeResolveSpecialQuizAllAnswered(sid, space);
|
||||
});
|
||||
|
||||
/** ผู้เล่นกด «เล่นต่อ» หลังโชว์การ์ดพิเศษ — เล่นรอบ quiz ต่อ (คนแรกที่กดพอ) */
|
||||
socket.on('special-quiz-continue', (_data, cb) => {
|
||||
const reply = typeof cb === 'function' ? cb : () => {};
|
||||
const sid = socket.data.spaceId;
|
||||
const space = sid ? spaces.get(sid) : null;
|
||||
if (!space || !space.peers.has(socket.id)) return reply({ ok: false });
|
||||
finishSpecialQuizContinue(sid, space);
|
||||
reply({ ok: true });
|
||||
});
|
||||
|
||||
/** เปลี่ยนสีเสื้อ/ผิวใน lobby — ห้ามเลือกสีที่คนอื่นใช้แล้ว */
|
||||
socket.on('lobby-tint-update', (data, cb) => {
|
||||
const reply = typeof cb === 'function' ? cb : () => {};
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 2.1 MiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 2.0 MiB |