"use strict"; // Item effect behavior, timers, and display metadata. (function (global) { const rawDefinitions = { laxative: { label: "\u4e0b\u5264", color: "rgba(119, 136, 58, 0.78)", kind: "timed", defaultDuration: 60, tags: ["item", "behavior", "food"], display: timer => `${Math.ceil(timer || 0)}\u79d2 / 3\u79d2\u3054\u3068\u306b\u305a\u3093\u3061 / \u98df\u4e8b\u306e\u7a7a\u8179\u56de\u5fa9\u306a\u3057`, }, ammo: { label: "\u5f3e\u85ac", color: "rgba(216, 142, 38, 0.82)", kind: "timed", defaultDuration: 18, tags: ["item", "behavior", "movement"], display: timer => `${Math.ceil(timer || 0)}\u79d2 / \u6b69\u884c\u901f\u5ea610\u500d / \u885d\u7a81\u3067\u5f3e\u304d\u98db\u3070\u3059`, }, protein: { label: "\u30d7\u30ed\u30c6\u30a4\u30f3", color: "rgba(239, 122, 51, 0.86)", kind: "permanent", exclusiveGroup: "power", tags: ["item", "behavior", "power"], display: () => "\u6c38\u7d9a / \u4e0e\u30c0\u30e1\u30fc\u30b81.75\u500d / \u75c5\u6c17\u78ba\u73870.5\u500d", }, niteropu: { label: "\u30f3\u30a4\u30c6\u30ed\u30d7", color: "rgba(88, 76, 166, 0.78)", kind: "permanent", exclusiveGroup: "power", tags: ["item", "behavior", "power"], display: () => "\u6c38\u7d9a / \u4e0e\u30c0\u30e1\u30fc\u30b80.5\u500d / \u75c5\u6c17\u78ba\u73872\u500d", }, mercury: { label: "\u6c34\u9280", color: "rgba(96, 146, 166, 0.82)", kind: "permanent", tags: ["item", "life"], display: (_timer, t) => `\u6c38\u7d9a / \u5bff\u547dx${((t && t.mercuryLifeMultiplier) || 1.3).toFixed(2)}\uff08\u98df\u3079\u308b\u305f\u3073\u4e57\u7b97\uff09`, }, giant_drug: { label: "\u5de8\u5927\u85ac", color: "rgba(228, 123, 58, 0.86)", kind: "permanent", exclusiveGroup: "body_size", tags: ["item", "body", "behavior"], display: () => "\u6c38\u7d9a / \u30b5\u30a4\u30ba3\u500d / \u653b\u64832\u500d / \u901f\u5ea61.5\u500d / \u6bce\u79d21\u30c0\u30e1\u30fc\u30b8", }, dwarf_drug: { label: "\u77ee\u5c0f\u85ac", color: "rgba(109, 107, 190, 0.82)", kind: "permanent", exclusiveGroup: "body_size", tags: ["item", "body", "behavior"], display: () => "\u6c38\u7d9a / \u30b5\u30a4\u30ba0.25\u500d / \u653b\u64830.25\u500d / \u901f\u5ea60.5\u500d / \u6bce\u79d21\u30c0\u30e1\u30fc\u30b8", }, love_mochi: { label: "\u3078\u3053\u9905", color: "rgba(190,82,132,0.78)", kind: "timer", timerProp: "loveMochiTimer", tags: ["item", "mochi", "behavior"], display: timer => `${Math.ceil(timer || 0)}\u79d2 / \u7e41\u6b96\u884c\u52d5\u304c\u8d77\u304d\u3084\u3059\u3044`, }, fight_mochi: { label: "\u3051\u3093\u304b\u9905", color: "rgba(180,86,52,0.80)", kind: "timer", timerProp: "fightMochiTimer", tags: ["item", "mochi", "behavior"], display: timer => `${Math.ceil(timer || 0)}\u79d2 / \u55a7\u5629\u304c\u8d77\u304d\u3084\u3059\u3044`, }, sleep_drug: { label: "\u306d\u3080\u308a\u85ac", color: "rgba(104,84,168,0.78)", kind: "disease", tags: ["item", "disease", "behavior"], }, first_aid: { label: "\u6551\u6025\u85ac", color: "rgba(210, 72, 82, 0.82)", kind: "instant", tags: ["item", "heal"], display: () => "\u5373\u6642 / HP\u56de\u5fa9\u306e\u307f", }, sedative: { label: "\u93ae\u9759\u85ac", color: "rgba(92, 142, 174, 0.82)", kind: "timed", defaultDuration: 42, tags: ["item", "behavior"], display: timer => `${Math.ceil(timer || 0)}\u79d2 / \u6050\u6016\u3068\u3051\u3093\u304b\u6c17\u5206\u3092\u6291\u3048\u308b`, }, mystery_drug: { label: "\u602a\u3057\u3044\u85ac", color: "rgba(60, 154, 87, 0.80)", kind: "instant", tags: ["item", "behavior"], }, zunda_juice: { label: "\u305a\u3093\u3060\u6c41", color: "rgba(87, 180, 79, 0.86)", kind: "cleanse", tags: ["item", "cleanse"], }, disease_zunchi: { label: "\u305a\u3093\u3061\u75c5", color: "rgba(113, 93, 59, 0.74)", kind: "disease", tags: ["disease", "behavior"] }, disease_sleep: { label: "\u306d\u3080\u308a\u75c5", color: "rgba(104,84,168,0.78)", kind: "disease", tags: ["disease", "behavior"] }, disease_explosion: { label: "\u7206\u767a\u75c5", color: "rgba(210, 90, 44, 0.78)", kind: "disease", tags: ["disease", "behavior"] }, disease_fight: { label: "\u304d\u305a\u3064\u304d\u75c5", color: "rgba(180,86,52,0.80)", kind: "disease", tags: ["disease", "behavior"] }, }; Object.assign(rawDefinitions.laxative, { modifiers: { hungerReliefMultiplier: 0 }, tickInterval: 3, bubblePolicy: "none", mysteryEligible: true, zundaJuiceRemovable: true, }); Object.assign(rawDefinitions.ammo, { modifiers: { speedMultiplier: 10 }, visualEffectId: "fall", bubblePolicy: "none", mysteryEligible: true, zundaJuiceRemovable: true, }); Object.assign(rawDefinitions.protein, { modifiers: { damageMultiplier: 1.75, diseaseChanceMultiplier: 0.5 }, visualEffectId: "fall_up_red", bubblePolicy: "none", mysteryEligible: true, zundaJuiceRemovable: true, }); Object.assign(rawDefinitions.niteropu, { modifiers: { damageMultiplier: 0.5, diseaseChanceMultiplier: 2 }, visualEffectId: "fall_down_purple", bubblePolicy: "none", mysteryEligible: true, zundaJuiceRemovable: true, }); Object.assign(rawDefinitions.mercury, { modifiers: { lifeMultiplierPerUse: 1.3 }, bubblePolicy: "none", mysteryEligible: true, zundaJuiceRemovable: true, }); Object.assign(rawDefinitions.giant_drug, { modifiers: { sizeMultiplier: 3, damageMultiplier: 2, speedMultiplier: 1.5, damagePerSecond: 1 }, bubblePolicy: "none", mysteryEligible: true, zundaJuiceRemovable: true, }); Object.assign(rawDefinitions.dwarf_drug, { modifiers: { sizeMultiplier: 0.25, damageMultiplier: 0.25, speedMultiplier: 0.5, damagePerSecond: 1 }, bubblePolicy: "none", mysteryEligible: true, zundaJuiceRemovable: true, }); for (const id of ["love_mochi", "fight_mochi", "sleep_drug"]) { Object.assign(rawDefinitions[id], { mysteryEligible: true, zundaJuiceRemovable: id !== "sleep_drug" }); } Object.assign(rawDefinitions.first_aid, { mysteryEligible: false, zundaJuiceRemovable: false }); Object.assign(rawDefinitions.sedative, { modifiers: { fearMultiplier: 0.45, fightWeightMultiplier: 0.28, speedMultiplier: 0.72 }, visualEffectId: "sedative", bubblePolicy: "none", mysteryEligible: true, zundaJuiceRemovable: true, }); Object.assign(rawDefinitions.zunda_juice, { removesItemEffects: true, mysteryEligible: false }); Object.assign(rawDefinitions.love_mochi, { onApply(tarinai, context = {}) { const scale = context.scale ?? 1; tarinai.loveMochiTimer = Math.max(tarinai.loveMochiTimer || 0, 42 * scale + deterministicRange(tarinai.world, "love-mochi-duration", 4, 12, tarinai, context.item)); const nutrition = Number(context.nutrition) || 0; if (typeof applyNeedRelief === "function") applyNeedRelief(tarinai, { fulfill: -(context.source === "eating" ? nutrition * 0.5 : 12), social: -4 }); if (context.source === "eating") { if (tarinai.forceBehavior) tarinai.forceBehavior("approach_mate", { source: "love_mochi", priority: 150, ttl: 24, searchRange: 820, causeText: "\u3078\u3053\u9905\u306e\u52b9\u679c" }); else if (typeof queueForcedTarinaiBehavior === "function") queueForcedTarinaiBehavior(tarinai, "approach_mate", { source: "love_mochi", priority: 150, ttl: 24, searchRange: 820, causeText: "\u3078\u3053\u9905\u306e\u52b9\u679c" }); } return true; }, }); Object.assign(rawDefinitions.fight_mochi, { onApply(tarinai, context = {}) { const scale = context.scale ?? 1; tarinai.fightMochiTimer = Math.max(tarinai.fightMochiTimer || 0, 52 * scale + deterministicRange(tarinai.world, "fight-mochi-duration", 10, 18, tarinai, context.item)); const nutrition = Number(context.nutrition) || 0; if (typeof applyNeedShock === "function") applyNeedShock(tarinai, { safety: context.source === "eating" ? nutrition * 0.5 : 16 }); if (context.source === "eating") { tarinai.fearTimer = Math.max(tarinai.fearTimer || 0, 0.32); if (tarinai.forceBehavior) tarinai.forceBehavior("fight_rival", { source: "fight_mochi", priority: 180, ttl: 24, searchRange: 820, causeText: "\u3051\u3093\u304b\u9905\u306e\u52b9\u679c" }); else if (typeof queueForcedTarinaiBehavior === "function") queueForcedTarinaiBehavior(tarinai, "fight_rival", { source: "fight_mochi", priority: 180, ttl: 24, searchRange: 820, causeText: "\u3051\u3093\u304b\u9905\u306e\u52b9\u679c" }); } return true; }, }); Object.assign(rawDefinitions.sleep_drug, { onApply(tarinai, context = {}) { if (context.source === "eating") { const nutrition = Number(context.nutrition) || 0; if (typeof applyNeedRelief === "function") applyNeedRelief(tarinai, { safety: -nutrition * 0.25, sleep: -nutrition * 0.15 }); tarinai.energy = clamp(tarinai.energy - nutrition * 0.20, 0, typeof tarinaiMaxEnergy === "function" ? tarinaiMaxEnergy(tarinai) : (Number(tarinai.maxEnergy) || 100)); tarinai.fearTimer = Math.max(0, (tarinai.fearTimer || 0) - 0.18); tarinai.fightMochiTimer = Math.max(0, (tarinai.fightMochiTimer || 0) - 2.5); const baseChance = Math.min(0.98, 0.35 + nutrition * 0.075); const sleepChance = tarinai.diseaseChance ? tarinai.diseaseChance(baseChance) : baseChance; if (tarinai.forceBehavior) tarinai.forceBehavior("sleep_anywhere", { source: "sleep_drug", priority: 145, ttl: 14, duration: 8, minDuration: 8, causeText: "\u306d\u3080\u308a\u85ac\u306e\u52b9\u679c" }); else if (typeof queueForcedTarinaiBehavior === "function") queueForcedTarinaiBehavior(tarinai, "sleep_anywhere", { source: "sleep_drug", priority: 145, ttl: 14, duration: 8, minDuration: 8, causeText: "\u306d\u3080\u308a\u85ac\u306e\u52b9\u679c" }); if (!tarinai.sleepDisease && deterministicChance(tarinai.world, "sleep-drug-disease", Math.min(0.98, sleepChance), tarinai, context.item)) return tarinai.infectSleepDisease?.(context.item || null) || true; return true; } return tarinai.infectSleepDisease?.(context.item || null) || true; }, }); Object.assign(rawDefinitions.first_aid, { onApply(tarinai, context = {}) { const max = typeof tarinaiMaxEnergy === "function" ? tarinaiMaxEnergy(tarinai) : (Number(tarinai.maxEnergy) || 100); const scale = Math.max(0.35, Number(context.scale ?? 1) || 1); const amount = Math.max(18, Math.round(max * 0.38 * scale)); const before = Number(tarinai.energy || 0) || 0; tarinai.recoverHealth?.(amount); const recovered = Math.max(0, (Number(tarinai.energy || 0) || 0) - before); if (recovered > 0.0001) global.TarinaiAchievements?.recordFirstAidRecovery?.({ world: tarinai.world, tarinai, item: context.item || null, source: context.source || "", recovered }); tarinai.hpBarTimer = Math.max(tarinai.hpBarTimer || 0, 2.4); tarinai.spawnPowerItemEffect?.("first_aid", 0.42); tarinai.bubble?.("HP+", 2.2, "rgba(210,72,82,0.82)", { force: true }); return true; }, }); Object.assign(rawDefinitions.sedative, { onApply(tarinai, context = {}) { const duration = Math.round((this.defaultDuration || 42) * Math.max(0.35, Number(context.scale ?? 1) || 1)); tarinai.setTimedItemEffect?.("sedative", duration); tarinai.fearTimer = Math.max(0, (tarinai.fearTimer || 0) - 2.4); tarinai.intimidatedTimer = Math.max(0, (tarinai.intimidatedTimer || 0) - 1.8); tarinai.fightMochiTimer = Math.max(0, (tarinai.fightMochiTimer || 0) - 10); tarinai.postConflictPeaceTimer = Math.max(tarinai.postConflictPeaceTimer || 0, 14); if (typeof applyNeedRelief === "function") applyNeedRelief(tarinai, { safety: -18, social: -2 }); tarinai.spawnPowerItemEffect?.("sedative", 0.36); return true; }, }); Object.assign(rawDefinitions.laxative, { onApply(tarinai, context = {}) { return tarinai.setTimedItemEffect?.("laxative", Math.round((this.defaultDuration || 60) * (context.scale ?? 1))); }, onTick(tarinai) { tarinai.forceLaxativePoop?.(); return true; }, }); Object.assign(rawDefinitions.ammo, { onApply(tarinai, context = {}) { return tarinai.setTimedItemEffect?.("ammo", Math.round((this.defaultDuration || 18) * (context.scale ?? 1))); }, }); Object.assign(rawDefinitions.protein, { onApply(tarinai) { return tarinai.setPowerItemMode?.("protein"); }, }); Object.assign(rawDefinitions.niteropu, { onApply(tarinai) { return tarinai.setPowerItemMode?.("niteropu"); }, }); Object.assign(rawDefinitions.mercury, { onApply(tarinai) { return tarinai.setMercuryEffect?.(); }, }); Object.assign(rawDefinitions.giant_drug, { onApply(tarinai) { return tarinai.setSizeItemMode?.("giant_drug"); }, onTick(tarinai) { tarinai.damage?.(this.modifiers?.damagePerSecond || 1, this.label); if (tarinai.world?.effects) tarinai.spawnPowerItemEffect?.("giant_drug", 0.25); return true; }, }); Object.assign(rawDefinitions.dwarf_drug, { onApply(tarinai) { return tarinai.setSizeItemMode?.("dwarf_drug"); }, onTick(tarinai) { tarinai.damage?.(this.modifiers?.damagePerSecond || 1, this.label); if (tarinai.world?.effects) tarinai.spawnPowerItemEffect?.("dwarf_drug", 0.25); return true; }, }); Object.assign(rawDefinitions.zunda_juice, { onApply(tarinai) { return tarinai.clearAllItemEffects?.(); }, }); Object.assign(rawDefinitions.disease_zunchi, { onApply(tarinai, context = {}) { return tarinai.infectZunchiDisease?.(context.item || null, true) || true; }, }); Object.assign(rawDefinitions.disease_sleep, { onApply(tarinai, context = {}) { return tarinai.infectSleepDisease?.(context.item || null) || true; }, }); Object.assign(rawDefinitions.disease_explosion, { onApply(tarinai, context = {}) { return tarinai.infectExplosionDisease?.(context.item || null) || true; }, }); Object.assign(rawDefinitions.disease_fight, { onApply(tarinai, context = {}) { return tarinai.infectFightDisease?.(context.item || null) || true; }, }); class EffectRegistry extends global.TarinaiRegistryBase { label(id = "") { return super.label(id, id || "\u4e0d\u660e"); } color(id = "") { return super.color(id, "rgba(255,242,160,0.85)"); } display(id = "", timer = 0, tarinai = null) { const def = this.get(id); if (!def) return ""; return typeof def.display === "function" ? def.display(timer, tarinai, def) : (def.display || ""); } apply(id = "", tarinai = null, context = {}) { const def = this.get(id); if (!def || !tarinai || typeof def.onApply !== "function") return false; return Boolean(def.onApply.call(def, tarinai, { ...context, effectId: id, registry: this })); } tick(id = "", tarinai = null, dt = 0, context = {}) { const def = this.get(id); if (!def || !tarinai || typeof def.onTick !== "function") return false; return Boolean(def.onTick.call(def, tarinai, Math.max(0, Number(dt) || 0), { ...context, effectId: id, registry: this })); } remove(id = "", tarinai = null, context = {}) { const def = this.get(id); if (!def || !tarinai || typeof def.onRemove !== "function") return false; return Boolean(def.onRemove.call(def, tarinai, { ...context, effectId: id, registry: this })); } modifier(id = "", key = "", fallback = 1) { const value = this.get(id)?.modifiers?.[key]; return Number.isFinite(value) ? value : fallback; } timerValue(tarinai = null, id = "") { const def = this.get(id); if (!def || !tarinai) return 0; if (def.timerProp) return Number(tarinai[def.timerProp] || 0); if (def.kind === "timed") return Number(tarinai.itemEffectTimers?.[id] || 0); return 0; } isActive(tarinai = null, id = "") { if (!tarinai) return false; const def = this.get(id); if (!def) return false; if (id === "protein" || id === "niteropu") return tarinai.powerItemMode === id; if (id === "giant_drug" || id === "dwarf_drug") return tarinai.sizeItemMode === id; if (id === "mercury") return tarinai.lifeItemMode === "mercury"; return this.timerValue(tarinai, id) > 0.04; } activeSummary(tarinai = null) { const order = ["protein", "niteropu", "mercury", "giant_drug", "dwarf_drug", "laxative", "ammo", "sedative", "love_mochi", "fight_mochi"]; return order .filter(id => this.isActive(tarinai, id)) .map(id => ({ id, label: this.label(id), detail: this.display(id, this.timerValue(tarinai, id), tarinai), })); } randomPool() { const itemEffects = [...this.defs.entries()] .filter(([id, def]) => Boolean(def.mysteryEligible && id !== "mystery_drug" && id !== "zunda_juice" && !(def.tags || []).includes("disease"))) .map(([id]) => id) .filter(id => id !== "mystery_drug" && id !== "zunda_juice"); const diseases = global.TarinaiDiseaseRegistry.mysteryPool() || []; return [...new Set([...itemEffects, ...diseases])]; } } const registry = new EffectRegistry(rawDefinitions); global.TarinaiEffectRegistry = registry; })(typeof window !== "undefined" ? window : globalThis);