tarinai/js/simulation_environment_system.js

73 lines
2.6 KiB
JavaScript
Raw Normal View History

2026-06-26 12:46:32 +09:00
"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;
2026-06-29 16:21:58 +09:00
return dt * worldRef.speed;
2026-06-26 12:46:32 +09:00
}
function updateClock(worldRef, dt) {
const previousDay = worldRef.day || 1;
2026-06-29 16:21:58 +09:00
worldRef.time += dt;
2026-06-26 12:46:32 +09:00
worldRef.day = Math.floor(worldRef.time / CONFIG.dayLength) + 1;
if (worldRef.day !== previousDay) {
for (const t of worldRef.tarinai || []) if (t) t.personalityDaily = { day: worldRef.day, total: 0, byKey: {}, byCause: {} };
}
}
function updateFrameSignals(worldRef, dt) {
if (worldRef.pointer) worldRef.pointer.motion = Math.max(0, (worldRef.pointer.motion || 0) - dt * 2.4);
2026-06-27 21:50:05 +09:00
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;
}
2026-06-26 12:46:32 +09:00
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.updateTerrainDirtyState?.(dt);
2026-06-28 13:40:41 +09:00
worldRef.evaluateColonyMood?.();
2026-06-26 12:46:32 +09:00
}
function prepareSpatialFrame(worldRef) {
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) {
worldRef.lastRuntimeDiagnostics = worldRef.runtimeDiagnostics?.() || null;
}
const phases = Object.freeze({
normalizeDelta,
updateClock,
updateFrameSignals,
updateEnvironment,
prepareSpatialFrame,
emitPhaseChange,
finalizeDiagnostics,
});
global.TarinaiEnvironmentSimulationSystem = Object.freeze({ phases });
})(typeof window !== "undefined" ? window : globalThis);