Game: Tower stack — raise swing/rope anchor after layer 9+ (mnn93hpi)

getStackTowerSwingLiftWorldPx tiers from layer 9; used in fall anim + draw.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-03 05:07:00 +00:00
parent 4a9755a4dc
commit afc8d3b995
2 changed files with 26 additions and 10 deletions
+25 -9
View File
@@ -29,6 +29,8 @@
const QUIZ_QUESTION_MISSION_MAP_ID = 'mng8a80o';
/** Stack ซ้อนตึก — ฉากภารกิจ (HOWTO → นับถอยหลัง → เล่น → สรุป) รูปใน `/Game/img/TowerBlock` */
const STACK_TOWER_MISSION_MAP_ID = 'mnn93hpi';
/** ครบชั้นนี้ขึ้นไป — ยกจุดแกว่ง/เชือกขึ้น (world px) ป้องกันชนกองสูง (เฉพาะ Tower mission) */
const STACK_TOWER_SWING_LIFT_FROM_LAYER = 9;
/** Violent Crime mission: asteroid strikes ship → invuln → 3 strikes = eliminated */
const SPACE_SHOOTER_MISSION_MAX_ASTEROID_HITS = 3;
const SPACE_SHOOTER_MISSION_HIT_INVULN_MS = 1400;
@@ -6553,6 +6555,16 @@
return { enabled: raw.enabled !== false, pxPerLayer, maxPx };
}
/** ยกจุดยึดเชือกขึ้นเมื่อหอสูง (y ลดลง = สูงขึ้นในโลก) — เฉพาะ mnn93hpi */
function getStackTowerSwingLiftWorldPx(layerCount, layerWorldHPx) {
if (!isStackTowerMissionUiMapPlay()) return 0;
const n = Math.floor(Number(layerCount) || 0);
if (n < STACK_TOWER_SWING_LIFT_FROM_LAYER) return 0;
const lh = Math.max(10, Number(layerWorldHPx) || Math.max(14, (tileSize || 32) * 0.3));
const tiers = n - (STACK_TOWER_SWING_LIFT_FROM_LAYER - 1);
return Math.min(lh * 20, tiers * lh * 0.98);
}
/** world px ตามความสูงหอ (mnn93hpi) — ใช้เลื่อนกล้องให้บล็อก/ฉากไปกับมุมมอง */
function getStackTowerBgScrollHeightBoostPx() {
if (!isStackTowerMissionUiMapPlay() || !stackMini) return 0;
@@ -6863,29 +6875,31 @@
const tw = m.widthTiles * tileSize;
const swingXW = (m.topCenterX + m.swingAmp * Math.sin(m.phase)) * tileSize;
const lh = m.layerWorldH || Math.max(14, tileSize * 0.3);
const swingLift = getStackTowerSwingLiftWorldPx(m.layers.length, lh);
const swingAttachY = m.swingWorldY - swingLift;
let y1 = m.floorWorldY - (m.layers.length + 1) * lh;
if (y1 <= m.swingWorldY) y1 = m.swingWorldY + lh * 0.55;
if (y1 <= swingAttachY) y1 = swingAttachY + lh * 0.55;
const landOff = hit.landOffsetTiles || 0;
const landCxWorld = (m.topCenterX + landOff) * tileSize;
const xLeft0 = swingXW - tw / 2;
const xLeft1 = landCxWorld - tw / 2;
const offN = Math.min(1, Math.abs(landOff) / Math.max(0.01, m.swingAmp));
const dur = Math.max(400, Math.min(1280, 240 + (y1 - m.swingWorldY) * 0.92 + offN * 560));
const dur = Math.max(400, Math.min(1280, 240 + (y1 - swingAttachY) * 0.92 + offN * 560));
const tiltMax = hit.miss
? 0.28 * (0.25 + offN)
: 0.16 * offN * (hit.perfect ? 0.1 : 1);
const isHumanPreview = !!(previewActor && previewActor.human);
const botIdPreview = previewActor && previewActor.botId ? previewActor.botId : null;
const cableTopYRel = Math.max(0, m.swingWorldY - tileSize * 6);
const cableTopYRel = Math.max(0, swingAttachY - tileSize * 6);
const craneXRel = m.craneWorldX != null ? m.craneWorldX : m.topCenterX * tileSize;
const releaseRopeAng = Math.atan2(m.swingWorldY - cableTopYRel, swingXW - craneXRel);
const releaseRopeAng = Math.atan2(swingAttachY - cableTopYRel, swingXW - craneXRel);
stackFall = {
t0: performance.now(),
dur,
xLeft0,
xLeft1,
tw,
y0: m.swingWorldY,
y0: swingAttachY,
y1,
hit,
tiltMax,
@@ -6894,7 +6908,7 @@
previewBotId: botIdPreview,
releaseRopeAng,
releaseAttachWorldX: swingXW,
releaseAttachWorldY: m.swingWorldY,
releaseAttachWorldY: swingAttachY,
};
return true;
}
@@ -7060,7 +7074,9 @@
const layerWorldH = m.layerWorldH || Math.max(14, tileSize * 0.3);
const stripH = m.blockStripH || Math.max(16, tileSize * 0.32);
const floorY = m.floorWorldY;
const guideTopY = Math.max(0, m.swingWorldY - tileSize * 6.5);
const swingLiftDraw = getStackTowerSwingLiftWorldPx(m.layers.length, layerWorldH);
const swingDrawY = m.swingWorldY - swingLiftDraw;
const guideTopY = Math.max(0, swingDrawY - tileSize * 6.5);
const [gtx, gty] = worldToScreen(m.topCenterX * tileSize, guideTopY);
const [gbx, gby] = worldToScreen(m.topCenterX * tileSize, floorY);
ctx.strokeStyle = 'rgba(255,255,255,0.22)';
@@ -7116,7 +7132,7 @@
} else {
const twWorld = m.widthTiles * tileSize;
const drawStripPx = stripH * zoom;
const cableTopY = Math.max(0, m.swingWorldY - tileSize * 6);
const cableTopY = Math.max(0, swingDrawY - tileSize * 6);
const craneX = m.craneWorldX != null ? m.craneWorldX : m.topCenterX * tileSize;
let blockLeftWorld;
let blockTopWorld;
@@ -7131,7 +7147,7 @@
} else {
const swingXW = (m.topCenterX + m.swingAmp * Math.sin(m.phase)) * tileSize;
blockLeftWorld = swingXW - twWorld / 2;
blockTopWorld = m.swingWorldY;
blockTopWorld = swingDrawY;
}
const cxMid = blockLeftWorld + twWorld / 2;
const [tcx, tcy] = worldToScreen(craneX, cableTopY);
+1 -1
View File
@@ -2009,7 +2009,7 @@
</div>
<script src="/Game/socket.io/socket.io.js"></script>
<script src="js/version.js?v=0.0184"></script>
<script src="js/play.js?v=0.270"></script>
<script src="js/play.js?v=0.271"></script>
<div class="version-tag">v —</div>
</body>
</html>