2026-06-22 02:03:19 +09:00
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
(function (global) {
|
|
|
|
|
const STORAGE_KEY = "tarinai_frozen_storage_v1";
|
|
|
|
|
const MAX_PENDING_LOSSES = 16;
|
|
|
|
|
const Snapshot = global.TarinaiSnapshot;
|
|
|
|
|
if (!Snapshot) throw new Error("TarinaiSnapshot is not available for freeze_system.js");
|
|
|
|
|
const clonePlain = Snapshot.clonePlain;
|
|
|
|
|
|
|
|
|
|
const htmlEscape = global.TarinaiUIHelpers.htmlEscape;
|
|
|
|
|
|
|
|
|
|
function frozenList(worldRef = global.world) {
|
|
|
|
|
if (!worldRef) return [];
|
|
|
|
|
if (!Array.isArray(worldRef.frozenTarinai)) worldRef.frozenTarinai = [];
|
|
|
|
|
return worldRef.frozenTarinai;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function saveFrozenStore(worldRef = global.world) {
|
|
|
|
|
try {
|
|
|
|
|
global.localStorage?.setItem(STORAGE_KEY, JSON.stringify(frozenList(worldRef)));
|
|
|
|
|
} catch (_) {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function loadFrozenStore(worldRef = global.world) {
|
|
|
|
|
if (!worldRef) return [];
|
|
|
|
|
try {
|
|
|
|
|
const raw = global.localStorage?.getItem(STORAGE_KEY);
|
|
|
|
|
const parsed = raw ? JSON.parse(raw) : [];
|
|
|
|
|
if (Array.isArray(parsed) && !worldRef.frozenTarinai?.length) worldRef.frozenTarinai = clonePlain(parsed) || [];
|
|
|
|
|
} catch (_) {
|
|
|
|
|
if (!Array.isArray(worldRef.frozenTarinai)) worldRef.frozenTarinai = [];
|
|
|
|
|
}
|
|
|
|
|
return frozenList(worldRef);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function spritePathFor(type = "smile") {
|
|
|
|
|
const sprites = (typeof SPRITES !== "undefined" ? SPRITES : (global.SPRITES || []));
|
|
|
|
|
const meta = sprites.find(s => s.id === type) || sprites[0];
|
|
|
|
|
return meta?.path || "assets/sprites/tarinai_01_smile.webp";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ensureStyles() {
|
|
|
|
|
if (document.getElementById("freezeSystemStyles")) return;
|
|
|
|
|
const style = document.createElement("style");
|
|
|
|
|
style.id = "freezeSystemStyles";
|
|
|
|
|
style.textContent = `
|
2026-06-23 11:27:55 +09:00
|
|
|
.frozen-panel { margin-top: 10px; padding: 8px; border: 1px solid rgba(82, 63, 43, 0.18); border-radius: 14px; background: rgba(244, 249, 255, 0.72); }
|
|
|
|
|
.frozen-panel-title { display:flex; align-items:center; justify-content:space-between; gap:8px; width:100%; border:0; background:transparent; padding:0; font-weight:700; font-size:13px; color:#4f5f70; margin:0; cursor:pointer; text-align:left; }
|
|
|
|
|
.frozen-panel-title::before { content:"▸"; width:14px; color:rgba(79,95,112,.74); }
|
|
|
|
|
.frozen-panel:not(.collapsed) .frozen-panel-title::before { content:"▾"; }
|
|
|
|
|
.frozen-panel-body { margin-top:8px; }
|
|
|
|
|
.frozen-panel.collapsed .frozen-panel-body { display:none; }
|
2026-06-22 02:03:19 +09:00
|
|
|
.frozen-panel-count { font-size:12px; opacity:.72; }
|
|
|
|
|
.frozen-list { display:grid; grid-template-columns: 1fr; gap:7px; }
|
|
|
|
|
.frozen-card { display:flex; align-items:center; gap:8px; width:100%; border:1px solid rgba(72, 98, 124, .20); border-radius:12px; padding:7px; background:rgba(255,255,255,.78); cursor:grab; color:#354657; text-align:left; box-shadow: 0 2px 7px rgba(41,53,65,.06); }
|
|
|
|
|
.frozen-card:active { cursor:grabbing; }
|
|
|
|
|
.frozen-card.pending-thaw { outline:2px solid rgba(70, 142, 210, .46); background:rgba(227, 242, 255, .86); }
|
|
|
|
|
.frozen-card img { width:34px; height:34px; object-fit:contain; flex:none; filter: drop-shadow(0 2px 3px rgba(34,44,55,.14)); }
|
|
|
|
|
.frozen-card-main { min-width:0; flex:1; }
|
|
|
|
|
.frozen-card-name { display:block; font-weight:700; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
|
|
|
.frozen-card-meta { display:block; font-size:11px; opacity:.70; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
|
|
|
.frozen-empty { font-size:12px; color:rgba(58,70,82,.68); padding:4px 2px; }
|
|
|
|
|
canvas.freeze-drop-ready { outline: 3px solid rgba(70, 142, 210, .45); outline-offset: -3px; }
|
|
|
|
|
`;
|
|
|
|
|
document.head.appendChild(style);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ensurePanel() {
|
|
|
|
|
ensureStyles();
|
|
|
|
|
let panel = document.getElementById("frozenPanel");
|
2026-06-23 11:27:55 +09:00
|
|
|
if (panel) {
|
|
|
|
|
const operateBody = document.querySelector('[data-tool-category="operate"] .tool-category-body');
|
|
|
|
|
if (operateBody && panel.parentNode !== operateBody) operateBody.appendChild(panel);
|
|
|
|
|
return panel;
|
|
|
|
|
}
|
2026-06-22 02:03:19 +09:00
|
|
|
panel = document.createElement("section");
|
|
|
|
|
panel.id = "frozenPanel";
|
|
|
|
|
panel.className = "frozen-panel";
|
2026-06-23 11:27:55 +09:00
|
|
|
panel.classList.add("collapsed");
|
2026-06-22 02:03:19 +09:00
|
|
|
panel.innerHTML = `
|
2026-06-23 11:27:55 +09:00
|
|
|
<button class="frozen-panel-title" type="button" aria-expanded="false"><span>冷凍個体</span><span id="frozenPanelCount" class="frozen-panel-count">0</span></button>
|
|
|
|
|
<div class="frozen-panel-body"><div id="frozenList" class="frozen-list"></div></div>
|
2026-06-22 02:03:19 +09:00
|
|
|
`;
|
2026-06-23 11:27:55 +09:00
|
|
|
const operateBody = document.querySelector('[data-tool-category="operate"] .tool-category-body');
|
2026-06-22 02:03:19 +09:00
|
|
|
const anchor = global.ui?.toolPalette || document.getElementById("toolPalette");
|
2026-06-23 11:27:55 +09:00
|
|
|
if (operateBody) operateBody.appendChild(panel);
|
|
|
|
|
else if (anchor?.parentNode) anchor.parentNode.insertBefore(panel, anchor.nextSibling);
|
2026-06-22 02:03:19 +09:00
|
|
|
else document.body.appendChild(panel);
|
|
|
|
|
return panel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderFrozenPanel(worldRef = global.world) {
|
|
|
|
|
const panel = ensurePanel();
|
|
|
|
|
const listEl = panel.querySelector("#frozenList");
|
|
|
|
|
const countEl = panel.querySelector("#frozenPanelCount");
|
|
|
|
|
const list = frozenList(worldRef);
|
|
|
|
|
if (countEl) countEl.textContent = `${list.length}`;
|
|
|
|
|
if (!listEl) return;
|
|
|
|
|
if (!list.length) {
|
|
|
|
|
listEl.innerHTML = `<div class="frozen-empty">冷凍中のたりないはいません。</div>`;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
listEl.innerHTML = list.map(entry => {
|
|
|
|
|
const data = entry.data || entry;
|
|
|
|
|
const losses = Array.isArray(entry.pendingLosses) && entry.pendingLosses.length ? ` / 訃報${entry.pendingLosses.length}` : "";
|
|
|
|
|
const gen = data.generation ? `第${data.generation}世代` : "";
|
|
|
|
|
const id = htmlEscape(entry.freezeId || entry.id || data.familyKey || "");
|
|
|
|
|
return `<button class="frozen-card" type="button" draggable="true" data-frozen-id="${id}" title="ドラッグしてフィールドに戻す">
|
|
|
|
|
<img src="${htmlEscape(spritePathFor(data.type || "smile"))}" alt="">
|
|
|
|
|
<span class="frozen-card-main"><span class="frozen-card-name">${htmlEscape(data.name || "たりない")}</span><span class="frozen-card-meta">${htmlEscape(gen)}${htmlEscape(losses)}</span></span>
|
|
|
|
|
</button>`;
|
|
|
|
|
}).join("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function makeFrozenEntry(t, worldRef = global.world) {
|
|
|
|
|
const data = Snapshot.snapshotEntity(worldRef, t, new Set(["world", "target", "panicTarget", "targetRef"]));
|
|
|
|
|
data.sleeping = false;
|
|
|
|
|
data.insideNestBoxId = "";
|
|
|
|
|
data.state = data.state === "sleep" || data.state === "seek_bed" ? "idle" : (data.state || "idle");
|
|
|
|
|
data.targetKey = "";
|
|
|
|
|
const id = (global.crypto?.randomUUID ? global.crypto.randomUUID() : `frozen-${Date.now()}-${Math.random()}`);
|
|
|
|
|
return {
|
|
|
|
|
freezeId: id,
|
|
|
|
|
frozenAt: Date.now(),
|
|
|
|
|
worldTime: worldRef?.time || 0,
|
|
|
|
|
name: t.name || "たりない",
|
|
|
|
|
familyKey: t.familyKey || "",
|
|
|
|
|
liveId: t.id || "",
|
|
|
|
|
liveToken: t.liveToken || 0,
|
|
|
|
|
type: t.type || "smile",
|
|
|
|
|
data,
|
|
|
|
|
pendingLosses: [],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function findTarinaiAt(worldRef, x, y) {
|
|
|
|
|
const arr = worldRef?.tarinai || [];
|
|
|
|
|
for (let i = arr.length - 1; i >= 0; i--) {
|
|
|
|
|
const t = arr[i];
|
|
|
|
|
if (!t || t.dead) continue;
|
|
|
|
|
if (worldRef.isTarinaiHiddenInNestBox?.(t)) continue;
|
|
|
|
|
if (t.contains ? t.contains(x, y) : distXY(x, y, t.x, t.y) <= (t.radius || 22) * 1.35) return t;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function freezeTarinai(t, worldRef = global.world) {
|
|
|
|
|
if (!t || t.dead || !worldRef) return false;
|
|
|
|
|
const entry = makeFrozenEntry(t, worldRef);
|
|
|
|
|
worldRef.clearLiveReferencesTo?.(t);
|
|
|
|
|
if (t.id && worldRef.liveTarinai?.has?.(t.id)) worldRef.liveTarinai.delete(t.id);
|
|
|
|
|
worldRef.tarinai = (worldRef.tarinai || []).filter(o => o !== t);
|
|
|
|
|
if (worldRef.selected === t) worldRef.selected = null;
|
|
|
|
|
frozenList(worldRef).push(entry);
|
|
|
|
|
worldRef.drawListDirty = true;
|
|
|
|
|
worldRef.familyTreeDirty = true;
|
|
|
|
|
worldRef.updateItemCounts?.();
|
|
|
|
|
worldRef.rebuildSpatial?.(true);
|
|
|
|
|
saveFrozenStore(worldRef);
|
|
|
|
|
renderFrozenPanel(worldRef);
|
|
|
|
|
global.showToast?.(`${t.name}を冷凍保存しました。`);
|
|
|
|
|
worldRef.log?.(`${t.name}をフィールド外で冷凍保存した。`, "observe", { participants: [t] });
|
|
|
|
|
global.renderStats?.();
|
|
|
|
|
global.render?.();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateLiveIdAfterThaw(worldRef, t) {
|
|
|
|
|
if (!worldRef.liveTarinai) worldRef.liveTarinai = new Map();
|
|
|
|
|
const id = t.id || "";
|
|
|
|
|
const conflict = id && worldRef.liveTarinai.has(id);
|
|
|
|
|
if (!id || conflict) {
|
|
|
|
|
worldRef.assignTarinaiLiveId?.(t);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
worldRef.liveTarinai.set(id, { token: t.liveToken || 0, target: t });
|
|
|
|
|
const m = /^t(\d+)$/.exec(id);
|
|
|
|
|
if (m) worldRef.liveIdNext = Math.max(worldRef.liveIdNext || 1, Number(m[1]) + 1);
|
|
|
|
|
worldRef.liveIdSerial = Math.max(worldRef.liveIdSerial || 0, t.liveToken || 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function applyPendingLossesOnThaw(t, entry, worldRef) {
|
|
|
|
|
const losses = Array.isArray(entry.pendingLosses) ? entry.pendingLosses : [];
|
|
|
|
|
if (!losses.length) return;
|
|
|
|
|
const unique = [];
|
|
|
|
|
const seen = new Set();
|
|
|
|
|
for (const loss of losses) {
|
|
|
|
|
const key = loss.familyKey || loss.liveId || loss.name || JSON.stringify(loss);
|
|
|
|
|
if (seen.has(key)) continue;
|
|
|
|
|
seen.add(key);
|
|
|
|
|
unique.push(loss);
|
|
|
|
|
}
|
|
|
|
|
const relPriority = unique.some(l => l.relation === "親" || l.relation === "子") ? 1 : 0;
|
|
|
|
|
const stress = Math.min(36, 10 + unique.length * 6 + relPriority * 8);
|
|
|
|
|
if (t.enterPanic) t.enterPanic({ reason: `${unique[0]?.name || "誰か"}がいないことに気づいた`, fear: 2.4 + Math.min(2.0, unique.length * 0.35), stress, cause: "pending_relation_death" });
|
|
|
|
|
else {
|
|
|
|
|
t.stress = clamp((t.stress || 0) + stress, 0, 130);
|
|
|
|
|
t.fearTimer = Math.max(t.fearTimer || 0, 2.4 + Math.min(2.0, unique.length * 0.35));
|
|
|
|
|
t.setActionState?.("panic", { target: t.panicDestination ? t.panicDestination() : null, reason: `${unique[0]?.name || "誰か"}がいないことに気づいた`, wake: true });
|
|
|
|
|
}
|
|
|
|
|
t.bubble?.("いない", 1.1, "rgba(60,50,68,0.82)");
|
|
|
|
|
t.recordChangeCause?.("冷凍中の訃報", "ストレス", { value: stress });
|
|
|
|
|
t.addRecord?.(`冷凍中に${unique.map(l => l.name || "誰か").slice(0, 3).join("、")}が死亡していたことに気づいた。`, "death");
|
|
|
|
|
worldRef.log?.(`${t.name}は解凍時に身近な個体の死に気づき、パニックになった。`, "death", { participants: [t] });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function thawFrozen(freezeId, x, y, worldRef = global.world) {
|
|
|
|
|
const list = frozenList(worldRef);
|
|
|
|
|
const index = list.findIndex(e => (e.freezeId || e.id) === freezeId);
|
|
|
|
|
if (index < 0 || !worldRef) return false;
|
|
|
|
|
const entry = list[index];
|
|
|
|
|
const data = clonePlain(entry.data || entry) || {};
|
|
|
|
|
let t = null;
|
|
|
|
|
try {
|
|
|
|
|
t = Snapshot.restoreTarinaiData(worldRef, data, { clearTransient: true });
|
|
|
|
|
} catch (_) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
t.dead = false;
|
|
|
|
|
t.deathReason = "";
|
|
|
|
|
t.x = clamp(Number(x) || worldRef.w / 2, CONFIG.worldPadding, worldRef.w - CONFIG.worldPadding);
|
|
|
|
|
t.y = clamp(Number(y) || worldRef.h / 2, CONFIG.worldPadding, worldRef.h - CONFIG.worldPadding);
|
|
|
|
|
t.vx = 0;
|
|
|
|
|
t.vy = 0;
|
|
|
|
|
t.target = null;
|
|
|
|
|
t.panicTarget = null;
|
|
|
|
|
t.insideNestBoxId = "";
|
|
|
|
|
t.sleeping = false;
|
|
|
|
|
if (t.state === "sleep" || t.state === "seek_bed") t.goIdle?.("解凍されて少し驚いている");
|
|
|
|
|
t.surpriseTimer = Math.max(t.surpriseTimer || 0, 0.35);
|
|
|
|
|
t.thought = "解凍されて少し驚いている";
|
|
|
|
|
t.frozenAt = 0;
|
|
|
|
|
updateLiveIdAfterThaw(worldRef, t);
|
|
|
|
|
if (typeof t.refreshEffectiveSize === "function") t.refreshEffectiveSize();
|
|
|
|
|
worldRef.tarinai.push(t);
|
|
|
|
|
worldRef.recordFamily?.(t);
|
|
|
|
|
applyPendingLossesOnThaw(t, entry, worldRef);
|
|
|
|
|
list.splice(index, 1);
|
|
|
|
|
worldRef.selected = t;
|
|
|
|
|
worldRef.drawListDirty = true;
|
|
|
|
|
worldRef.familyTreeDirty = true;
|
|
|
|
|
worldRef.updateItemCounts?.();
|
|
|
|
|
worldRef.rebuildSpatial?.(true);
|
|
|
|
|
saveFrozenStore(worldRef);
|
|
|
|
|
renderFrozenPanel(worldRef);
|
|
|
|
|
global.showToast?.(`${t.name}を解凍しました。`);
|
|
|
|
|
worldRef.log?.(`${t.name}を解凍してフィールドに戻した。`, "birth", { participants: [t] });
|
|
|
|
|
global.renderStats?.();
|
|
|
|
|
global.render?.();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function bindFreezeSystem() {
|
|
|
|
|
const worldRef = global.world;
|
|
|
|
|
loadFrozenStore(worldRef);
|
|
|
|
|
renderFrozenPanel(worldRef);
|
|
|
|
|
const panel = ensurePanel();
|
|
|
|
|
if (panel.dataset.freezeBound !== "1") {
|
|
|
|
|
panel.dataset.freezeBound = "1";
|
2026-06-23 11:27:55 +09:00
|
|
|
panel.addEventListener("click", (e) => {
|
|
|
|
|
const title = e.target.closest(".frozen-panel-title");
|
|
|
|
|
if (!title) return;
|
|
|
|
|
const collapsed = !panel.classList.toggle("collapsed");
|
|
|
|
|
title.setAttribute("aria-expanded", collapsed ? "true" : "false");
|
|
|
|
|
});
|
2026-06-22 02:03:19 +09:00
|
|
|
panel.addEventListener("dragstart", (e) => {
|
|
|
|
|
const card = e.target.closest(".frozen-card[data-frozen-id]");
|
|
|
|
|
if (!card) return;
|
|
|
|
|
const id = card.dataset.frozenId || "";
|
|
|
|
|
e.dataTransfer?.setData("text/plain", `tarinai-frozen:${id}`);
|
|
|
|
|
e.dataTransfer?.setData("application/x-tarinai-frozen", id);
|
|
|
|
|
e.dataTransfer.effectAllowed = "move";
|
|
|
|
|
global.document?.querySelector("canvas")?.classList.add("freeze-drop-ready");
|
|
|
|
|
});
|
|
|
|
|
panel.addEventListener("dragend", () => global.document?.querySelector("canvas")?.classList.remove("freeze-drop-ready"));
|
|
|
|
|
panel.addEventListener("click", (e) => {
|
|
|
|
|
const card = e.target.closest(".frozen-card[data-frozen-id]");
|
|
|
|
|
if (!card) return;
|
|
|
|
|
pendingThawId = card.dataset.frozenId || "";
|
|
|
|
|
for (const c of panel.querySelectorAll(".frozen-card")) c.classList.toggle("pending-thaw", c === card);
|
|
|
|
|
global.showToast?.("フィールドをクリックすると解凍します。ドラッグ&ドロップでも配置できます。");
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
const canvas = global.canvas || document.getElementById("gameCanvas");
|
|
|
|
|
if (canvas && canvas.dataset.freezeDropBound !== "1") {
|
|
|
|
|
canvas.dataset.freezeDropBound = "1";
|
|
|
|
|
canvas.addEventListener("dragover", (e) => {
|
|
|
|
|
const text = e.dataTransfer?.types?.includes?.("application/x-tarinai-frozen") || [...(e.dataTransfer?.types || [])].includes("text/plain");
|
|
|
|
|
if (!text) return;
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
e.dataTransfer.dropEffect = "move";
|
|
|
|
|
canvas.classList.add("freeze-drop-ready");
|
|
|
|
|
});
|
|
|
|
|
canvas.addEventListener("dragleave", () => canvas.classList.remove("freeze-drop-ready"));
|
|
|
|
|
canvas.addEventListener("drop", (e) => {
|
|
|
|
|
const id = e.dataTransfer?.getData("application/x-tarinai-frozen") || String(e.dataTransfer?.getData("text/plain") || "").replace(/^tarinai-frozen:/, "");
|
|
|
|
|
if (!id) return;
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
canvas.classList.remove("freeze-drop-ready");
|
|
|
|
|
const p = typeof global.screenToWorld === "function" ? global.screenToWorld(e) : (() => {
|
|
|
|
|
const rect = canvas.getBoundingClientRect();
|
|
|
|
|
const sx = e.clientX - rect.left;
|
|
|
|
|
const sy = e.clientY - rect.top;
|
|
|
|
|
return worldRef.screenToWorld ? worldRef.screenToWorld(sx, sy) : { x: sx, y: sy, inside: true };
|
|
|
|
|
})();
|
|
|
|
|
thawFrozen(id, p.x, p.y, worldRef);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let pendingThawId = "";
|
|
|
|
|
|
|
|
|
|
function tryPendingThawAt(x, y, worldRef = global.world) {
|
|
|
|
|
if (!pendingThawId) return false;
|
|
|
|
|
const id = pendingThawId;
|
|
|
|
|
pendingThawId = "";
|
|
|
|
|
document.querySelectorAll(".frozen-card.pending-thaw").forEach(el => el.classList.remove("pending-thaw"));
|
|
|
|
|
return thawFrozen(id, x, y, worldRef);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function afterSnapshotRestored(worldRef = global.world) {
|
|
|
|
|
if (!Array.isArray(worldRef?.frozenTarinai)) worldRef.frozenTarinai = [];
|
|
|
|
|
saveFrozenStore(worldRef);
|
|
|
|
|
renderFrozenPanel(worldRef);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function patchWorldPrototype() {
|
|
|
|
|
const apply = (proto) => {
|
|
|
|
|
const originalHandleClick = proto.handleClick;
|
|
|
|
|
proto.handleClick = function (x, y) {
|
|
|
|
|
if (tryPendingThawAt(x, y, this)) return;
|
|
|
|
|
if (this.tool === "freeze") {
|
|
|
|
|
global.showToast?.("冷凍は『つまむ』でたりないを冷凍個体UIへ運んでください。");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
return originalHandleClick.call(this, x, y);
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
if (global.TarinaiPatcher?.patchWorld?.("freezeSystem", apply)) return;
|
|
|
|
|
const World = global.World;
|
|
|
|
|
if (!World || World.prototype.__freezeSystemPatched) return;
|
|
|
|
|
World.prototype.__freezeSystemPatched = true;
|
|
|
|
|
apply(World.prototype);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
patchWorldPrototype();
|
|
|
|
|
|
|
|
|
|
global.TarinaiFreezeSystem = {
|
|
|
|
|
bindFreezeSystem,
|
|
|
|
|
renderFrozenPanel,
|
|
|
|
|
freezeTarinai,
|
|
|
|
|
thawFrozen,
|
|
|
|
|
frozenList,
|
|
|
|
|
loadFrozenStore,
|
|
|
|
|
saveFrozenStore,
|
|
|
|
|
afterSnapshotRestored,
|
|
|
|
|
};
|
|
|
|
|
})(typeof window !== "undefined" ? window : globalThis);
|