diff --git a/www/html/Game/public/js/play.js b/www/html/Game/public/js/play.js index a2899c9..23593f0 100644 --- a/www/html/Game/public/js/play.js +++ b/www/html/Game/public/js/play.js @@ -75,6 +75,18 @@ const SPACE_SHOOTER_MISSION_MAX_ASTEROID_HITS = 3; const SPACE_SHOOTER_MISSION_HIT_INVULN_MS = 1400; const SPACE_SHOOTER_MISSION_SHIP_HIT_RADIUS = 12; + /** อุกาบาต: HP สุ่ม 1–5 ต่อก้อน (ไม่วาดหัวใจบนก้อน) — ขนาดตาม HP เทียบสเกล 5 */ + const SPACE_SHOOTER_ASTEROID_MAX_HP = 5; + const SPACE_SHOOTER_ASTEROID_RADIUS_AT_FULL = 48; + const SPACE_SHOOTER_ASTEROID_RADIUS_AT_MIN_HP = 11; + + function spaceShooterAsteroidRadiusFromHpPlay(hp) { + const cap = SPACE_SHOOTER_ASTEROID_MAX_HP; + const h = Math.max(0, Math.min(cap, Math.floor(Number(hp)) || 0)); + const frac = h <= 0 ? 0 : h / cap; + return SPACE_SHOOTER_ASTEROID_RADIUS_AT_MIN_HP + + (SPACE_SHOOTER_ASTEROID_RADIUS_AT_FULL - SPACE_SHOOTER_ASTEROID_RADIUS_AT_MIN_HP) * frac; + } function spaceShooterResetMissionShipStateForAllPlay() { function resetEnt(ent) { @@ -123,6 +135,22 @@ if (!o) return; tryHit(o, o.spaceShooterCx, o.spaceShooterCy); }); + if (spaceShooterMissionEveryParticipantEliminatedPlay()) { + endSpaceShooterMissionRound('all_dead'); + } + } + + /** Space Shooter ภารกิจ: ผู้เข้าร่วมทุกคนถูกกำจัดแล้ว (รวมเรา) */ + function spaceShooterMissionEveryParticipantEliminatedPlay() { + if (!isSpaceShooterMissionUiMapPlay() || spaceShooterMissionPhase !== 'live' || spaceShooterGameEnded) return false; + if (myId == null) return false; + if (!me.spaceShooterEliminated) return false; + let anyAlive = false; + others.forEach(function (o) { + if (!o) return; + if (!o.spaceShooterEliminated) anyAlive = true; + }); + return !anyAlive; } /** จนกว่าโหลด /api/characters — placeholder ชั่วคราวก่อน join */ @@ -4648,6 +4676,49 @@ } } + /** + * Space Shooter mnpz6rkp: หมดเวลา = แฟลช result-timeup แล้ว result-gameover แล้ว GCM; + * ทุกคนตาย = แฟลช result-gameover อย่างเดียวแล้ว GCM + */ + function beginSpaceShooterMissionResultFlashSequenceThenGcm(mission, endKind) { + if (!mission || mission.uiSkin !== 'violent_crime') { + showGauntletCrownMissionOverlay(mission); + return; + } + hideStackTowerResultFlashDomOnlyPlay(); + const ov = document.getElementById('stack-tower-result-flash'); + const imgEl = document.getElementById('stack-tower-result-flash-img'); + if (!ov || !imgEl) { + showGauntletCrownMissionOverlay(mission); + return; + } + const finishToGcm = function () { + hideStackTowerResultFlashDomOnlyPlay(); + showGauntletCrownMissionOverlay(mission); + }; + const showOneFlash = function (file, onDone) { + imgEl.onerror = function () { + imgEl.onerror = null; + onDone(); + }; + imgEl.src = violentCrimeAssetUrl(file); + ov.classList.remove('is-hidden'); + ov.setAttribute('aria-hidden', 'false'); + stackTowerResultFlashTimer = setTimeout(function () { + stackTowerResultFlashTimer = null; + onDone(); + }, STACK_TOWER_RESULT_FLASH_MS); + }; + if (endKind === 'time_up') { + showOneFlash('result-timeup.png', function () { + hideStackTowerResultFlashDomOnlyPlay(); + showOneFlash('result-gameover.png', finishToGcm); + }); + } else { + showOneFlash('result-gameover.png', finishToGcm); + } + } + function stackTowerMissionTimeLimitSecPlay() { const t = Number(playStackTowerMissionTimeSec); if (Number.isFinite(t) && t > 0) return Math.max(10, Math.min(7200, Math.floor(t))); @@ -5817,8 +5888,9 @@ }; } - function endSpaceShooterMissionRound() { + function endSpaceShooterMissionRound(endKind) { if (!isSpaceShooterMissionUiMapPlay() || spaceShooterGameEnded) return; + const kind = endKind === 'all_dead' ? 'all_dead' : 'time_up'; spaceShooterGameEnded = true; spaceShooterMissionPhase = 'ended'; applySpaceShooterMissionPanelImages(); @@ -5827,7 +5899,9 @@ spaceShooterAsteroidExplosions = []; spaceShooterSpawnAccMs = 0; spaceShooterPopups = []; - showGauntletCrownMissionOverlay(spaceShooterBuildMissionPayload()); + const mission = spaceShooterBuildMissionPayload(); + mission.spaceShooterEndKind = kind; + beginSpaceShooterMissionResultFlashSequenceThenGcm(mission, kind); } function questionMissionAssetUrl(file) { @@ -10067,7 +10141,7 @@ } const gcmHead = document.getElementById('gcm-heading'); if (gcmHead) { - if (mission && (mission.uiSkin === 'question_mission' || mission.uiSkin === 'stack_tower' || mission.uiSkin === 'mega_virus')) gcmHead.classList.add('sr-only'); + if (mission && (mission.uiSkin === 'question_mission' || mission.uiSkin === 'stack_tower' || mission.uiSkin === 'mega_virus' || mission.uiSkin === 'jumper' || mission.uiSkin === 'violent_crime')) gcmHead.classList.add('sr-only'); else gcmHead.classList.remove('sr-only'); } ov.classList.remove('is-hidden'); @@ -10081,7 +10155,7 @@ if (previewMode && editorEmbedReturn) { ov.classList.add('is-hidden'); if (gcmHead) gcmHead.classList.remove('sr-only'); - if (mission && (mission.uiSkin === 'question_mission' || mission.uiSkin === 'stack_tower' || mission.uiSkin === 'mega_virus' || mission.uiSkin === 'jumper')) { + if (mission && (mission.uiSkin === 'question_mission' || mission.uiSkin === 'stack_tower' || mission.uiSkin === 'mega_virus' || mission.uiSkin === 'jumper' || mission.uiSkin === 'violent_crime')) { cancelQuizCarryResultEndAfterTimeup(); hideQuizCarryTimeupOnDeskLayer(); hideQuizCarryResultEndLayer(); @@ -10727,7 +10801,7 @@ function endSpaceShooterTimeUp() { if (spaceShooterGameEnded || !mapData || mapData.gameType !== 'space_shooter') return; if (isSpaceShooterMissionUiMapPlay()) { - endSpaceShooterMissionRound(); + endSpaceShooterMissionRound('time_up'); return; } spaceShooterGameEnded = true; @@ -10870,12 +10944,15 @@ spaceShooterSpawnAccMs += dt * 1000; while (spaceShooterSpawnAccMs >= interval) { spaceShooterSpawnAccMs -= interval; + const maxHp = 1 + Math.floor(Math.random() * SPACE_SHOOTER_ASTEROID_MAX_HP); + const hp0 = maxHp; spaceShooterAsteroids.push({ x: 36 + Math.random() * (mw - 72), y: -45 - Math.random() * 90, - r: 13 + Math.random() * 17, + r: spaceShooterAsteroidRadiusFromHpPlay(hp0), vy: 58 + Math.random() * 62, - hp: 1, + maxHp: maxHp, + hp: hp0, }); } @@ -10908,8 +10985,8 @@ } spaceShooterFireCd -= dt; - const fireHeld = !isChatFocused() && !!keys['Space']; - if (canPilotMe && fireHeld && spaceShooterFireCd <= 0 && me.spaceShooterCy != null) { + const autoFireOk = canPilotMe && !isChatFocused(); + if (autoFireOk && spaceShooterFireCd <= 0 && me.spaceShooterCy != null) { spaceShooterFireCd = 0.21; spaceShooterBullets.push({ x: me.spaceShooterCx, y: me.spaceShooterCy - 20, vy: -580, ownerId: myId }); } @@ -10940,7 +11017,8 @@ } if (hit >= 0) { const a = spaceShooterAsteroids[hit]; - a.hp = (a.hp || 1) - 1; + const mh = Math.max(1, Math.floor(Number(a.maxHp)) || SPACE_SHOOTER_ASTEROID_MAX_HP); + a.hp = Math.max(0, Math.floor(Number(a.hp) || mh) - 1); spaceShooterBullets.splice(bi, 1); const add = 5; if (b.ownerId === myId) { @@ -10956,6 +11034,8 @@ if (a.hp <= 0) { spaceShooterSpawnAsteroidExplosion(a.x, a.y, a.r); spaceShooterAsteroids.splice(hit, 1); + } else { + a.r = spaceShooterAsteroidRadiusFromHpPlay(a.hp); } } } diff --git a/www/html/Game/public/play.html b/www/html/Game/public/play.html index 751ce6e..3b1a178 100644 --- a/www/html/Game/public/play.html +++ b/www/html/Game/public/play.html @@ -3075,7 +3075,7 @@ - +
v —