fix game5 and 7
This commit is contained in:
@@ -3909,6 +3909,11 @@
|
||||
var bp = Number(data.balloonBossBalloonsPerPlayer);
|
||||
inpBp.value = String(Number.isFinite(bp) && bp > 0 ? Math.min(12, Math.floor(bp)) : 0);
|
||||
}
|
||||
var inpDh = el('mega-virus-damage-per-hit');
|
||||
if (inpDh && Object.prototype.hasOwnProperty.call(data, 'balloonBossDamagePerHit')) {
|
||||
var dh = Number(data.balloonBossDamagePerHit);
|
||||
inpDh.value = String(Number.isFinite(dh) && dh > 0 ? Math.max(1, Math.min(100, Math.floor(dh))) : 10);
|
||||
}
|
||||
var bossInp = el('mega-virus-boss-url');
|
||||
if (bossInp && Object.prototype.hasOwnProperty.call(data, 'balloonBossBossImageUrl')) {
|
||||
bossInp.value = data.balloonBossBossImageUrl != null ? String(data.balloonBossBossImageUrl) : '';
|
||||
@@ -3956,6 +3961,9 @@
|
||||
var balloonsPer = el('mega-virus-balloons-per-player') ? parseInt(String(el('mega-virus-balloons-per-player').value), 10) : 0;
|
||||
if (Number.isNaN(balloonsPer) || balloonsPer < 0) balloonsPer = 0;
|
||||
balloonsPer = Math.max(0, Math.min(12, balloonsPer));
|
||||
var dmgPerHit = el('mega-virus-damage-per-hit') ? parseInt(String(el('mega-virus-damage-per-hit').value), 10) : 10;
|
||||
if (Number.isNaN(dmgPerHit) || dmgPerHit < 1) dmgPerHit = 10;
|
||||
dmgPerHit = Math.max(1, Math.min(100, dmgPerHit));
|
||||
gameTimingFetch('GET')
|
||||
.then(function (data) {
|
||||
data.balloonBossMissionTimeSec = limSs;
|
||||
@@ -3963,6 +3971,7 @@
|
||||
data.balloonBossPlayerBalloonImageUrls = balloonUrls;
|
||||
data.balloonBossPlayerBalloonFallbackUrl = fbUrl;
|
||||
data.balloonBossBalloonsPerPlayer = balloonsPer;
|
||||
data.balloonBossDamagePerHit = dmgPerHit;
|
||||
return gameTimingFetch('PUT', data);
|
||||
})
|
||||
.then(function (res) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -821,6 +821,7 @@
|
||||
<div class="form-grid form-inline quiz-timing-grid">
|
||||
<label title="0 = ใช้ 120 วิเมื่อแมปไม่กำหนด · ตั้งอย่างน้อย 10 ถ้าต้องการกำหนดเอง">เวลารอบ (วินาที) <input type="number" id="mega-virus-mission-sec" min="0" max="7200" step="5" value="0"></label>
|
||||
<label title="จำนวนลูกโป่ง (ชีวิต) ต่อผู้เล่น · 0 = ใช้ค่าจากแมป หรือ default 3 · แมปกำหนดทับค่านี้">ลูกโป่งต่อคน <input type="number" id="mega-virus-balloons-per-player" min="0" max="12" step="1" value="0"></label>
|
||||
<label title="ยิงโดนบอส 1 นัด = ลบเลือดบอสเท่านี้ (แยกจากคะแนน) · default 10 · เลือดบอสตั้งในแมป (balloonBossMaxHp default 100)">ลบเลือดบอส/นัด <input type="number" id="mega-virus-damage-per-hit" min="1" max="100" step="1" value="10"></label>
|
||||
</div>
|
||||
<div class="form-grid form-inline" style="margin-top:0.75rem;align-items:flex-end;gap:0.75rem;flex-wrap:wrap">
|
||||
<label class="space-shooter-ship-url-label" style="flex:1;min-width:14rem">รูปบอส (URL) <input type="text" id="mega-virus-boss-url" maxlength="500" spellcheck="false" placeholder="/Game/img/MegaVirus/boss.png" autocomplete="off"></label>
|
||||
@@ -1357,7 +1358,7 @@
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
<script src="admin.js?v=94"></script>
|
||||
<script src="admin.js?v=95"></script>
|
||||
<script>
|
||||
/* toggle: เปิด/ปิด HUD โหลด LobbyA (Iron Man) ให้ "ผู้เล่นทั่วไป" เห็น (เก็บใน game-timing.json: lobbyDebugHud)
|
||||
— dev เปิดเครื่องตัวเองได้เสมอด้วย ?dbg=1 หรือ localStorage.lobbyDbg='1' โดยไม่ต้องใช้ปุ่มนี้ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -114,9 +114,9 @@
|
||||
"providerUserId": "p_1775128666204_xzgg2n6x8h",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 363,
|
||||
"coins": 437,
|
||||
"createdAt": "2026-04-02T11:17:46+00:00",
|
||||
"updatedAt": "2026-07-03T11:54:27+00:00",
|
||||
"updatedAt": "2026-07-08T12:21:48+00:00",
|
||||
"lobbyColorThemeIndex": 1,
|
||||
"lobbySkinToneIndex": 3,
|
||||
"daily": {
|
||||
@@ -132,12 +132,12 @@
|
||||
],
|
||||
"lockUntilMs": 0
|
||||
},
|
||||
"score": 318,
|
||||
"score": 392,
|
||||
"scoreByCase": {
|
||||
"6": 56,
|
||||
"13": 50,
|
||||
"13": 70,
|
||||
"5": 8,
|
||||
"12": 6,
|
||||
"12": 60,
|
||||
"10": 106,
|
||||
"3": 10,
|
||||
"2": 26,
|
||||
@@ -148,11 +148,26 @@
|
||||
"achievements": {
|
||||
"d1_minigame_solver": 20,
|
||||
"a1_first_deduction": 1,
|
||||
"a5_truth_hunter": 3,
|
||||
"a5_truth_hunter": 4,
|
||||
"e2_the_impostor": 1,
|
||||
"e4_agent_of_chaos": 1,
|
||||
"e3_master_of_doubt": 1,
|
||||
"e5_slippery_eel": 1
|
||||
"e5_slippery_eel": 1,
|
||||
"b1_evidence_collector": 6,
|
||||
"b4_data_miner": 4,
|
||||
"a2_sharp_eye": 2,
|
||||
"d3_the_backbone": 6,
|
||||
"c5_lone_wolf": 1,
|
||||
"c2_high_stakes": 1,
|
||||
"a4_logic_over_luck": 1,
|
||||
"d2_silent_guardian": 2,
|
||||
"a6_unbreakable_logic": 1,
|
||||
"d4_flawless_diver": 1,
|
||||
"b2_relentless_investigator": 1
|
||||
},
|
||||
"achvStreak": {
|
||||
"a6_unbreakable_logic": 1,
|
||||
"d4_flawless_diver": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -340,7 +355,7 @@
|
||||
"blocked": false,
|
||||
"coins": 50,
|
||||
"createdAt": "2026-06-19T06:13:44+00:00",
|
||||
"updatedAt": "2026-07-02T10:45:20+00:00",
|
||||
"updatedAt": "2026-07-08T07:22:42+00:00",
|
||||
"score": 50,
|
||||
"scoreByCase": {
|
||||
"1": 12,
|
||||
@@ -364,9 +379,9 @@
|
||||
"providerUserId": "p_1781849642042_x2vt68wscm",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 169,
|
||||
"coins": 183,
|
||||
"createdAt": "2026-06-19T06:14:02+00:00",
|
||||
"updatedAt": "2026-07-03T11:55:41+00:00",
|
||||
"updatedAt": "2026-07-08T12:21:48+00:00",
|
||||
"daily": {
|
||||
"anchorMs": 1781802000000,
|
||||
"claimedDays": [
|
||||
@@ -380,18 +395,22 @@
|
||||
],
|
||||
"lockUntilMs": 0
|
||||
},
|
||||
"score": 144,
|
||||
"score": 158,
|
||||
"scoreByCase": {
|
||||
"1": 66,
|
||||
"7": 16,
|
||||
"5": 10,
|
||||
"2": 40,
|
||||
"6": 10,
|
||||
"3": 2
|
||||
"3": 2,
|
||||
"12": 8,
|
||||
"13": 6
|
||||
},
|
||||
"lbName": "tomato",
|
||||
"achievements": {
|
||||
"d1_minigame_solver": 19
|
||||
"d1_minigame_solver": 20,
|
||||
"b5_deep_scanner": 1,
|
||||
"b1_evidence_collector": 1
|
||||
},
|
||||
"lobbyColorThemeIndex": 1,
|
||||
"lobbySkinToneIndex": 1
|
||||
@@ -749,18 +768,19 @@
|
||||
"providerUserId": "p_1782122326943_7p2fnvivscm",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 309,
|
||||
"coins": 335,
|
||||
"createdAt": "2026-06-22T09:58:46+00:00",
|
||||
"updatedAt": "2026-07-06T11:31:06+00:00",
|
||||
"lobbyColorThemeIndex": 7,
|
||||
"updatedAt": "2026-07-08T17:04:52+00:00",
|
||||
"lobbyColorThemeIndex": 1,
|
||||
"lobbySkinToneIndex": 2,
|
||||
"score": 284,
|
||||
"score": 310,
|
||||
"scoreByCase": {
|
||||
"10": 44,
|
||||
"10": 52,
|
||||
"12": 142,
|
||||
"3": 54,
|
||||
"13": 30,
|
||||
"8": 14
|
||||
"8": 14,
|
||||
"2": 18
|
||||
},
|
||||
"lbName": "Q",
|
||||
"achievements": {
|
||||
@@ -769,9 +789,9 @@
|
||||
"e4_agent_of_chaos": 1,
|
||||
"e3_master_of_doubt": 1,
|
||||
"e5_slippery_eel": 1,
|
||||
"b4_data_miner": 5,
|
||||
"b4_data_miner": 12,
|
||||
"a2_sharp_eye": 2,
|
||||
"b1_evidence_collector": 2,
|
||||
"b1_evidence_collector": 10,
|
||||
"b3_hidden_fragment": 1,
|
||||
"d3_the_backbone": 3,
|
||||
"a3_mind_architect": 1,
|
||||
@@ -790,7 +810,7 @@
|
||||
false,
|
||||
false
|
||||
],
|
||||
"lockUntilMs": 1783357200000
|
||||
"lockUntilMs": 0
|
||||
},
|
||||
"achvStreak": {
|
||||
"a6_unbreakable_logic": 0,
|
||||
@@ -932,17 +952,17 @@
|
||||
"providerUserId": "p_1782300287206_l5omneu1yeo",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 169,
|
||||
"coins": 207,
|
||||
"createdAt": "2026-06-24T11:24:48+00:00",
|
||||
"updatedAt": "2026-07-01T12:20:59+00:00",
|
||||
"lobbyColorThemeIndex": 3,
|
||||
"updatedAt": "2026-07-08T12:21:48+00:00",
|
||||
"lobbyColorThemeIndex": 6,
|
||||
"lobbySkinToneIndex": 3,
|
||||
"score": 144,
|
||||
"score": 162,
|
||||
"scoreByCase": {
|
||||
"6": 24,
|
||||
"13": 44,
|
||||
"13": 52,
|
||||
"5": 16,
|
||||
"12": 8,
|
||||
"12": 18,
|
||||
"3": 20,
|
||||
"7": 4,
|
||||
"2": 14,
|
||||
@@ -952,20 +972,30 @@
|
||||
"achievements": {
|
||||
"d1_minigame_solver": 20,
|
||||
"a1_first_deduction": 1,
|
||||
"a5_truth_hunter": 1
|
||||
"a5_truth_hunter": 1,
|
||||
"b4_data_miner": 4,
|
||||
"a2_sharp_eye": 1,
|
||||
"d3_the_backbone": 3,
|
||||
"b2_relentless_investigator": 1,
|
||||
"d2_silent_guardian": 1,
|
||||
"e1_the_observer": 1,
|
||||
"b1_evidence_collector": 2
|
||||
},
|
||||
"daily": {
|
||||
"anchorMs": 1782406800000,
|
||||
"claimedDays": [
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
],
|
||||
"lockUntilMs": 1782925200000
|
||||
"lockUntilMs": 1783530000000
|
||||
},
|
||||
"achvStreak": {
|
||||
"e1_the_observer": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1066,25 +1096,39 @@
|
||||
"providerUserId": "p_1782472374020_hlha51h8q2m",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 183,
|
||||
"coins": 260,
|
||||
"createdAt": "2026-06-26T11:12:52+00:00",
|
||||
"updatedAt": "2026-07-02T07:25:12+00:00",
|
||||
"updatedAt": "2026-07-08T12:21:48+00:00",
|
||||
"lobbyColorThemeIndex": 8,
|
||||
"lobbySkinToneIndex": 3,
|
||||
"score": 138,
|
||||
"score": 190,
|
||||
"scoreByCase": {
|
||||
"10": 60,
|
||||
"6": 8,
|
||||
"3": 16,
|
||||
"12": 10,
|
||||
"12": 44,
|
||||
"1": 10,
|
||||
"7": 10,
|
||||
"2": 14,
|
||||
"13": 10
|
||||
"13": 28
|
||||
},
|
||||
"lbName": "MOOKIZ",
|
||||
"achievements": {
|
||||
"d1_minigame_solver": 16
|
||||
"d1_minigame_solver": 20,
|
||||
"b5_deep_scanner": 1,
|
||||
"b4_data_miner": 6,
|
||||
"b1_evidence_collector": 5,
|
||||
"d3_the_backbone": 6,
|
||||
"a1_first_deduction": 1,
|
||||
"c5_lone_wolf": 1,
|
||||
"c2_high_stakes": 1,
|
||||
"a4_logic_over_luck": 1,
|
||||
"b2_relentless_investigator": 1,
|
||||
"d2_silent_guardian": 1,
|
||||
"e1_the_observer": 1,
|
||||
"d4_flawless_diver": 1,
|
||||
"a6_unbreakable_logic": 1,
|
||||
"a2_sharp_eye": 1
|
||||
},
|
||||
"daily": {
|
||||
"anchorMs": 1782666000000,
|
||||
@@ -1092,12 +1136,17 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
],
|
||||
"lockUntilMs": 1783011600000
|
||||
"lockUntilMs": 1783530000000
|
||||
},
|
||||
"achvStreak": {
|
||||
"e1_the_observer": 1,
|
||||
"d4_flawless_diver": 1,
|
||||
"a6_unbreakable_logic": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1120,26 +1169,39 @@
|
||||
"providerUserId": "p_1778156246099_lbrni0cvx8",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 116,
|
||||
"coins": 142,
|
||||
"createdAt": "2026-06-29T07:25:24+00:00",
|
||||
"updatedAt": "2026-07-03T11:58:39+00:00",
|
||||
"score": 116,
|
||||
"updatedAt": "2026-07-08T12:12:56+00:00",
|
||||
"score": 142,
|
||||
"scoreByCase": {
|
||||
"10": 58,
|
||||
"8": 10,
|
||||
"7": 2,
|
||||
"1": 18,
|
||||
"6": 28
|
||||
"6": 28,
|
||||
"12": 16,
|
||||
"13": 10
|
||||
},
|
||||
"lbName": "บอท 666",
|
||||
"lbName": "สรยุทธ์",
|
||||
"achievements": {
|
||||
"d1_minigame_solver": 15,
|
||||
"d1_minigame_solver": 20,
|
||||
"e2_the_impostor": 1,
|
||||
"e4_agent_of_chaos": 2,
|
||||
"e4_agent_of_chaos": 3,
|
||||
"e3_master_of_doubt": 1,
|
||||
"e5_slippery_eel": 1,
|
||||
"e5_slippery_eel": 2,
|
||||
"a1_first_deduction": 1,
|
||||
"a5_truth_hunter": 1
|
||||
"a5_truth_hunter": 1,
|
||||
"b4_data_miner": 7,
|
||||
"a2_sharp_eye": 1,
|
||||
"b1_evidence_collector": 3,
|
||||
"d3_the_backbone": 6,
|
||||
"e1_the_observer": 2,
|
||||
"d4_flawless_diver": 0,
|
||||
"b3_hidden_fragment": 1
|
||||
},
|
||||
"achvStreak": {
|
||||
"e1_the_observer": 2,
|
||||
"d4_flawless_diver": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1231,16 +1293,16 @@
|
||||
"providerUserId": "p_1782921490642_wkx6gl2hwtn",
|
||||
"notes": "auto: game-award",
|
||||
"blocked": false,
|
||||
"coins": 24,
|
||||
"score": 24,
|
||||
"coins": 32,
|
||||
"score": 32,
|
||||
"scoreByCase": {
|
||||
"1": 24
|
||||
"1": 32
|
||||
},
|
||||
"lbName": "MONE",
|
||||
"lbName": "Guest",
|
||||
"createdAt": "2026-07-01T16:01:03+00:00",
|
||||
"updatedAt": "2026-07-01T16:08:23+00:00",
|
||||
"updatedAt": "2026-07-08T10:34:54+00:00",
|
||||
"achievements": {
|
||||
"d1_minigame_solver": 3
|
||||
"d1_minigame_solver": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1251,16 +1313,18 @@
|
||||
"providerUserId": "p_1782921488461_e17kxhzmrl8",
|
||||
"notes": "auto: game-award",
|
||||
"blocked": false,
|
||||
"coins": 18,
|
||||
"score": 18,
|
||||
"coins": 28,
|
||||
"score": 28,
|
||||
"scoreByCase": {
|
||||
"1": 18
|
||||
"1": 28
|
||||
},
|
||||
"lbName": "ผู้เล่น",
|
||||
"lbName": "Guest",
|
||||
"createdAt": "2026-07-01T16:01:03+00:00",
|
||||
"updatedAt": "2026-07-01T16:08:23+00:00",
|
||||
"updatedAt": "2026-07-08T10:34:54+00:00",
|
||||
"achievements": {
|
||||
"d1_minigame_solver": 1
|
||||
"d1_minigame_solver": 2,
|
||||
"b4_data_miner": 1,
|
||||
"b1_evidence_collector": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1355,16 +1419,16 @@
|
||||
"providerUserId": "g_103253816568665853265",
|
||||
"notes": "auto: game-award",
|
||||
"blocked": false,
|
||||
"coins": 30,
|
||||
"score": 30,
|
||||
"coins": 70,
|
||||
"score": 70,
|
||||
"scoreByCase": {
|
||||
"1": 30
|
||||
"1": 70
|
||||
},
|
||||
"lbName": "TOY Studio",
|
||||
"createdAt": "2026-07-07T07:06:32+00:00",
|
||||
"updatedAt": "2026-07-07T07:21:02+00:00",
|
||||
"updatedAt": "2026-07-08T06:57:39+00:00",
|
||||
"achievements": {
|
||||
"d1_minigame_solver": 1
|
||||
"d1_minigame_solver": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1375,20 +1439,38 @@
|
||||
"providerUserId": "p_1783423451842_11irmcfil84",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 10,
|
||||
"coins": 84,
|
||||
"createdAt": "2026-07-07T11:24:11+00:00",
|
||||
"updatedAt": "2026-07-07T13:10:37+00:00",
|
||||
"score": 10,
|
||||
"updatedAt": "2026-07-08T17:17:36+00:00",
|
||||
"score": 84,
|
||||
"scoreByCase": {
|
||||
"2": 10
|
||||
"2": 20,
|
||||
"12": 24,
|
||||
"13": 20,
|
||||
"10": 20
|
||||
},
|
||||
"lbName": "ผู้เล่น",
|
||||
"lbName": "กัน จอมพลัง",
|
||||
"achievements": {
|
||||
"d1_minigame_solver": 1,
|
||||
"b4_data_miner": 3,
|
||||
"b1_evidence_collector": 1,
|
||||
"a2_sharp_eye": 2
|
||||
}
|
||||
"d1_minigame_solver": 11,
|
||||
"b4_data_miner": 19,
|
||||
"b1_evidence_collector": 11,
|
||||
"a2_sharp_eye": 7,
|
||||
"d3_the_backbone": 6,
|
||||
"d4_flawless_diver": 0,
|
||||
"b2_relentless_investigator": 1,
|
||||
"d2_silent_guardian": 1,
|
||||
"b5_deep_scanner": 1,
|
||||
"e1_the_observer": 1,
|
||||
"a6_unbreakable_logic": 0,
|
||||
"b3_hidden_fragment": 1
|
||||
},
|
||||
"achvStreak": {
|
||||
"d4_flawless_diver": 0,
|
||||
"e1_the_observer": 1,
|
||||
"a6_unbreakable_logic": 0
|
||||
},
|
||||
"lobbyColorThemeIndex": 7,
|
||||
"lobbySkinToneIndex": 1
|
||||
},
|
||||
{
|
||||
"id": "056ac410650650b51ad4f969",
|
||||
@@ -1401,6 +1483,302 @@
|
||||
"coins": 0,
|
||||
"createdAt": "2026-07-07T13:14:37+00:00",
|
||||
"updatedAt": "2026-07-07T13:14:37+00:00"
|
||||
},
|
||||
{
|
||||
"id": "c102247fb56343cb7c07d383",
|
||||
"email": "",
|
||||
"displayName": "Guest",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "p_1783488401360_la99satzc7m",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 10,
|
||||
"createdAt": "2026-07-08T05:26:41+00:00",
|
||||
"updatedAt": "2026-07-09T04:02:24+00:00",
|
||||
"daily": {
|
||||
"anchorMs": 1783530000000,
|
||||
"claimedDays": [
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
],
|
||||
"lockUntilMs": 1783616400000
|
||||
},
|
||||
"lobbyColorThemeIndex": 5,
|
||||
"lobbySkinToneIndex": 1
|
||||
},
|
||||
{
|
||||
"id": "99ceaaa5bba7f30ccaacf955",
|
||||
"email": "",
|
||||
"displayName": "Guest",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "p_1783490562751_hcpqt0gpbj5",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 10,
|
||||
"createdAt": "2026-07-08T06:02:42+00:00",
|
||||
"updatedAt": "2026-07-08T11:51:25+00:00",
|
||||
"daily": {
|
||||
"anchorMs": 1783443600000,
|
||||
"claimedDays": [
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
],
|
||||
"lockUntilMs": 1783530000000
|
||||
},
|
||||
"lobbyColorThemeIndex": 7,
|
||||
"lobbySkinToneIndex": 3,
|
||||
"achievements": {
|
||||
"b4_data_miner": 3,
|
||||
"a2_sharp_eye": 2,
|
||||
"b3_hidden_fragment": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "a4ee55fab2ff81fdadd86874",
|
||||
"email": "",
|
||||
"displayName": "Guest",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "p_1783491385591_hxztc6q0pup",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 10,
|
||||
"createdAt": "2026-07-08T06:16:25+00:00",
|
||||
"updatedAt": "2026-07-08T06:16:49+00:00",
|
||||
"daily": {
|
||||
"anchorMs": 1783443600000,
|
||||
"claimedDays": [
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
],
|
||||
"lockUntilMs": 1783530000000
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "a552b03c208421f2e15d1e5c",
|
||||
"email": "",
|
||||
"displayName": "Guest",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "p_1783492264923_akwsutojqys",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 0,
|
||||
"createdAt": "2026-07-08T06:31:04+00:00",
|
||||
"updatedAt": "2026-07-08T06:31:04+00:00"
|
||||
},
|
||||
{
|
||||
"id": "099987d8b3b22a5fd72de4ab",
|
||||
"email": "",
|
||||
"displayName": "Guest",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "p_1783498064493_7q7w9qal0bc",
|
||||
"notes": "auto: achievements",
|
||||
"blocked": false,
|
||||
"coins": 44,
|
||||
"achievements": {
|
||||
"b5_deep_scanner": 2,
|
||||
"d1_minigame_solver": 5
|
||||
},
|
||||
"createdAt": "2026-07-08T08:24:23+00:00",
|
||||
"updatedAt": "2026-07-08T10:34:54+00:00",
|
||||
"score": 44,
|
||||
"scoreByCase": {
|
||||
"1": 44
|
||||
},
|
||||
"lbName": "Guest"
|
||||
},
|
||||
{
|
||||
"id": "c32c748d2c799560ac6817d6",
|
||||
"email": "",
|
||||
"displayName": "SimSolo",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "simkey_ho00kinngy",
|
||||
"notes": "auto: game-award",
|
||||
"blocked": false,
|
||||
"coins": 10,
|
||||
"score": 10,
|
||||
"scoreByCase": {
|
||||
"1": 10
|
||||
},
|
||||
"lbName": "SimSolo",
|
||||
"createdAt": "2026-07-08T09:00:55+00:00",
|
||||
"updatedAt": "2026-07-08T09:00:55+00:00",
|
||||
"achievements": {
|
||||
"d1_minigame_solver": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cd7961fe98cddb94988a53fe",
|
||||
"email": "",
|
||||
"displayName": "SimSolo",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "simkey_r9zqefndca",
|
||||
"notes": "auto: achievements",
|
||||
"blocked": false,
|
||||
"coins": 10,
|
||||
"achievements": {
|
||||
"d1_minigame_solver": 1
|
||||
},
|
||||
"createdAt": "2026-07-08T09:02:07+00:00",
|
||||
"updatedAt": "2026-07-08T09:02:07+00:00",
|
||||
"score": 10,
|
||||
"scoreByCase": {
|
||||
"1": 10
|
||||
},
|
||||
"lbName": "SimSolo"
|
||||
},
|
||||
{
|
||||
"id": "9e9f65d26b0de4e149d4949d",
|
||||
"email": "",
|
||||
"displayName": "Guest",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "simkey_sg3pikxq3x",
|
||||
"notes": "auto: achievements",
|
||||
"blocked": false,
|
||||
"coins": 0,
|
||||
"achievements": {
|
||||
"b1_evidence_collector": 1,
|
||||
"d1_minigame_solver": 1,
|
||||
"b4_data_miner": 1
|
||||
},
|
||||
"createdAt": "2026-07-08T09:07:18+00:00",
|
||||
"updatedAt": "2026-07-08T09:07:18+00:00"
|
||||
},
|
||||
{
|
||||
"id": "cce5a4032e3a1d477af96ba1",
|
||||
"email": "",
|
||||
"displayName": "Guest",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "p_1783504619686_yd6bngw7w1j",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 0,
|
||||
"createdAt": "2026-07-08T09:57:00+00:00",
|
||||
"updatedAt": "2026-07-08T10:04:41+00:00",
|
||||
"achievements": {
|
||||
"b5_deep_scanner": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "409de8e9da4690a6fcc8c527",
|
||||
"email": "",
|
||||
"displayName": "Guest",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "p_1783499004206_k0t9nw3s8s",
|
||||
"notes": "auto: achievements",
|
||||
"blocked": false,
|
||||
"coins": 6,
|
||||
"achievements": {
|
||||
"d1_minigame_solver": 1,
|
||||
"b5_deep_scanner": 1,
|
||||
"b4_data_miner": 1
|
||||
},
|
||||
"createdAt": "2026-07-08T10:34:54+00:00",
|
||||
"updatedAt": "2026-07-08T13:16:15+00:00",
|
||||
"score": 6,
|
||||
"scoreByCase": {
|
||||
"1": 6
|
||||
},
|
||||
"lbName": "Guest"
|
||||
},
|
||||
{
|
||||
"id": "d5f19965d63102d32f1e7ad2",
|
||||
"email": "",
|
||||
"displayName": "Guest",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "p_1783510048205_5nggtubx9f3",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 0,
|
||||
"createdAt": "2026-07-08T11:27:28+00:00",
|
||||
"updatedAt": "2026-07-08T11:27:28+00:00"
|
||||
},
|
||||
{
|
||||
"id": "0dd6bbeb46926b62ba3c8b87",
|
||||
"email": "",
|
||||
"displayName": "Guest",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "p_1783512570968_6r0ooctea8",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 0,
|
||||
"createdAt": "2026-07-08T12:09:31+00:00",
|
||||
"updatedAt": "2026-07-08T12:09:31+00:00"
|
||||
},
|
||||
{
|
||||
"id": "5a94f9199f1412978b1aee8a",
|
||||
"email": "",
|
||||
"displayName": "Guest",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "p_1783520037906_2d2qs3gr7us",
|
||||
"notes": "auto: achievements",
|
||||
"blocked": false,
|
||||
"coins": 20,
|
||||
"achievements": {
|
||||
"b4_data_miner": 6,
|
||||
"b1_evidence_collector": 5,
|
||||
"b3_hidden_fragment": 1,
|
||||
"b5_deep_scanner": 2,
|
||||
"d1_minigame_solver": 2,
|
||||
"a2_sharp_eye": 1
|
||||
},
|
||||
"createdAt": "2026-07-08T14:15:53+00:00",
|
||||
"updatedAt": "2026-07-08T17:31:49+00:00",
|
||||
"score": 20,
|
||||
"scoreByCase": {
|
||||
"1": 20
|
||||
},
|
||||
"lbName": "Guest"
|
||||
},
|
||||
{
|
||||
"id": "fb4b4dea7f60a773a456b2e5",
|
||||
"email": "",
|
||||
"displayName": "ผู้เล่น",
|
||||
"loginType": "guest",
|
||||
"providerUserId": "p_1783523564193_ag9odfihrd",
|
||||
"notes": "auto: player-coins",
|
||||
"blocked": false,
|
||||
"coins": 20,
|
||||
"createdAt": "2026-07-08T15:12:42+00:00",
|
||||
"updatedAt": "2026-07-08T15:18:54+00:00",
|
||||
"achievements": {
|
||||
"b5_deep_scanner": 1,
|
||||
"b1_evidence_collector": 1,
|
||||
"d1_minigame_solver": 1,
|
||||
"b4_data_miner": 1
|
||||
},
|
||||
"score": 10,
|
||||
"scoreByCase": {
|
||||
"1": 10
|
||||
},
|
||||
"lbName": "ผู้เล่น",
|
||||
"daily": {
|
||||
"anchorMs": 1783443600000,
|
||||
"claimedDays": [
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
],
|
||||
"lockUntilMs": 1783530000000
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"gauntletTickMs": 220,
|
||||
"gauntletJumpTicks": 4,
|
||||
"gauntletJumpHeightMult": 0.52,
|
||||
"gauntletJumpTicks": 1,
|
||||
"gauntletJumpHeightMult": 1.5,
|
||||
"gauntletTimeLimitSec": 0,
|
||||
"troublesomeOfferSec": 15,
|
||||
"gauntletLaneImageUrls": [
|
||||
@@ -96,10 +96,11 @@
|
||||
],
|
||||
"balloonBossPlayerBalloonFallbackUrl": "/Game/img/MegaVirus/Artboard%209.png",
|
||||
"balloonBossBalloonsPerPlayer": 3,
|
||||
"balloonBossDamagePerHit": 10,
|
||||
"forcedMinigameKeys": [
|
||||
"quiz_carry",
|
||||
"jump_survive",
|
||||
"balloon_boss"
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"testSpecialCardByMap": {},
|
||||
"troublesomeForceOffer": false,
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -564,7 +564,7 @@
|
||||
'</div>';
|
||||
document.body.appendChild(ov);
|
||||
var closeFn = function () { ov.style.display = 'none'; };
|
||||
ov.addEventListener('click', function (e) { if (e.target === ov || (e.target.classList && e.target.classList.contains('ecl-close'))) closeFn(); });
|
||||
ov.addEventListener('click', function (e) { if (e.target === ov || (e.target.closest && e.target.closest('.ecl-close'))) closeFn(); });
|
||||
document.addEventListener('keydown', function (e) { if (e.key === 'Escape' && ov.style.display !== 'none') closeFn(); });
|
||||
}
|
||||
var img = ov.querySelector('.ecl-img');
|
||||
@@ -3646,6 +3646,22 @@
|
||||
function isMeGauntletJumpAnimActivePlay() {
|
||||
return meGauntletJumpAnimStart > 0 && (Date.now() - meGauntletJumpAnimStart) < meGauntletJumpAnimDur;
|
||||
}
|
||||
/** peer อื่น: เริ่ม "อาร์คกระโดด" เมื่อ server ส่ง gauntletJumpSeq เพิ่มขึ้น (นับครั้งเริ่มกระโดด)
|
||||
แก้บั๊ก "คนอื่นกระโดดแล้วเราไม่เห็น": gauntletJumpTicks ถูกตัด 0 ใน tick เดียวกันตอนข้ามสำเร็จ
|
||||
→ peer ไม่เคยเห็นค่า >0 → ไม่เด้ง · seq ไม่ถูกรีเซ็ต จึงจับ "เริ่มกระโดด" ได้เสมอ (mirror อาร์ค local) */
|
||||
function notePeerGauntletJumpFromSync(o, seqRaw) {
|
||||
if (!o) return;
|
||||
const seq = Number(seqRaw) || 0;
|
||||
if (!Object.prototype.hasOwnProperty.call(o, 'gauntletJumpSeq')) { o.gauntletJumpSeq = seq; return; }
|
||||
if (seq > (o.gauntletJumpSeq || 0)) {
|
||||
o.gauntletJumpSeq = seq;
|
||||
o.gauntletJumpAnimStart = Date.now();
|
||||
o.gauntletJumpAnimDur = Math.max(360, (gauntletRuntimeJumpTicks || 6) * (gauntletRuntimeTickMs || 220));
|
||||
}
|
||||
}
|
||||
function isPeerGauntletJumpAnimActive(o) {
|
||||
return !!(o && o.gauntletJumpAnimStart > 0 && (Date.now() - o.gauntletJumpAnimStart) < o.gauntletJumpAnimDur);
|
||||
}
|
||||
/** ซิงก์จากเซิร์ฟเวอร์ (gauntlet-sync / GET /api/game-timing) */
|
||||
let gauntletRuntimeTickMs = 220;
|
||||
let gauntletRuntimeJumpTicks = 6;
|
||||
@@ -3688,6 +3704,8 @@
|
||||
let playSpaceShooterShipDamageOverlayUrls = ['', '', ''];
|
||||
/** balloon_boss / Mega Virus — จาก game-timing */
|
||||
let playBalloonBossMissionTimeSec = 0;
|
||||
/** ดาเมจต่อการยิงโดนบอส (ลบเลือดบอส/นัด) — Admin Minigame-7 · แยกจากคะแนน · default 10 */
|
||||
let playBalloonBossDamagePerHit = 10;
|
||||
let playBalloonBossBossImageUrl = '';
|
||||
let playBalloonBossPlayerBalloonImageUrls = ['', '', '', '', '', ''];
|
||||
let playBalloonBossPlayerBalloonFallbackUrl = '';
|
||||
@@ -6700,18 +6718,15 @@
|
||||
if (isSpaceShooter() || isBalloonBoss()) {
|
||||
const mwPx = w * tileSize;
|
||||
const mhPx = h * tileSize;
|
||||
/* fit ทั้งแมปให้ขอบแมปอยู่ในเฟรมเสมอ → ยาน/บอทที่ clamp อยู่ในขอบแมป [22, mw-22] จะไม่หลุดออกนอกจอ
|
||||
(เดิม balloon_boss ซูมเข้าหา content-window ทำให้ขอบแมปหลุดนอกจอ = ลมกระโชกดันยาน/บอทลอยหายนอกเฟรม)
|
||||
BG วาด cover เต็มจอแล้ว (draw ~25633) ขอบดำซ้าย-ขวาจึงไม่โผล่แม้ซูมออก แค่ world rect เล็กลงเล็กน้อย */
|
||||
zDraw = Math.min(canvas.width / mwPx, canvas.height / mhPx) * 0.96;
|
||||
/* MG7 (balloon_boss) — ขยายให้เต็มจอกว่า fit ทั้งแมป: ซูมพอดีกับพื้นที่ผู้เล่น+บอส (crop ขอบบน-ล่างที่ว่าง)
|
||||
แมป 20×15 (aspect 1.33) บนจอ 16:9 ถ้า fit ทั้งแมปจะเหลือขอบดำซ้าย-ขวาเยอะ */
|
||||
if (isBalloonBoss()) {
|
||||
const win = getBalloonBossVisibleHalfTilesPlay(mapData);
|
||||
if (win) {
|
||||
const needWpx = win.halfW * 2 * tileSize;
|
||||
const needHpx = win.halfH * 2 * tileSize;
|
||||
const zContent = Math.min(canvas.width / needWpx, canvas.height / needHpx);
|
||||
if (Number.isFinite(zContent) && zContent > zDraw) zDraw = zContent;
|
||||
}
|
||||
}
|
||||
} else if (isJumpSurvive()) {
|
||||
/* MG5 (jump_survive) — เกมเดียวที่ตกไปใช้ zoom ดิบ 1.4 (ไม่ fit จอ = เหลือขอบซ้าย-ขวา)
|
||||
→ fit ความกว้างเต็มจอ (vertical scroller เลื่อนแนวตั้งด้วย jumpSurviveCamCenterY อยู่แล้ว) */
|
||||
const mwPx = w * tileSize;
|
||||
if (mwPx > 0) zDraw = canvas.width / mwPx;
|
||||
} else if (isQuizQuestionMissionHudActivePlay()) {
|
||||
const qmc = getQuizQuestionMissionMapCenterWorldPxPlay();
|
||||
if (qmc) {
|
||||
@@ -10350,6 +10365,13 @@
|
||||
quizCarryPregameActive = true;
|
||||
quizCarryLobbyReadyMap = {};
|
||||
quizCarryPregameHumanIds().forEach((id) => { quizCarryLobbyReadyMap[id] = false; });
|
||||
/* MG4: อุ่น sprite + tint ตัวละคร (เรา+เพื่อน) ตอนเข้า HOW TO — กัน avatar บนแมป/SCORE bar จาง (ก้อน silhouette)
|
||||
ตอน pregame เพราะเลเยอร์ย้อมสี in-game ยังโหลดไม่เสร็จ (เกม crown ใช้ lobby-avatar ที่ warm แล้วจึงไม่เจอ) */
|
||||
try {
|
||||
const warmEnt = (cid, tint) => { if (!cid) return; preloadPlayCharacterLayers(cid); if (tint) preloadPlayTintForAvatar(cid, tint); };
|
||||
warmEnt(me.characterId || getPlayCharacterId(), me.playTint);
|
||||
others.forEach((o) => { if (o) warmEnt(o.characterId, o.playTint); });
|
||||
} catch (e) { /* ignore */ }
|
||||
showQuizCarryPregameOverlay();
|
||||
/* ขอสถานะ ready ปัจจุบันจาก server (authoritative) — ทุกคนรวม host ต้องกด READY เองตาม flow */
|
||||
if (socket && socket.connected) socket.emit('quiz-carry-lobby-sync-request');
|
||||
@@ -13417,6 +13439,10 @@
|
||||
playBalloonBossMissionTimeSec = 0;
|
||||
}
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(payload, 'balloonBossDamagePerHit')) {
|
||||
const dh = Number(payload.balloonBossDamagePerHit);
|
||||
playBalloonBossDamagePerHit = Math.max(1, Math.min(100, Number.isFinite(dh) && dh > 0 ? Math.floor(dh) : 10));
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(payload, 'balloonBossBossImageUrl')) {
|
||||
playBalloonBossBossImageUrl = normalizeGauntletAssetUrlForPlay(
|
||||
typeof payload.balloonBossBossImageUrl === 'string' ? payload.balloonBossBossImageUrl : ''
|
||||
@@ -18504,7 +18530,7 @@
|
||||
tMax: 0.85,
|
||||
});
|
||||
const addScore = 10;
|
||||
const addBossDmg = 2;
|
||||
const addBossDmg = playBalloonBossDamagePerHit; /* ลบเลือดบอส/นัด (ตั้งใน Admin) — แยกจากคะแนน · default 10 */
|
||||
/* score/dmg: เจ้าของเท่านั้นเป็นคนบวก (มนุษย์=ตัวเอง broadcast ผ่าน move, บอท=host broadcast ผ่าน fill-bot-state)
|
||||
เครื่องอื่นห้ามบวกเอง — เดิม non-owner บวกจากกระสุนที่ถึงคนละจังหวะ → คะแนน/HP สุดท้ายไม่ตรง */
|
||||
if (b.ownerId === myId) {
|
||||
@@ -20141,6 +20167,13 @@
|
||||
const prevWasSpaceShooter = mapData && mapData.gameType === 'space_shooter';
|
||||
const prevWasBalloonBoss = mapData && mapData.gameType === 'balloon_boss';
|
||||
mapData = gameMapData;
|
||||
/* MG5 (jump_survive): server สุ่ม pattern แพลตฟอร์ม 1 อัน/เกม แล้วส่งมาใน game-start (res.jsLayout)
|
||||
→ override layout ให้ทุก client เห็น pattern เดียวกัน (client physics/render อ่าน mapData ตรง ไม่มี cache) */
|
||||
if (res && res.jsLayout && mapData && mapData.gameType === 'jump_survive'
|
||||
&& Array.isArray(res.jsLayout.platformArea) && Array.isArray(res.jsLayout.variantArea)) {
|
||||
mapData.jumpSurvivePlatformArea = res.jsLayout.platformArea;
|
||||
mapData.jumpSurvivePlatformVariantArea = res.jsLayout.variantArea;
|
||||
}
|
||||
playEmbedUserZoomMul = 1;
|
||||
if (mapData.gameType !== 'quiz_carry') {
|
||||
quizCarryWalkSpeedMultActive = QUIZ_CARRY_WALK_SPEED_MULT;
|
||||
@@ -22445,6 +22478,7 @@
|
||||
const jt = Number(p.gauntletJumpTicks);
|
||||
o.gauntletJumpTicks = Number.isFinite(jt) ? jt : 0;
|
||||
if (o.gauntletJumpVis == null) o.gauntletJumpVis = o.gauntletJumpTicks;
|
||||
notePeerGauntletJumpFromSync(o, p.gauntletJumpSeq);
|
||||
const sc = Number(p.gauntletScore);
|
||||
const newSc = Number.isFinite(sc) ? Math.max(0, sc) : 0;
|
||||
o.gauntletScore = newSc;
|
||||
@@ -22500,6 +22534,7 @@
|
||||
const jt = Number(p.gauntletJumpTicks);
|
||||
o.gauntletJumpTicks = Number.isFinite(jt) ? jt : 0;
|
||||
if (o.gauntletJumpVis == null) o.gauntletJumpVis = o.gauntletJumpTicks;
|
||||
notePeerGauntletJumpFromSync(o, p.gauntletJumpSeq);
|
||||
const sc = Number(p.gauntletScore);
|
||||
const newSc = Number.isFinite(sc) ? Math.max(0, sc) : 0;
|
||||
o.gauntletScore = newSc;
|
||||
@@ -23503,6 +23538,7 @@
|
||||
const tx = +p[0], ty = +p[1];
|
||||
if (!bp[ty] || bp[ty][tx] !== 1) continue;
|
||||
for (const [, o] of others) {
|
||||
if (o.quizCannotTrue && o.quizCannotFalse) continue; /* MG1: ผี (ตกรอบ) = spectator ไม่บล็อกการเดิน */
|
||||
if (playPeerBlockPlayerOccupiesTile(o.x, o.y, tx, ty)) return false;
|
||||
}
|
||||
}
|
||||
@@ -23552,9 +23588,11 @@
|
||||
if (!bp[ty] || bp[ty][tx] !== 1) continue;
|
||||
for (const [, peer] of others) {
|
||||
if (o && peer === o) continue;
|
||||
if (peer.quizCannotTrue && peer.quizCannotFalse) continue; /* MG1: ผีไม่บล็อก */
|
||||
if (playPeerBlockPlayerOccupiesTile(peer.x, peer.y, tx, ty)) return false;
|
||||
}
|
||||
if (o && playPeerBlockPlayerOccupiesTile(me.x, me.y, tx, ty)) return false;
|
||||
const meGhost = !!(playQuizPlayerLocal && playQuizPlayerLocal.cannotTrue && playQuizPlayerLocal.cannotFalse);
|
||||
if (o && !meGhost && playPeerBlockPlayerOccupiesTile(me.x, me.y, tx, ty)) return false;
|
||||
}
|
||||
}
|
||||
if (isQuiz()) {
|
||||
@@ -26868,9 +26906,16 @@
|
||||
const op = lerpGauntletEntityPos(o.x, o.y, o.tx, o.ty, oAir ? GAUNTLET_AIR_X_LERP : GAUNTLET_VIS_LERP);
|
||||
o.x = op.nx;
|
||||
o.y = op.ny;
|
||||
if (gauntletFinishWalkPose) { o.gauntletJumpTicks = 0; o.gauntletJumpVis = 0; return; }
|
||||
if (o.gauntletJumpVis == null) o.gauntletJumpVis = o.gauntletJumpTicks || 0;
|
||||
o.gauntletJumpVis = stepGauntletJumpVis(o.gauntletJumpVis, o.gauntletJumpTicks || 0);
|
||||
if (gauntletFinishWalkPose) { o.gauntletJumpTicks = 0; o.gauntletJumpVis = 0; o.gauntletJumpAnimStart = 0; return; }
|
||||
if (isPeerGauntletJumpAnimActive(o)) {
|
||||
/* อาร์ค peer: prog 0→1 ; vis = max·(1−prog) → เห็นคนอื่นกระโดดขึ้น-ลงเต็มโค้ง (mirror อาร์ค local) */
|
||||
const oprog = Math.max(0, Math.min(1, (Date.now() - o.gauntletJumpAnimStart) / o.gauntletJumpAnimDur));
|
||||
o.gauntletJumpVis = (gauntletRuntimeJumpTicks || 6) * (1 - oprog);
|
||||
} else {
|
||||
if (o.gauntletJumpAnimStart > 0) o.gauntletJumpAnimStart = 0;
|
||||
if (o.gauntletJumpVis == null) o.gauntletJumpVis = o.gauntletJumpTicks || 0;
|
||||
o.gauntletJumpVis = stepGauntletJumpVis(o.gauntletJumpVis, o.gauntletJumpTicks || 0);
|
||||
}
|
||||
});
|
||||
clampPlayEntityFootprintToMap(me, mapData);
|
||||
others.forEach((o) => {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -6426,7 +6426,7 @@
|
||||
document.head.appendChild(st);
|
||||
}
|
||||
var closeFn = function () { ov.classList.add('is-hidden'); ov.style.display = 'none'; };
|
||||
ov.addEventListener('click', function (e) { if (e.target === ov || e.target.classList.contains('ecl-close')) closeFn(); });
|
||||
ov.addEventListener('click', function (e) { if (e.target === ov || (e.target.closest && e.target.closest('.ecl-close'))) closeFn(); });
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape' && ov.style.display !== 'none') closeFn();
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5458,7 +5458,7 @@
|
||||
<script src="/Game/socket.io/socket.io.js"></script>
|
||||
<script src="js/version.js?v=0.0306"></script>
|
||||
<script src="js/sound.js?v=1"></script>
|
||||
<script src="js/play.js?v=0.006301082"></script>
|
||||
<script src="js/play.js?v=0.006301121"></script>
|
||||
<div class="version-tag">v —</div>
|
||||
<style id="qc-howto-mg2-fix">
|
||||
/* HOW TO PLAY ของ quiz_carry (Minigame-4) -> ให้เหมือน Minigame-2 (gch-mg2-mock)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1648,7 +1648,7 @@
|
||||
<script src="js/customize-popup.js?v=40" data-customize-triggers="" data-customize-asset-base="img/03-5-Customize"></script>
|
||||
<script src="js/achievements.js?v=0.002" data-asset-base="img/03-6-Profile"></script>
|
||||
<script src="js/sound.js?v=1"></script>
|
||||
<script src="js/room-lobby.js?v=0.0351"></script>
|
||||
<script src="js/room-lobby.js?v=0.0352"></script>
|
||||
<div class="version-tag">v —</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+75
-18
@@ -2288,6 +2288,8 @@ function defaultGameTiming() {
|
||||
balloonBossPlayerBalloonFallbackUrl: '/Game/img/MegaVirus/Artboard 9.png',
|
||||
/** จำนวนลูกโป่งต่อคน (0 = ใช้ค่าจากแมป หรือ default 3) */
|
||||
balloonBossBalloonsPerPlayer: 0,
|
||||
/** ดาเมจต่อการยิงโดนบอส (ลบเลือดบอส/นัด) — ตั้งใน Admin Minigame-7 · แยกจากคะแนน */
|
||||
balloonBossDamagePerHit: 10,
|
||||
/** โหมดเทสต์: เกมบังคับต่อการ์ด 3 ใบ — ['','',''] = สุ่มหมด, แต่ละช่องใส่ key เพื่อเจาะจงใบนั้น */
|
||||
forcedMinigameKeys: ['', '', ''],
|
||||
/** โหมดเทสต์: บังคับการ์ดพิเศษต่อเกม { mapId: cardId } */
|
||||
@@ -2713,6 +2715,9 @@ function loadGameTiming() {
|
||||
balloonBossBalloonsPerPlayer: Object.prototype.hasOwnProperty.call(j, 'balloonBossBalloonsPerPlayer')
|
||||
? Math.max(0, Math.min(12, Math.floor(Number(j.balloonBossBalloonsPerPlayer)) || 0))
|
||||
: 0,
|
||||
balloonBossDamagePerHit: Object.prototype.hasOwnProperty.call(j, 'balloonBossDamagePerHit')
|
||||
? Math.max(1, Math.min(100, Math.floor(Number(j.balloonBossDamagePerHit)) || 10))
|
||||
: 10,
|
||||
forcedMinigameKeys: normalizeForcedMinigameKeys(
|
||||
j.forcedMinigameKeys != null ? j.forcedMinigameKeys : j.forcedMinigameKey,
|
||||
),
|
||||
@@ -2739,6 +2744,44 @@ function loadGameTiming() {
|
||||
|
||||
let runtimeGameTiming = loadGameTiming();
|
||||
|
||||
/** MG5 jump_survive: pool ของ pattern แพลตฟอร์ม (verify reachability offline แล้ว) — สุ่ม 1 อัน/เกม
|
||||
เพื่อให้ layout หลากหลาย/เดายาก · pattern[0] = layout เดิม (baseline) · โหลดครั้งเดียวตอน boot */
|
||||
let jumpSurvivePatterns = [];
|
||||
function loadJumpSurvivePatterns() {
|
||||
try {
|
||||
const p = path.join(__dirname, 'data', 'jump-survive-patterns.json');
|
||||
if (fs.existsSync(p)) {
|
||||
const j = JSON.parse(fs.readFileSync(p, 'utf8'));
|
||||
if (j && Array.isArray(j.patterns)) {
|
||||
jumpSurvivePatterns = j.patterns.filter((x) => x && Array.isArray(x.platformArea) && Array.isArray(x.variantArea));
|
||||
}
|
||||
}
|
||||
} catch (e) { console.error('loadJumpSurvivePatterns', e.message); jumpSurvivePatterns = []; }
|
||||
}
|
||||
loadJumpSurvivePatterns();
|
||||
/** เลือก pattern สุ่ม → เก็บบน space (ใช้ทั้ง server bot physics + ส่งให้ client) · คงเดิมถ้าไม่มี pool */
|
||||
function pickJumpSurviveLayoutForSpace(space) {
|
||||
if (!space || !jumpSurvivePatterns.length) return null;
|
||||
const idx = Math.floor(Math.random() * jumpSurvivePatterns.length);
|
||||
const pat = jumpSurvivePatterns[idx] || jumpSurvivePatterns[0];
|
||||
space.jsLayout = { idx, platformArea: pat.platformArea, variantArea: pat.variantArea };
|
||||
space._jsEffMd = null; /* invalidate effMd cache */
|
||||
return space.jsLayout;
|
||||
}
|
||||
/** md ที่ override platformArea/variantArea ด้วย pattern ที่เลือก (สร้าง 1 ครั้ง/เกม, cache บน space)
|
||||
ไม่ mutate แมป share (หลายห้องเล่นพร้อมกันได้) */
|
||||
function jsMap(space) {
|
||||
const base = (space && space.mapId && maps.get(space.mapId)) || (space && space.mapData) || null;
|
||||
if (!base || !space || !space.jsLayout) return base;
|
||||
if (space._jsEffMd && space._jsEffMd.__base === base) return space._jsEffMd;
|
||||
space._jsEffMd = Object.assign(Object.create(base), {
|
||||
__base: base,
|
||||
jumpSurvivePlatformArea: space.jsLayout.platformArea,
|
||||
jumpSurvivePlatformVariantArea: space.jsLayout.variantArea,
|
||||
});
|
||||
return space._jsEffMd;
|
||||
}
|
||||
|
||||
/** จำนวนลูกโป่งต่อคน Mega Virus — แมปกำหนดก่อน, ไม่งั้นใช้ค่ากลางจาก admin, สุดท้าย default 3 (clamp 1-12) */
|
||||
function balloonBossBalloonsForMap(md) {
|
||||
const fromMap = Math.floor(Number(md && md.balloonBossBalloonsPerPlayer)) || 0;
|
||||
@@ -2873,6 +2916,13 @@ function saveGameTimingToFile(d) {
|
||||
const balloonBossBalloonsPerPlayer = Object.prototype.hasOwnProperty.call(d, 'balloonBossBalloonsPerPlayer')
|
||||
? Math.max(0, Math.min(12, Math.floor(Number(d.balloonBossBalloonsPerPlayer)) || 0))
|
||||
: prevBbCount;
|
||||
/* ดาเมจต่อการยิงโดนบอส (แยกจากคะแนน) — Admin Minigame-7 */
|
||||
const prevBbDmg = Object.prototype.hasOwnProperty.call(prev, 'balloonBossDamagePerHit')
|
||||
? Math.max(1, Math.min(100, Math.floor(Number(prev.balloonBossDamagePerHit)) || 10))
|
||||
: 10;
|
||||
const balloonBossDamagePerHit = Object.prototype.hasOwnProperty.call(d, 'balloonBossDamagePerHit')
|
||||
? Math.max(1, Math.min(100, Math.floor(Number(d.balloonBossDamagePerHit)) || 10))
|
||||
: prevBbDmg;
|
||||
const prevStackTowerSec = Object.prototype.hasOwnProperty.call(prev, 'stackTowerMissionTimeSec')
|
||||
? prev.stackTowerMissionTimeSec
|
||||
: 90;
|
||||
@@ -2938,6 +2988,7 @@ function saveGameTimingToFile(d) {
|
||||
balloonBossPlayerBalloonImageUrls,
|
||||
balloonBossPlayerBalloonFallbackUrl,
|
||||
balloonBossBalloonsPerPlayer,
|
||||
balloonBossDamagePerHit,
|
||||
forcedMinigameKeys: Object.prototype.hasOwnProperty.call(d, 'forcedMinigameKeys')
|
||||
? normalizeForcedMinigameKeys(d.forcedMinigameKeys)
|
||||
: (Object.prototype.hasOwnProperty.call(d, 'forcedMinigameKey')
|
||||
@@ -4006,6 +4057,9 @@ function beginDetectiveSuspectMinigame(sid, space, cardEntry, selectedIndex) {
|
||||
space.quizSession = null;
|
||||
space.mapId = mapId;
|
||||
space.mapData = md;
|
||||
/* MG5: สุ่ม pattern แพลตฟอร์ม 1 อัน/เกม (layout หลากหลาย/เดายาก) — เก็บบน space, ส่งให้ client ผ่าน game-start */
|
||||
space.jsLayout = null; space._jsEffMd = null;
|
||||
if (md && md.gameType === 'jump_survive') pickJumpSurviveLayoutForSpace(space);
|
||||
glog(sid, space, 'game-start', 'เริ่มมินิเกม: ' + ((md && md.name) || mapId) + ' (การ์ด ' + ((selectedIndex != null ? selectedIndex + 1 : '?')) + ')');
|
||||
/* สุ่มไอคอนคำถามพิเศษสำหรับรอบนี้ (1 ใน 3) — ส่งจริงผ่าน joinCb เมื่อ client เข้า play.html */
|
||||
maybeSpawnSpecialQuizForRun(space);
|
||||
@@ -4091,6 +4145,7 @@ function beginDetectiveSuspectMinigame(sid, space, cardEntry, selectedIndex) {
|
||||
minigameLabel: cardEntry.labelTh,
|
||||
bannedPlayerId: space.bannedThisRunPlayerId || null,
|
||||
};
|
||||
if (space.jsLayout) gameStartPayload.jsLayout = space.jsLayout;
|
||||
if (md.gameType === 'gauntlet' && space.gauntletRun) {
|
||||
gameStartPayload.gauntletEndsAt = space.gauntletRun.endsAt != null ? space.gauntletRun.endsAt : null;
|
||||
}
|
||||
@@ -4811,7 +4866,6 @@ function resolveQuizRound(sid, space, md) {
|
||||
const results = [];
|
||||
|
||||
const ejectMoves = [];
|
||||
const tc191Rows = []; /* [TC191] verify: เทียบผลตัดสิน "แถวเท้า" vs "หัว(เดิม)" ต่อคน */
|
||||
|
||||
space.peers.forEach((p, peerId) => {
|
||||
const st = sess.players[peerId];
|
||||
@@ -4860,14 +4914,6 @@ function resolveQuizRound(sid, space, md) {
|
||||
});
|
||||
}
|
||||
|
||||
/* [TC191] เก็บบรรทัดเทียบ: เท้า(ที่ใช้จริง) vs หัว(สูตรเดิม single-tile) → พิสูจน์ว่าตัดสินที่แถวเท้า */
|
||||
{
|
||||
const headY = Math.floor(Number(p.y));
|
||||
tc191Rows.push((p.nickname || '?').slice(0, 8) + ' fY=' + qFeetTy + ' hY=' + headY
|
||||
+ ' เท้า[T' + (inT ? 1 : 0) + 'F' + (inF ? 1 : 0) + ']'
|
||||
+ ' หัวเดิม[T' + (quizCellOn(tGrid, qBaseTx, headY) ? 1 : 0) + 'F' + (quizCellOn(fGrid, qBaseTx, headY) ? 1 : 0) + ']'
|
||||
+ ' → ' + (choice === true ? 'จริง' : choice === false ? 'เท็จ' : '-') + (right ? '✓' : '✗'));
|
||||
}
|
||||
results.push({
|
||||
id: peerId,
|
||||
nickname: p.nickname || '',
|
||||
@@ -4878,10 +4924,6 @@ function resolveQuizRound(sid, space, md) {
|
||||
});
|
||||
});
|
||||
|
||||
if (tc191Rows.length) {
|
||||
try { glog(sid, space, 'mg1-feet', '[TC191] Q' + (idx + 1) + ' ตัดสินแถวเท้า: ' + tc191Rows.join(' | ')); } catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
ejectMoves.forEach((ev) => {
|
||||
io.to(sid).emit('user-move', ev);
|
||||
try {
|
||||
@@ -8012,9 +8054,10 @@ function gauntletBotDecideJump(b, obstacles, md, w, h) {
|
||||
const roll = Math.random();
|
||||
if (sameCell && roll < pSame) {
|
||||
b.gauntletJumpTicks = getGauntletJumpTicks();
|
||||
b.gauntletJumpSeq = (b.gauntletJumpSeq || 0) + 1;
|
||||
return;
|
||||
}
|
||||
if (incomingCol && roll < pAhead) b.gauntletJumpTicks = getGauntletJumpTicks();
|
||||
if (incomingCol && roll < pAhead) { b.gauntletJumpTicks = getGauntletJumpTicks(); b.gauntletJumpSeq = (b.gauntletJumpSeq || 0) + 1; }
|
||||
}
|
||||
|
||||
/** ฟิสิกส์บอท 1 ตัว 1 tick (server) — mirror applyGauntletPhysicsToPreviewBot + runGauntletTick peer loop */
|
||||
@@ -8117,6 +8160,7 @@ function emitGauntletSync(sid, space) {
|
||||
lobbyColorThemeIndex: p.lobbyColorThemeIndex || null,
|
||||
lobbySkinToneIndex: p.lobbySkinToneIndex || null,
|
||||
gauntletJumpTicks: p.gauntletJumpTicks || 0,
|
||||
gauntletJumpSeq: p.gauntletJumpSeq || 0,
|
||||
gauntletScore: p.gauntletScore || 0,
|
||||
gauntletEliminated: !!p.gauntletEliminated,
|
||||
}));
|
||||
@@ -8130,6 +8174,7 @@ function emitGauntletSync(sid, space) {
|
||||
direction: b.dir || 'right',
|
||||
isBot: true,
|
||||
gauntletJumpTicks: b.gauntletJumpTicks || 0,
|
||||
gauntletJumpSeq: b.gauntletJumpSeq || 0,
|
||||
gauntletScore: b.gauntletScore || 0,
|
||||
gauntletEliminated: !!b.gauntletEliminated,
|
||||
};
|
||||
@@ -8869,7 +8914,7 @@ function createJumpSurviveBots(space, md) {
|
||||
}
|
||||
}
|
||||
function startJumpSurviveGame(sid, space) {
|
||||
const md = (space.mapId && maps.get(space.mapId)) || space.mapData;
|
||||
const md = jsMap(space); /* ใช้ pattern ที่สุ่มไว้ (effMd) — bot/spawn ตรงกับ client */
|
||||
if (!md || md.gameType !== 'jump_survive') return;
|
||||
if (!space.detectiveMinigameActive) return; /* เกมจริงเท่านั้น — editor preview คง client-sim */
|
||||
if (space.jumpSurviveSession && space.jumpSurviveSession.active) return;
|
||||
@@ -8923,7 +8968,7 @@ function endJumpSurviveGame(sid, space, reason) {
|
||||
function stepJumpSurviveBots(sid, space, dt, now) {
|
||||
const s = space.jumpSurviveSession;
|
||||
if (!s || !s.active || s.ended) return;
|
||||
const md = (space.mapId && maps.get(space.mapId)) || space.mapData;
|
||||
const md = jsMap(space); /* ใช้ pattern ที่สุ่มไว้ (effMd) */
|
||||
if (!md || md.gameType !== 'jump_survive') return;
|
||||
/* ขยับบอทเฉพาะหลังนับถอยหลัง 3-2-1 จบ (liveBeginsAt) — ก่อนหน้านี้บอทเริ่มทันทีที่ session active
|
||||
ทำให้บอทวิ่ง/กระโดดก่อน "1" จบ → กันด้วยการ return จนถึงเวลาจริง (เหมือน scroll ที่อิง liveBeginsAt อยู่แล้ว) */
|
||||
@@ -9179,6 +9224,8 @@ function bbTimeLimitSec(md) {
|
||||
return Number.isFinite(rt) && rt > 0 && rt < 7200 ? Math.floor(rt) : 120;
|
||||
}
|
||||
function bbMaxHp(md) { const n = Number(md.balloonBossMaxHp); return Math.max(20, Math.min(9999, Number.isFinite(n) ? Math.floor(n) : 100)); }
|
||||
/* ดาเมจต่อการยิงโดนบอส (ลบเลือดบอส/นัด) จาก game-timing (Admin Minigame-7) — แยกจากคะแนน · default 10 */
|
||||
function bbDamagePerHit() { const n = Number(runtimeGameTiming && runtimeGameTiming.balloonBossDamagePerHit); return Math.max(1, Math.min(100, Number.isFinite(n) && n > 0 ? Math.floor(n) : 10)); }
|
||||
function bbBossCenter(md, ts) {
|
||||
const bx = md.balloonBossBossSpawn;
|
||||
if (bx && Number.isFinite(Number(bx.x)) && Number.isFinite(Number(bx.y))) return { cx: (Number(bx.x) + 0.5) * ts, cy: (Number(bx.y) + 0.5) * ts };
|
||||
@@ -9331,7 +9378,7 @@ function stepBalloonBossBots(sid, space, dt, now) {
|
||||
io.to(sid).emit('balloon-boss-shot', { sx, sy, vx, vy, ownerId: id, t0: now });
|
||||
b.score = Math.max(0, (b.score | 0) - 5); /* สเปก: ยิง 1 ครั้ง −5 */
|
||||
const hitProb = b.tier === 'sharp' ? 0.55 : b.tier === 'weak' ? 0.26 : 0.4;
|
||||
if (Math.random() < hitProb) { b.score += 10; b.dmg += 2; } /* โดนบอส: +10 คะแนน, −2 HP บอส */
|
||||
if (Math.random() < hitProb) { b.score += 10; b.dmg += bbDamagePerHit(); } /* โดนบอส: +10 คะแนน, −HP บอสตามค่า Admin (default 10) */
|
||||
}
|
||||
outBots.push({ id, cx: b.cx, cy: b.cy, score: b.score, dmg: b.dmg, balloons: b.balloons, elim: false });
|
||||
});
|
||||
@@ -9899,6 +9946,9 @@ function runGauntletTick(sid, space) {
|
||||
if (p.gauntletJumpPending) {
|
||||
if ((p.gauntletJumpTicks || 0) === 0) {
|
||||
p.gauntletJumpTicks = getGauntletJumpTicks();
|
||||
/* นับครั้งเริ่มกระโดด (ไม่รีเซ็ตตอนข้ามสำเร็จ) → ให้ peer เห็นอาร์คกระโดดเต็ม
|
||||
แม้ gauntletJumpTicks ถูกตัด 0 ใน tick เดียวกันตอน advanceX (peer ไม่เคยเห็นค่า >0) */
|
||||
p.gauntletJumpSeq = (p.gauntletJumpSeq || 0) + 1;
|
||||
}
|
||||
p.gauntletJumpPending = false;
|
||||
}
|
||||
@@ -11083,6 +11133,7 @@ io.on('connection', (socket) => {
|
||||
missionLiveBeginsAt: space.missionLiveBeginsAt || null,
|
||||
missionLive: isMinigameLiveForRejoinResume(space), /* rejoin กลางเกม live → client ข้าม how-to เข้าเล่นต่อ */
|
||||
};
|
||||
if (space.jsLayout) joinCb.jsLayout = space.jsLayout; /* MG5: ส่ง pattern ที่สุ่มไว้ให้ client (initial + late-join) */
|
||||
if (serverMapIsPostCaseLobbyB(space)) {
|
||||
joinCb.detectiveLobbyLevel = space.detectiveLobbyLevel != null ? space.detectiveLobbyLevel : null;
|
||||
joinCb.detectiveLobbyCaseId = space.detectiveLobbyCaseId != null ? space.detectiveLobbyCaseId : null;
|
||||
@@ -12276,6 +12327,9 @@ io.on('connection', (socket) => {
|
||||
space.mapId = mapId;
|
||||
space.mapData = maps.get(mapId);
|
||||
const md = space.mapData;
|
||||
/* MG5: สุ่ม pattern แพลตฟอร์ม 1 อัน/เกม (เหมือน detective starter) */
|
||||
space.jsLayout = null; space._jsEffMd = null;
|
||||
if (md && md.gameType === 'jump_survive') pickJumpSurviveLayoutForSpace(space);
|
||||
if (md && md.gameType === 'quiz_battle' && quizBattlePathModeActiveServer(md)) {
|
||||
space.peers.forEach((p) => {
|
||||
const sn = snapPositionOntoQuizBattlePathServer(md, Number(p.x), Number(p.y));
|
||||
@@ -12324,6 +12378,7 @@ io.on('connection', (socket) => {
|
||||
caseId: caseId || undefined,
|
||||
peersSnap: peersSnap || undefined,
|
||||
};
|
||||
if (space.jsLayout) gameStartPayload.jsLayout = space.jsLayout;
|
||||
if (peersSnap) gameStartPayload.gauntletEndsAt = gauntletEndsAtEmit != null ? gauntletEndsAtEmit : null;
|
||||
if (mapId && maps.has(mapId) && (isBalloonBossMissionShellSpace(space) || isQuizQuestionMissionShellSpace(space) || isStackTowerMissionShellSpace(space) || isJumpSurviveMissionShellSpace(space) || isSpaceShooterMissionShellSpace(space))) {
|
||||
const grs = space.gauntletRun;
|
||||
@@ -13072,7 +13127,9 @@ io.on('connection', (socket) => {
|
||||
const nd = Math.floor(Number(data.balloonBossBossDmg));
|
||||
if (Number.isFinite(nd) && nd >= 0) {
|
||||
const prevD = Math.max(0, p.balloonBossBossDmg | 0);
|
||||
if (nd <= prevD + 8) p.balloonBossBossDmg = Math.max(prevD, nd);
|
||||
/* เพดานเพิ่ม/แพ็กเก็ต = เผื่อยิงโดนหลายนัดต่อ move (ดาเมจ/นัดตั้งได้ถึง 100) */
|
||||
const bbDmgCap = Math.max(8, bbDamagePerHit() * 3);
|
||||
if (nd <= prevD + bbDmgCap) p.balloonBossBossDmg = Math.max(prevD, nd);
|
||||
}
|
||||
}
|
||||
if (data.balloonBossBalloons != null) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+3013
-15836
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user