This commit is contained in:
33333-33333 2026-06-28 23:07:40 +09:00
commit 0e432c62ae
87 changed files with 4282 additions and 3066 deletions

View file

@ -1,33 +1,4 @@
"use strict";
(function ensureDeterministicHelpers(global) {
if (typeof global.deterministicChance === "function" && typeof global.deterministicRange === "function") return;
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;
};
global.deterministicFrame = global.deterministicFrame || ((worldRef = null, hz = 60) => Math.floor((Number(worldRef?.time || 0) || 0) * Math.max(1, Number(hz) || 60) + 1e-6));
global.deterministicUnit = global.deterministicUnit || ((worldRef = null, salt = "", ...parts) => hashUnit(String(worldRef?.worldSeed || "tarinai-world"), [salt, global.deterministicFrame(worldRef, 60), Number(worldRef?._deterministicEpoch || 0) || 0, ...parts.map(keyPart)].join("|")));
global.deterministicRange = global.deterministicRange || ((worldRef = null, salt = "", min = 0, max = 1, ...parts) => (Number(min) || 0) + global.deterministicUnit(worldRef, salt, ...parts) * ((Number(max) || 0) - (Number(min) || 0)));
global.deterministicSigned = global.deterministicSigned || ((worldRef = null, salt = "", ...parts) => global.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 && global.deterministicUnit(worldRef, salt, ...parts) < p); });
global.deterministicAngle = global.deterministicAngle || ((worldRef = null, salt = "", ...parts) => global.deterministicRange(worldRef, salt, 0, Math.PI * 2, ...parts));
})(typeof window !== "undefined" ? window : globalThis);
// Layer: entity-runtime/tarinai/update-step
@ -35,6 +6,24 @@
// pressure, and early freeze exits. This is extracted from the former
// Tarinai.prototype.update body without changing behavior.
(function (global) {
function detRange(worldRef, salt, min, max, ...parts) {
const fn = global.deterministicRange;
if (typeof fn === "function") return fn(worldRef, salt, min, max, ...parts);
const a = Number(min) || 0;
const b = Number(max) || 0;
return (a + b) * 0.5;
}
function detSigned(worldRef, salt, ...parts) {
const fn = global.deterministicSigned;
return typeof fn === "function" ? fn(worldRef, salt, ...parts) : 1;
}
function detChance(worldRef, salt, chance, ...parts) {
const fn = global.deterministicChance;
return typeof fn === "function" ? fn(worldRef, salt, chance, ...parts) : (Number(chance) || 0) >= 1;
}
function update(t, dt, context = {}) {
if (!t || t.dead) return { done: true };
t.prevX = t.x;
@ -106,7 +95,7 @@
t.defeatedTimer = Math.max(0, t.defeatedTimer - dt);
if (wasFighting && t.fightTimer <= 0.04 && t.defeatedById) {
const winner = t.world.liveTarinaiById?.(t.defeatedById) || null;
t.defeatedTimer = Math.max(t.defeatedTimer, deterministicRange(t.world, "defeated-recover-timer", 3.4, 5.2, t));
t.defeatedTimer = Math.max(t.defeatedTimer, detRange(t.world, "defeated-recover-timer", 3.4, 5.2, t));
t.fearTimer = Math.max(t.fearTimer, 1.0 * t.personalityProfile().fear);
t.hurtTimer = Math.max(t.hurtTimer, 1.8);
t.fallTimer = Math.max(t.fallTimer, 1.15);
@ -126,27 +115,27 @@
&& (t.fallTimer || 0) <= 0.04
&& !t.dead
&& !["sleep", "fight", "panic", "birth_ritual", "frozen"].includes(String(t.state || ""))
&& deterministicChance(t.world, "foot-massage-stumble", dt * 0.055, t)) {
const dir = deterministicSigned(t.world, "foot-massage-stumble-dir", t);
t.groundStumbleCooldown = deterministicRange(t.world, "foot-massage-stumble-cooldown", 8.5, 16.0, t);
t.fallTimer = Math.max(t.fallTimer || 0, deterministicRange(t.world, "foot-massage-stumble-fall", 0.86, 1.18, t));
&& detChance(t.world, "foot-massage-stumble", dt * 0.055, t)) {
const dir = detSigned(t.world, "foot-massage-stumble-dir", t);
t.groundStumbleCooldown = detRange(t.world, "foot-massage-stumble-cooldown", 8.5, 16.0, t);
t.fallTimer = Math.max(t.fallTimer || 0, detRange(t.world, "foot-massage-stumble-fall", 0.86, 1.18, t));
t.fallMax = Math.max(t.fallMax || 1.05, t.fallTimer);
t.fallDir = dir;
t.vx += dir * deterministicRange(t.world, "foot-massage-stumble-vx", 26, 52, t);
t.vy += deterministicRange(t.world, "foot-massage-stumble-vy", -18, 18, t);
t.vx += dir * detRange(t.world, "foot-massage-stumble-vx", 26, 52, t);
t.vy += detRange(t.world, "foot-massage-stumble-vy", -18, 18, t);
t.world?.spawnFallEffect?.(t.x, t.y + t.radius * 0.45);
t.setActionState?.("idle", { target: null, reason: "\u8db3\u3064\u307c\u306e\u7a81\u8d77\u306b\u3064\u307e\u3065\u3044\u305f\u3002", sleeping: false, clearTarget: false });
if ((t.world?.time || 0) >= (t.nextBubbleAt || 0)) t.bubble?.("\u3046\u3063", 1.6, "rgba(86,70,96,0.78)");
}
if (t.stress > 92 && t.state !== "sleep" && t.state !== "fight" && t.state !== "eat" && deterministicChance(t.world, "stress-breath-bubble", dt * 0.050, t)) {
if (t.stress > 92 && t.state !== "sleep" && t.state !== "fight" && t.state !== "eat" && detChance(t.world, "stress-breath-bubble", dt * 0.050, t)) {
t.bubble("\u306f\u3063...\u306f\u3063...", 3.4, "rgba(58,48,63,0.80)");
}
if (t.state === "idle" && t.stress < 78 && deterministicChance(t.world, "idle-bubble", dt * 0.018, t)) {
if (t.state === "idle" && t.stress < 78 && detChance(t.world, "idle-bubble", dt * 0.018, t)) {
t.bubble(pick(["\u306f\u3046", "\u306f\u3046\u3045", "\u306f\u3046\u3063", "\u306f\u3045"]), 4.2, "rgba(62,84,45,0.76)");
}
if (t.hurtTimer > 0 && deterministicChance(t.world, "hurt-bleed-effect", dt * 5.2, t)) {
if (t.hurtTimer > 0 && detChance(t.world, "hurt-bleed-effect", dt * 5.2, t)) {
const side = t.facingDir();
t.world.spawnBleedEffect(t.x - side * t.radius * deterministicRange(t.world, "hurt-bleed-x", 0.15, 0.42, t), t.y - t.radius * deterministicRange(t.world, "hurt-bleed-y", 0.08, 0.34, t));
t.world.spawnBleedEffect(t.x - side * t.radius * detRange(t.world, "hurt-bleed-x", 0.15, 0.42, t), t.y - t.radius * detRange(t.world, "hurt-bleed-y", 0.08, 0.34, t));
}
t.tempTimer += dt;