"use strict"; // Layer: core/deterministic // Shared deterministic pseudo-random helpers used by behavior, item runtime, // and visual effects. Previously this bootstrap lived inline in several // modules; keeping it here prevents helper drift and load-order surprises. (function ensureDeterministicHelpers(global) { const clamp01 = v => Math.max(0, Math.min(1, Number(v) || 0)); const keyPart = value => { if (value == null) return "null"; if (typeof value === "number") return Number.isFinite(value) ? value.toFixed(3) : "nan"; if (typeof value === "string" || typeof value === "boolean") return String(value); if (typeof value === "object") { const id = value.familyKey || value.id || value.seed || value.liveToken || value.name; if (id) return `${value.type || value.constructor?.name || "entity"}:${id}`; const x = Number.isFinite(value.x) ? value.x.toFixed(1) : "x"; const y = Number.isFinite(value.y) ? value.y.toFixed(1) : "y"; return `${value.type || value.constructor?.name || "entity"}@${x},${y}`; } return String(value); }; const hashUnit = (seed, salt = "") => { const str = `${seed}:${salt}`; let h = 2166136261; for (let i = 0; i < str.length; i++) { h ^= str.charCodeAt(i); h = Math.imul(h, 16777619); } return ((h >>> 0) % 100000) / 100000; }; const deterministicFrame = (worldRef = null, hz = 60) => Math.floor((Number(worldRef?.time || 0) || 0) * Math.max(1, Number(hz) || 60) + 1e-6); const deterministicUnit = (worldRef = null, salt = "", ...parts) => hashUnit(String(worldRef?.worldSeed || "tarinai-world"), [salt, deterministicFrame(worldRef, 60), Number(worldRef?._deterministicEpoch || 0) || 0, ...parts.map(keyPart)].join("|")); const finiteOr = (value, fallback = 0) => { const n = Number(value); return Number.isFinite(n) ? n : fallback; }; const clampNumber = (value, min, max) => Math.max(min, Math.min(max, finiteOr(value, min))); const isPlainObject = value => Boolean(value && typeof value === "object" && !Array.isArray(value)); const clonePlain = (value, fallback = {}) => { if (value == null) return fallback; try { if (typeof structuredClone === "function") return structuredClone(value); } catch (_) {} return JSON.parse(JSON.stringify(value)); }; const birthHash32 = (seed = "") => { const match = /^b[0-9a-z]+_([0-9a-z]+)$/i.exec(String(seed || "")); if (match) { const parsed = parseInt(match[1], 36); if (Number.isFinite(parsed)) return parsed >>> 0; } let h = 2166136261; const value = String(seed || ""); for (let i = 0; i < value.length; i++) { h ^= value.charCodeAt(i); h = Math.imul(h, 16777619); } return h >>> 0; }; const isEffectCauseText = (text = "") => /\u306E\u52B9\u679C$/.test(String(text || "").trim().replace(/[\u3002\uFF01\uFF1F]+$/, "")); global.deterministicRange = global.deterministicRange || ((worldRef = null, salt = "", min = 0, max = 1, ...parts) => (Number(min) || 0) + deterministicUnit(worldRef, salt, ...parts) * ((Number(max) || 0) - (Number(min) || 0))); global.deterministicSigned = global.deterministicSigned || ((worldRef = null, salt = "", ...parts) => deterministicUnit(worldRef, salt, ...parts) < 0.5 ? -1 : 1); global.deterministicChance = global.deterministicChance || ((worldRef = null, salt = "", chance = 0, ...parts) => { const p = clamp01(chance); return p >= 1 || (p > 0 && deterministicUnit(worldRef, salt, ...parts) < p); }); global.deterministicAngle = global.deterministicAngle || ((worldRef = null, salt = "", ...parts) => global.deterministicRange(worldRef, salt, 0, Math.PI * 2, ...parts)); global.TarinaiCoreHelpers = Object.freeze({ ...(global.TarinaiCoreHelpers || {}), finiteOr, clampNumber, isPlainObject, clonePlain, birthHash32, isEffectCauseText, }); global.isTarinaiEffectCauseText = global.isTarinaiEffectCauseText || isEffectCauseText; })(typeof window !== "undefined" ? window : globalThis); // Keep the historical bare high-level helper names available to legacy scripts while the // implementation lives on globalThis. var deterministicRange = (typeof window !== "undefined" ? window : globalThis).deterministicRange; var deterministicSigned = (typeof window !== "undefined" ? window : globalThis).deterministicSigned; var deterministicChance = (typeof window !== "undefined" ? window : globalThis).deterministicChance; var deterministicAngle = (typeof window !== "undefined" ? window : globalThis).deterministicAngle;