update mg quest and mobile some path

This commit is contained in:
2026-08-03 03:25:36 +00:00
parent 1f5f1ee321
commit c73b27e89f
7 changed files with 6681 additions and 5787 deletions
+124 -12
View File
@@ -2078,14 +2078,34 @@ function evidencePoolCounts() {
return out;
}
/* แปลงเกรด -> rarity key ('legendary'=ชี้คนร้าย/'rare'/'common') ตามเปอร์เซ็นต์ที่กำหนด */
function rollEvidenceRarityKey(grade) {
/* แปลงเกรด -> rarity key ('legendary'=ชี้คนร้าย/'rare'/'common') ตามเปอรเซนตกำหนด
[2026-07-31] allowLegendary=false ดทองออกแล "เกลี่ยสัดส่วนที่เหลือตามเดิม"
(A: rare:common = 50:20 5/7 : 2/7 · B: 30:50 3/8 : 5/8) ไมใชดไปทางใดทางหน */
function rollEvidenceRarityKey(grade, allowLegendary) {
const r = Math.random();
if (grade === 'A') return r < 0.30 ? 'legendary' : (r < 0.80 ? 'rare' : 'common');
if (grade === 'B') return r < 0.20 ? 'legendary' : (r < 0.50 ? 'rare' : 'common');
const allow = allowLegendary !== false;
if (grade === 'A') {
if (allow) return r < 0.30 ? 'legendary' : (r < 0.80 ? 'rare' : 'common');
return r < (5 / 7) ? 'rare' : 'common';
}
if (grade === 'B') {
if (allow) return r < 0.20 ? 'legendary' : (r < 0.50 ? 'rare' : 'common');
return r < (3 / 8) ? 'rare' : 'common';
}
return r < 0.20 ? 'rare' : 'common'; // C ลงไป: ไม่มีชี้คนร้าย
}
/** [2026-07-31] "" (legendary = ) 2
* 1) แฟมทกำลงสบตองเป "คนร้ายตัวจริง" ทองในแฟมคนบรทธ = หลกฐานชดคน
* 2) งรอบมเกมออกไดใบเดยว ไมาจะมเลนกคน (รวมการดพเศษใบ 7 หลกฐานฟรวย)
* ธงข 2 อยบน space งคมทกเสนทางแจกในรอบเดยวกนโดยอตโนม */
function legendaryAllowedForRun(space, suspectIndex) {
if (!space) return false;
if (space.legendaryGrantedThisRun) return false;
const culprit = (typeof space.culpritIndex === 'number') ? space.culpritIndex : -1;
return culprit >= 0 && Number(suspectIndex) === culprit;
}
/* โฟลเดอร์รูปของผู้ต้องสงสัยตาม config คดี (fallback = suspect-(idx+1)) */
function evidenceImageDirForSuspect(space, suspectIndex) {
const def = EVIDENCE_IMAGE_DIRS[suspectIndex] || EVIDENCE_IMAGE_DIRS[0];
@@ -2104,10 +2124,12 @@ function pickEvidenceCardForSuspect(space, suspectIndex, grade) {
const imageDir = evidenceImageDirForSuspect(space, suspectIndex);
const pools = evidenceImagePools();
const buckets = pools[imageDir] || pools[EVIDENCE_IMAGE_DIRS[0]] || { common: [], rare: [], legendary: [] };
let want = rollEvidenceRarityKey(grade || 'C');
const allowLegendary = legendaryAllowedForRun(space, suspectIndex);
let want = rollEvidenceRarityKey(grade || 'C', allowLegendary);
let pool = buckets[want];
if (!pool || !pool.length) {
const tryOrder = ['common', 'rare', 'legendary'];
/* fallback ตอนพูลว่าง — ถ้าทองยังไม่ได้รับอนุญาต ห้ามหล่นมาลงทองแทน */
const tryOrder = allowLegendary ? ['common', 'rare', 'legendary'] : ['common', 'rare'];
for (const k of tryOrder) { if (buckets[k] && buckets[k].length) { pool = buckets[k]; want = k; break; } }
}
if (!pool || !pool.length) return null;
@@ -2119,11 +2141,14 @@ function evidenceGradeFromPct(avgPct) {
return avgPct >= 80 ? 'A' : avgPct >= 60 ? 'B' : 'C';
}
/* คะแนนดิบของผู้เล่นต่อ gameType (ใช้กรณี normalize เทียบ best) */
/* gameType ( normalize best)
[2026-07-31] MG5 เดมอาน p.gauntletScore jump_survive ไมเคยเขยน (เกมเขยนลง
p.reportedMiniScore = รอด 100 / ตาย 0 server.js:9686) ได 0 กคน = เกรด C ตลอด
แกใหานฟลดเกมเขยนจร เกรดกลายเป "% คนที่รอด" งตรงกบธรรมชาตเกมเอาชตรอด */
function evidencePlayerRawScore(space, p, gameType) {
switch (gameType) {
case 'gauntlet':
case 'jump_survive': return Math.max(0, p.gauntletScore | 0);
case 'gauntlet': return Math.max(0, p.gauntletScore | 0);
case 'jump_survive': return Math.max(0, p.reportedMiniScore | 0);
case 'space_shooter': return Math.max(0, p.spaceShooterScore | 0);
case 'balloon_boss': return Math.max(0, p.balloonBossScore | 0);
default:
@@ -2149,6 +2174,27 @@ function computeRunGradeForEvidence(space) {
return evidenceGradeFromPct(avgPct);
}
}
/* [2026-07-31] MG4 % MG1 ( )
เดมตกไปเขาสาขา default าน gauntlet/spaceShooter/balloonBossScore MG4 ไมเคยเขยน C ตลอด */
if (gameType === 'quiz_carry' && space.quizCarrySession && space.quizCarrySession.players) {
const len = Math.max(0, Number(space.quizCarrySession.sessionLength) || 0);
const total = len * QUIZ_CARRY_POINTS_PER_CORRECT;
const ids = Object.keys(space.quizCarrySession.players);
if (total > 0 && ids.length) {
const avgPct = ids.reduce((s, id) => {
const sc = Math.max(0, Number(space.quizCarrySession.players[id].score) || 0);
return s + Math.min(100, (sc / total) * 100);
}, 0) / ids.length;
return evidenceGradeFromPct(avgPct);
}
}
/* [2026-07-31] MG3 Tower block "" ( )
ในหองไมความหมาย ใชความคบหนาถอดรหสของทมเปนเกรดสมบรณ (แนวเดยวก MG7)
เดมตกไปสาขา default านฟลด MG3 ไมเคยเขยน (เกมเขยนลง p.reportedMiniScore) C ตลอด */
if (gameType === 'stack' && space.stackSession) {
const pct = Math.max(0, Math.min(100, Number(space.stackSession.progressPct) || 0));
return evidenceGradeFromPct(pct);
}
/* Last Light (crown gauntlet): mission payload ()
F (ไมรอด) ไม tier ในหลกฐาน map เป C */
if (gameType === 'gauntlet' && isGauntletCrownHeistMapBySpace(space) && space.lastCrownMissionGrade) {
@@ -4219,11 +4265,56 @@ function awardRandomEvidenceCardToPlayer(space, playerId, suspectIndex, grade) {
return null;
}
list.push(card);
/* [2026-07-31] "" () 3 return null
ไปกอนหนาน ทองจะยงไมกใชทธ คนถดไปในรอบเดยวกนยงมทธได */
if (card.rarity === 'legendary') space.legendaryGrantedThisRun = true;
space.playerEvidence[playerId][suspectIndex] = list;
syncEvidenceByNick(space, playerId);
return card;
}
/** [2026-07-31] "" ( 7 )
* MG3 stack / MG4 quiz_carry ไมตกรอบ กคนไดตามเด
* าน 2 ทาง: ธง/เซสชนฝ server + าท client รายงานตอนจบ (reportedMiniSurvived)
* เพอใหไดคำตอบเดยวกนทงเสนทาง returnDetective และ detective-minigame-finished */
const EVIDENCE_DEATH_GAME_TYPES = ['quiz', 'gauntlet', 'jump_survive', 'space_shooter', 'balloon_boss'];
function playerDiedThisRunForEvidence(space, playerId) {
const p = space && space.peers ? space.peers.get(playerId) : null;
if (!p) return false;
/* gameType space.mapId detective-minigame-finished
แมปถกสลบเป LobbyB ไปแล (server.js:4636) จะไดชนดผดแลวปลอยคนตายผาน
ใชาทจำไวงแต "ตอนเริ่มรอบ" แทน (fallback = แมปปจจ เผ space เกาทงไมลด) */
let gameType = space.detectiveRunGameType || null;
if (!gameType) {
const md = (space.mapId && maps.get(space.mapId)) || space.mapData;
gameType = md && md.gameType;
}
if (EVIDENCE_DEATH_GAME_TYPES.indexOf(gameType) < 0) return false;
if (p.reportedMiniSurvived === false) return true;
switch (gameType) {
case 'quiz': {
const st = space.quizSession && space.quizSession.players ? space.quizSession.players[playerId] : null;
return !!(st && st.eliminated);
}
case 'gauntlet':
return !!p.gauntletEliminated;
case 'jump_survive': {
const sj = space.jumpSurviveSession;
const st = sj && sj.players ? sj.players[playerId] : null;
return !!(st && st.eliminated);
}
case 'space_shooter': {
const ss = space.spaceShooterSession;
const st = ss && ss.players ? ss.players[playerId] : null;
return !!((st && st.eliminated) || p.spaceShooterEliminated);
}
case 'balloon_boss':
return !!p.balloonBossEliminated;
default:
return false;
}
}
/* [achv Phase A 2026-07-05] achievements
b4_data_miner(รวมทกใบ ×100) · b1_evidence_collector(common ×20) · a2_sharp_eye(rare/Silver ×10) · b3_hidden_fragment(legendary ครงแรก)
เฉพาะผเลนจร ( playerKey) ามบอท + เรยกจาก "จุดแจกจริง" 2 เทาน (ไมรวม debug hotkey) */
@@ -4278,10 +4369,22 @@ function grantDetectiveEvidenceForCurrentRun(sid, space, playerIds) {
if (space.detectiveAwardDoneForRun) {
return { suspectIdx, awarded: {}, alreadyGranted: true };
}
const ids = (playerIds && playerIds.length) ? playerIds : [...space.peers.keys()];
const grade = computeRunGradeForEvidence(space);
const idsRaw = (playerIds && playerIds.length) ? playerIds : [...space.peers.keys()];
/* [2026-07-31] ""
ครอบทงการแจกปกตและการดพเศษใบ 7 (หลกฐานฟร) วนรายชอชดเดยวก */
const died = [];
const ids = idsRaw.filter((pid) => {
if (!playerDiedThisRunForEvidence(space, pid)) return true;
died.push(pid);
return false;
});
if (died.length) {
try { console.log('[evidence] ตายในรอบนี้ ' + died.length + ' คน → ไม่ได้การ์ด (' + died.join(',') + ')'); } catch (e) { /* ignore */ }
}
/* [2026-07-31] ใช้เกรดที่ snapshot ไว้ตอนจบรอบ (ก่อนเซสชันถูกล้าง) — ถ้าไม่มีค่อยคิดสด */
const grade = space.pendingRunEvidenceGrade || computeRunGradeForEvidence(space);
const awardedList = {};
ids.forEach((pid) => { awardedList[pid] = []; });
idsRaw.forEach((pid) => { awardedList[pid] = []; });
const awarded = awardDetectiveEvidenceForMinigameEnd(space, suspectIdx, ids, grade);
ids.forEach((pid) => { if (awarded[pid]) awardedList[pid].push(awarded[pid]); });
/* Card 7 Free Evidence — ทุกคนรับหลักฐานเพิ่ม (after_game) */
@@ -4360,6 +4463,9 @@ function beginDetectiveSuspectMinigame(sid, space, cardEntry, selectedIndex) {
armLobbyBLoadedSafety(sid, space); /* backstop กัน deadlock ถ้า signal ไม่ครบ */
space.detectiveAwardDoneForRun = false;
space.coinAwardDoneForRun = false;
space.legendaryGrantedThisRun = false; /* [2026-07-31] ทองออกได้ใบเดียวต่อรอบมินิเกม */
space.detectiveRunGameType = md.gameType || null; /* [2026-07-31] จำชนิดเกมของรอบนี้ไว้ตัดสิน "ตายแล้วไม่ได้การ์ด" */
space.pendingRunEvidenceGrade = null; /* [2026-07-31] เกรดของรอบใหม่ ยังไม่คิด */
space.lastCrownMissionGrade = null;
/* รีเซ็ตคะแนนที่ client รายงาน (stack/quiz_carry) ของรอบก่อน */
space.peers.forEach((p) => { p.reportedMiniScore = 0; p.reportedMiniSurvived = true; });
@@ -4488,6 +4594,12 @@ function beginDetectiveSuspectMinigame(sid, space, cardEntry, selectedIndex) {
function returnDetectiveSpaceToLobbyB(sid, space, message, awardOptions) {
ensurePostCaseLobbyMapLoaded();
/* [2026-07-31] 🔴 ""
เดมไปคดตอนแจกการ (บรรท ~4657) งอย "หลัง" การลาง quiz/stack/quizCarry/jumpSurvive
Session = null (4600-4628) สาขาทานเซสชนตายหมด ตกไปสาขา default าน
gauntlet/spaceShooter/balloonBossScore ได 0 = เกรด C ตลอด (กระทบ MG1, MG3, MG4, MG5)
เกมทเกบคะแนนไวบน peer (MG2/MG6/MG7) ไมโดน เพราะ peer ไมกลาง */
space.pendingRunEvidenceGrade = computeRunGradeForEvidence(space);
/* แจกเหรียญตามอันดับ + คะแนนสะสม ก่อนล้างสถานะมินิเกม (คะแนน/ผู้รอดยังครบ) */
awardMinigameRankCoins(sid, space);
clearSpaceQuizTimers(space);