"use strict"; // Layer: simulation/system-effects // Owns frame updates for transient visual/effect entities. (function (global) { function updateEffect(effect, dt, frameId = 0) { if (!effect || effect.dead) return false; const runDt = Math.min(0.24, Math.max(0, Number(effect._effectUpdateAccum || 0) + dt)); effect._effectUpdateAccum = 0; effect._effectUpdatedFrame = frameId; effect.update(runDt); return true; } function updateEffects(worldRef, dt) { const effects = worldRef.effects || []; const total = effects.length; const frameId = (worldRef._effectUpdateFrameId || 0) + 1; worldRef._effectUpdateFrameId = frameId; if (total <= 56) { for (const ef of effects) updateEffect(ef, dt, frameId); worldRef._effectUpdateStats = { total, updated: total, skipped: 0, batched: false }; return; } const budget = Math.max(40, Math.ceil(total * 0.42)); let cursor = Math.max(0, Math.floor(worldRef._effectUpdateCursor || 0)) % total; let updated = 0; let scanned = 0; while (updated < budget && scanned < total) { const ef = effects[cursor]; cursor = (cursor + 1) % total; scanned += 1; if (!ef || ef.dead) continue; updateEffect(ef, dt, frameId); updated += 1; } for (let i = 0; i < total; i += 1) { const ef = effects[i]; if (!ef || ef.dead || ef._effectUpdatedFrame === frameId) continue; if (Number.isFinite(ef._effectUpdateAccum)) ef._effectUpdateAccum = Math.min(0.24, ef._effectUpdateAccum + dt); else ef._effectUpdateAccum = dt; } worldRef._effectUpdateCursor = cursor; worldRef._effectUpdateStats = { total, updated, skipped: Math.max(0, total - updated), batched: true }; } global.TarinaiEffectsSimulationSystem = Object.freeze({ phases: Object.freeze({ updateEffects }), }); })(typeof window !== "undefined" ? window : globalThis);