"use strict"; // Layer: simulation/system-environment // Owns frame time, world clock, frame signals, weather/terrain preparation, // phase-change notification, and diagnostics publication. (function (global) { function normalizeDelta(worldRef, dt) { if (!worldRef || worldRef.paused) return null; return dt * worldRef.speed; } function updateClock(worldRef, dt) { const previousDay = worldRef.day || 1; worldRef.time += dt; worldRef.elapsedDays = Math.max(0, Math.floor(worldRef.time / CONFIG.dayLength)); worldRef.day = worldRef.elapsedDays + 1; if (worldRef.day !== previousDay) { for (const t of worldRef.tarinai || []) if (t) t.personalityDaily = { day: worldRef.day, total: 0, byKey: {}, byCause: {} }; global.TarinaiAchievements?.evaluateEvent?.(worldRef, "season", { previousDay, day: worldRef.day }); } } function updateFrameSignals(worldRef, dt) { if (worldRef.pointer) worldRef.pointer.motion = Math.max(0, (worldRef.pointer.motion || 0) - dt * 2.4); const recoilX = Number(worldRef.shootCursorOffsetX) || 0; const recoilY = Number(worldRef.shootCursorOffsetY) || 0; if (recoilX || recoilY) { // Recoil is a real aim offset, but it should settle back to the actual // mouse/touch position in roughly 1-2 seconds instead of drifting forever. const k = Math.exp(-Math.max(0, Number(dt) || 0) * 3.15); worldRef.shootCursorOffsetX = Math.abs(recoilX * k) < 0.25 ? 0 : recoilX * k; worldRef.shootCursorOffsetY = Math.abs(recoilY * k) < 0.25 ? 0 : recoilY * k; worldRef.drawListDirty = true; } worldRef.shakeTimer = Math.max(0, (worldRef.shakeTimer || 0) - dt); if ((worldRef.shakeTimer || 0) <= 0) { worldRef.shakeDuration = 0; worldRef.shakeStrength = 0; } } function updateEnvironment(worldRef, dt) { worldRef.updateWeather(dt); worldRef.updateTemperature?.(dt); worldRef.updateTerrainDirtyState?.(dt); const now = worldRef.time || 0; if (now >= (worldRef.nextColonyMoodEvalAt || 0)) worldRef.evaluateColonyMood?.(); } function prepareSpatialFrame(worldRef) { if (global.TarinaiPerf?.diagnosticsEnabled?.() === true) { worldRef.spatialRebuildsThisFrame = 0; worldRef.spatialDirtyMarksThisFrame = 0; } worldRef.ensureSpatial?.("update-start"); worldRef.beginFramePerformanceBudgets?.(); } function emitPhaseChange(worldRef) { const phase = worldRef.phaseName(); if (phase !== worldRef.lastPhase) { worldRef.lastPhase = phase; worldRef.emit("world:phase", { world: worldRef, phase }); } } function finalizeDiagnostics(worldRef) { if (!worldRef) return; const wantsDiagnostics = Boolean(global.__tarinaiDebugOverlayEnabled || global.__tarinaiForceRuntimeDiagnostics); worldRef.lastRuntimeDiagnostics = wantsDiagnostics ? (worldRef.runtimeDiagnostics?.() || null) : null; } const phases = Object.freeze({ normalizeDelta, updateClock, updateFrameSignals, updateEnvironment, prepareSpatialFrame, emitPhaseChange, finalizeDiagnostics, }); global.TarinaiEnvironmentSimulationSystem = Object.freeze({ phases }); })(typeof window !== "undefined" ? window : globalThis);