// ==================== ВОДА 3D — GrechkaCraft v3 ==================== // Та же логика 2D-игры (кислород, всплеск, болото), но с учётом Z. import { TILE } from '../core/constants.js'; import { state } from '../core/state.js'; import { getBlock } from '../world/world-storage3d.js'; import { playSound } from '../audio/sound-engine.js'; function blockAt3(px, py, pz) { const gx = Math.floor(px / TILE); const gy = Math.floor(py / TILE); const gz = Math.floor(pz / TILE); return getBlock(gx, gy, gz); } function isWaterAt(px, py, pz) { const b = blockAt3(px, py, pz); return !!(b && (b.t === 'water' || b.t === 'swamp_water')); } function isSwampWaterAt(px, py, pz) { const b = blockAt3(px, py, pz); return !!(b && b.t === 'swamp_water'); } // Обновляет флаги воды на сущности (игрок или моб). // dt передаётся явно — в 2D-версии он был неявной переменной цикла. export function updateWaterFlag3(e, dt) { const cx = e.x + e.w / 2; const cz = (e.z || 0) + (e.d || e.w) / 2; const wasInWater = e.inWater; const mid = isWaterAt(cx, e.y + e.h / 2, cz); const feet = isWaterAt(cx, e.y + e.h - 2, cz); e.inWater = mid || feet; e.inSwampWater = isSwampWaterAt(cx, e.y + e.h / 2, cz); e.headInWater = isWaterAt(cx, e.y + 4, cz); if (e === state.player && !wasInWater && e.inWater && e.vy > 100) { playSound('splash'); } if (e === state.player && e.inSwampWater) { state.player.hp -= 3 * (typeof dt === 'number' ? dt : 0.016); } } // Лодка тонет, если под ней нет воды (с учётом Z). export function updateWaterPhysics3(dt) { void dt; } export { isWaterAt, isSwampWaterAt };