86 lines
4.5 KiB
JavaScript
86 lines
4.5 KiB
JavaScript
"use strict";
|
|
|
|
(function (global) {
|
|
const MAX_PENDING_LOSSES = 16;
|
|
|
|
|
|
function relationWithDead(observer, dead, worldRef) {
|
|
if (!observer || !dead || observer === dead) return "";
|
|
const deadFamily = worldRef?.tarinaiFamilyKey ? worldRef.tarinaiFamilyKey(dead) : (dead.familyKey || "");
|
|
const observerFamily = observer.familyKey || observer.archiveKey || observer.id || "";
|
|
const deadId = dead.id || dead.releasedLiveId || "";
|
|
const observerId = observer.id || observer.liveId || "";
|
|
if (deadFamily && (observer.parents || []).includes(deadFamily)) return "親";
|
|
if (deadFamily && (observer.children || []).includes(deadFamily)) return "子";
|
|
if (observerFamily && (dead.parents || []).includes(observerFamily)) return "子";
|
|
if (observerFamily && (dead.children || []).includes(observerFamily)) return "親";
|
|
const rel = deadId ? observer.relationships?.[deadId] : null;
|
|
const reverse = observerId ? dead.relationships?.[observerId] : null;
|
|
if ((rel?.affinity || 0) >= (global.FRIEND_AFFINITY_THRESHOLD || 14) || (reverse?.affinity || 0) >= (global.FRIEND_AFFINITY_THRESHOLD || 14)) return "友達";
|
|
return "";
|
|
}
|
|
|
|
function applyLiveDeathShock(observer, dead, relation, worldRef) {
|
|
const strong = relation === "親" || relation === "子";
|
|
if (observer.state === "sleep" || observer.state === "seek_bed") observer.goIdle?.("身近な個体の死に気づいた");
|
|
const stress = strong ? 18 : 11;
|
|
const fear = strong ? 2.1 : 1.45;
|
|
if (observer.enterPanic) observer.enterPanic({ threat: dead, reason: `${relation}が死んだ`, fear, stress, cause: "relation_death", bubble: "!!", bubbleColor: "rgba(60,50,68,0.82)" });
|
|
else {
|
|
observer.sleeping = false;
|
|
observer.setActionState?.("panic", { target: observer.panicDestination ? observer.panicDestination(dead) : null, reason: `${relation}が死んだ`, wake: true });
|
|
observer.fearTimer = Math.max(observer.fearTimer || 0, fear);
|
|
if (typeof applyNeedShock === "function") applyNeedShock(observer, { safety: stress * 1.6, social: stress * 1.4 });
|
|
observer.bubble?.("!!", 1.0, "rgba(60,50,68,0.82)");
|
|
}
|
|
observer.recordChangeCause?.(`${relation}の死亡`, "ストレス", { value: stress });
|
|
observer.addRecord?.(`${dead.name || "身近な個体"}の死に気づいてパニックになった。`, "death");
|
|
}
|
|
|
|
function notifyDeathToRelations(dead, reason = "") {
|
|
const worldRef = this || global.world;
|
|
if (!worldRef || !dead) return;
|
|
const deadFamily = worldRef.tarinaiFamilyKey ? worldRef.tarinaiFamilyKey(dead) : (dead.familyKey || "");
|
|
const deadId = dead.id || dead.releasedLiveId || "";
|
|
let liveHits = 0;
|
|
for (const other of worldRef.tarinai || []) {
|
|
if (!other || other === dead || other.dead) continue;
|
|
const relation = relationWithDead(other, dead, worldRef);
|
|
if (!relation) continue;
|
|
applyLiveDeathShock(other, dead, relation, worldRef);
|
|
liveHits += 1;
|
|
}
|
|
for (const entry of (global.TarinaiFreezeSystem?.frozenList?.(worldRef) || [])) {
|
|
const data = entry.data || entry;
|
|
const relation = relationWithDead(data, dead, worldRef);
|
|
if (!relation) continue;
|
|
if (!Array.isArray(entry.pendingLosses)) entry.pendingLosses = [];
|
|
const duplicate = entry.pendingLosses.some(l => (deadFamily && l.familyKey === deadFamily) || (deadId && l.liveId === deadId));
|
|
if (!duplicate) {
|
|
entry.pendingLosses.unshift({
|
|
relation,
|
|
name: dead.name || "たりない",
|
|
familyKey: deadFamily,
|
|
liveId: deadId,
|
|
reason: reason || dead.deathReason || "死亡",
|
|
time: worldRef.time || 0,
|
|
});
|
|
if (entry.pendingLosses.length > MAX_PENDING_LOSSES) entry.pendingLosses.length = MAX_PENDING_LOSSES;
|
|
}
|
|
}
|
|
if (liveHits) worldRef.log?.(`${dead.name || "たりない"}の死に、身近な個体が動揺した。`, "death", { participants: [dead] });
|
|
global.TarinaiFreezeSystem?.saveFrozenStore?.(worldRef);
|
|
global.TarinaiFreezeSystem?.renderFrozenPanel?.(worldRef);
|
|
}
|
|
|
|
function patchWorldPrototype() {
|
|
const apply = (proto) => { proto.notifyDeathToRelations = notifyDeathToRelations; };
|
|
if (global.TarinaiPatcher?.patchWorld?.("relationEvents", apply)) return;
|
|
const World = global.World;
|
|
if (!World) return;
|
|
apply(World.prototype);
|
|
}
|
|
|
|
global.TarinaiRelationEvents = { relationWithDead, applyLiveDeathShock, notifyDeathToRelations, patchWorldPrototype };
|
|
patchWorldPrototype();
|
|
})(typeof window !== "undefined" ? window : globalThis);
|