tarinai/js/tarinai_forced_behavior.js
2026-07-01 14:41:05 +09:00

465 lines
24 KiB
JavaScript

"use strict";
function actionById(id = "") {
const key = String(id || "");
return (typeof getTarinaiActionSpec === "function" ? getTarinaiActionSpec(key) : null)
|| (Array.isArray(TARINAI_ACTIONS) ? TARINAI_ACTIONS.find(action => action && action.id === key) || null : null);
}
function behaviorTargetId(target = null) {
if (!target) return null;
if (target.id != null) return target.id;
if (Number.isFinite(target.x) && Number.isFinite(target.y)) return `pos:${Math.round(target.x)},${Math.round(target.y)}`;
return null;
}
function currentBehaviorTarget(tarinai, behavior = null) {
if (!tarinai) return null;
const b = behavior || (currentTarinaiBehavior(tarinai)) || null;
if (!b) return tarinai.target || null;
const ref = b.target || null;
const id = ref?.id || b.targetId || null;
if (tarinai.target && !tarinai.target.dead && (!id || behaviorTargetId(tarinai.target) === id)) return tarinai.target;
if (id) {
return tarinai.world?.liveTarinaiById?.(id)
|| tarinai.world?.itemById?.(id)
|| (tarinai.world?.items || []).find(item => item && !item.dead && item.id === id)
|| null;
}
if (Number.isFinite(ref?.x) && Number.isFinite(ref?.y)) return { x: ref.x, y: ref.y, dead: false };
return null;
}
function isLiveTarinaiEntity(value) {
return Boolean(value && !value.dead && typeof value.relationTo === "function" && Number.isFinite(value.x) && Number.isFinite(value.y));
}
function nearestForcedFightTarget(tarinai, world, maxDist = 720) {
if (!tarinai || !world) return null;
const current = currentBehaviorTarget(tarinai) || tarinai.target || null;
const ok = o => isLiveTarinaiEntity(o) && o !== tarinai && !!o.isZunchiSlave === !!tarinai.isZunchiSlave && !world.areParentChild?.(tarinai, o) && !world.areCoParents?.(tarinai, o) && !o.sleepDisease;
if (ok(current) && dist(tarinai, current) <= maxDist + 120) return current;
const conflict = conflictTargetFor(tarinai, world, 6);
if (ok(conflict?.target)) return conflict.target;
return world.nearestOther?.(tarinai, maxDist, ok) || null;
}
function resolveForcedBehaviorTarget(tarinai, world, entry = {}, action = null) {
if (!tarinai || !world) return null;
if (entry.targetId) {
const found = world.liveTarinaiById?.(entry.targetId)
|| world.itemById?.(entry.targetId)
|| (world.items || []).find(item => item && !item.dead && item.id === entry.targetId)
|| null;
if (found) return found;
}
const id = String(entry.id || action?.id || "");
if (id === "fight_rival" || id === "intimidate_enemy") return nearestForcedFightTarget(tarinai, world, Number(entry.searchRange || 760));
if (id === "approach_mate" || id === "birth_ritual") return mateTargetFor(tarinai, world, Number(entry.searchRange || 760));
if (id === "eat_food") return behaviorFoodTarget(tarinai, world, "food", Number(entry.searchRange || 900));
if (id === "drink_water") return behaviorFoodTarget(tarinai, world, "drink", Number(entry.searchRange || 680));
if (id === "use_medicine") return behaviorFoodTarget(tarinai, world, "medicine", Number(entry.searchRange || 760));
if (id === "sleep_in_bed") return findNearestSleepPlace(world, tarinai, Number(entry.searchRange || 760));
return null;
}
function forcedBehaviorSourcePriority(source = "external") {
return Number(TARINAI_FORCED_BEHAVIOR_SOURCE_PRIORITY[String(source || "external")] || TARINAI_FORCED_BEHAVIOR_SOURCE_PRIORITY.external || 130) || 130;
}
function forcedBehaviorQueueOf(tarinai) {
if (!tarinai) return [];
if (!Array.isArray(tarinai.forcedBehaviorQueue)) tarinai.forcedBehaviorQueue = [];
return tarinai.forcedBehaviorQueue;
}
function setForcedBehaviorQueue(tarinai, queue = []) {
if (!tarinai) return [];
tarinai.forcedBehaviorQueue = (Array.isArray(queue) ? queue : []).filter(Boolean);
return tarinai.forcedBehaviorQueue;
}
function normalizeForcedBehaviorEntry(tarinai, actionId, opts = {}) {
const now = tarinai?.world?.time || 0;
const source = opts.source || "external";
const basePriority = forcedBehaviorSourcePriority(source);
const raw = {
uid: opts.uid || `${String(actionId)}:${source}:${now.toFixed(3)}:${Math.random().toString(36).slice(2, 8)}`,
id: String(actionId),
targetId: opts.targetId ?? behaviorTargetId(opts.target),
reason: opts.reasonText || opts.reason || "",
causeText: opts.causeText || "",
source,
priority: Number(opts.priority ?? Math.max(basePriority, actionPriority(actionId) + 70)) || basePriority,
force: opts.force !== false,
replaceSameSource: opts.replaceSameSource !== false,
interrupt: opts.interrupt !== false,
createdAt: now,
status: opts.status || "queued",
attempts: Number(opts.attempts || 0) || 0,
lastTriedAt: Number(opts.lastTriedAt ?? -999) || -999,
retryDelay: Number(opts.retryDelay ?? 0.25) || 0.25,
expiresAt: Number.isFinite(opts.expiresAt) ? opts.expiresAt : now + Number(opts.ttl ?? 18),
duration: Number(opts.duration ?? 0) || 0,
minDuration: Number(opts.minDuration ?? opts.duration ?? 0) || 0,
searchRange: Number(opts.searchRange ?? 0) || 0,
};
return typeof normalizeTarinaiForcedRequest === "function" ? { ...raw, ...normalizeTarinaiForcedRequest(raw, raw), force: raw.force, replaceSameSource: raw.replaceSameSource, interrupt: raw.interrupt, retryDelay: raw.retryDelay, attempts: raw.attempts, lastTriedAt: raw.lastTriedAt, searchRange: raw.searchRange } : raw;
}
function markForcedBehaviorActive(tarinai, entry, action = null) {
if (!tarinai || !entry) return null;
entry.status = "active";
entry.activeSince = entry.activeSince || tarinai.world?.time || 0;
entry.startedAt = entry.startedAt || entry.activeSince;
const payload = { ...entry, id: action?.id || entry.id, status: "active" };
return typeof setTarinaiForcedBehavior === "function" ? setTarinaiForcedBehavior(tarinai, payload) : payload;
}
function behaviorIsForced(behavior = null) {
return typeof isTarinaiBehaviorValueForced === "function"
? isTarinaiBehaviorValueForced(behavior)
: Boolean(behavior?.source === "forced" || behavior?.forcedId || behavior?.forcedRequest);
}
function isCurrentBehaviorForced(tarinai) {
return behaviorIsForced(currentTarinaiBehavior(tarinai));
}
function currentForcedBehaviorRequest(tarinai) {
if (typeof getTarinaiForcedBehavior === "function") return getTarinaiForcedBehavior(tarinai);
const b = currentTarinaiBehavior(tarinai);
return behaviorIsForced(b) ? (b.forcedRequest || { uid: b.forcedId || "", id: b.actionId || "", source: b.data?.forcedSource || b.source || "external", priority: Number(b.priority || 0) || 0 }) : null;
}
function clearForcedBehaviorQueue(tarinai, predicate = null) {
if (!tarinai) return 0;
const queue = forcedBehaviorQueueOf(tarinai);
const before = queue.length;
const next = typeof predicate !== "function" ? [] : queue.filter(entry => !predicate(entry));
setForcedBehaviorQueue(tarinai, next);
const active = currentForcedBehaviorRequest(tarinai);
if (active?.uid && !next.some(entry => entry && entry.uid === active.uid) && typeof clearTarinaiForcedBehavior === "function") clearTarinaiForcedBehavior(tarinai);
return before - next.length;
}
function behaviorText(tarinai) {
const b = currentTarinaiBehavior(tarinai);
if (!b) return "";
const state = String(tarinai.state || "");
const timerActive = (tarinai.birthRitualTimer || 0) > 0.04 || (tarinai.fightTimer || 0) > 0.04 || (tarinai.eatTimer || 0) > 0.04 || (tarinai.intimidateTimer || 0) > 0.04 || (tarinai.fearTimer || 0) > 0.04;
const validByState = !b.state || b.state === state || timerActive || ["seek_food", "seek_water", "seek_friend", "seek_enemy", "follow_parent", "seek_bed", "wander", "build", "play_ball"].includes(state);
if (!validByState && !behaviorIsForced(b)) return "";
return composeTarinaiBehaviorText(tarinai, b) || String(b.text || b.reason || b.label || "").trim();
}
function setBehavior(tarinai, fields = {}) {
if (!tarinai || tarinai.dead) return null;
const now = tarinai.world?.time || 0;
const previous = (currentTarinaiBehavior(tarinai)) || {};
const previousActionId = previous.actionId || "";
const actionId = fields.actionId || fields.id || previousActionId || tarinai.state || "idle";
const action = fields.action || actionById(actionId) || null;
const need = fields.need || action?.need || previous.need || "fulfill";
const label = fields.label || fields.actionLabel || action?.label || previous.label || "\u884c\u52d5\u3057\u3066\u3044\u308b";
const reason = fields.reason || fields.text || label;
const startedAt = Number.isFinite(fields.startedAt) ? fields.startedAt : (Number.isFinite(previous.startedAt) && previousActionId === actionId ? previous.startedAt : now);
const lockSeconds = Number(fields.lockSeconds ?? previous.lockSeconds ?? (action ? actionLockSeconds(action, tarinai) : 1.0)) || 1.0;
const minDuration = Number(fields.minDuration ?? previous.minDuration ?? Math.max(0.45, lockSeconds * 0.72)) || 0.45;
const target = fields.target !== undefined ? fields.target : tarinai.target;
const forced = Boolean(fields.forced ?? (typeof isTarinaiBehaviorValueForced === "function" ? isTarinaiBehaviorValueForced(previous) : Boolean(previous.forcedId || previous.forcedRequest)));
const source = forced ? "forced" : (fields.source || previous.source || "need");
const forcedRequest = fields.forcedRequest || previous.forcedRequest || null;
const next = {
actionId,
need,
subNeed: fields.subNeed || action?.subNeed || previous.subNeed || "",
phase: fields.phase || previous.phase || (String(tarinai.state || "") === "idle" ? "idle" : "acting"),
label,
text: fields.text || reason,
reason,
target,
startedAt,
elapsed: Math.max(0, now - startedAt),
minDuration,
lockSeconds,
deadlineAt: Number.isFinite(fields.deadlineAt) ? fields.deadlineAt : previous.deadlineAt,
source,
sourceReasonText: fields.sourceReasonText || previous.sourceReasonText || "",
causeText: fields.causeText || previous.causeText || "",
forcedId: fields.forcedId || previous.forcedId || "",
forcedRequest,
priority: Number(fields.priority ?? previous.priority ?? (action ? actionPriority(action) : 0)) || 0,
interruptible: fields.interruptible !== false,
data: { ...(previous.data || {}), ...(fields.data || {}) },
tiedNeeds: fields.tiedNeeds || previous.tiedNeeds || [need],
specId: fields.specId || action?.id || previous.specId || actionId,
specKind: fields.specKind || action?.kind || previous.specKind || "need_action",
};
if (forcedRequest?.source) next.data.forcedSource = forcedRequest.source;
tarinai.behaviorSerial = (tarinai.behaviorSerial || 0) + 1;
next.serial = tarinai.behaviorSerial;
if (typeof setTarinaiBehavior === "function") tarinai.behavior = setTarinaiBehavior(tarinai, next);
else tarinai.behavior = next;
if (target !== undefined) tarinai.target = target;
if (reason && (!tarinai.thought || tarinai.thought === previous.reason || tarinai.thought === previous.text || tarinai.thought === previous.label)) tarinai.thought = reason;
return tarinai.behavior || next;
}
function setBehaviorFromAction(tarinai, action, choice = {}, reasonText = "", options = {}) {
if (!action) return null;
return setBehavior(tarinai, {
actionId: action.id,
action: action,
need: choice.need || action.need,
subNeed: options.subNeed || action.subNeed || "",
label: action.label || options.actionLabel || "\u884c\u52d5\u3057\u3066\u3044\u308b",
text: reasonText || action.label,
reason: reasonText || action.label,
target: options.target !== undefined ? options.target : tarinai?.target,
tiedNeeds: choice.tiedNeeds || [choice.need || action.need],
source: options.forced ? "forced" : (options.source || "need"),
forced: Boolean(options.forced),
forcedId: options.forcedId || "",
sourceReasonText: options.sourceReasonText || "",
causeText: options.causeText || "",
forcedRequest: options.forcedRequest || null,
priority: options.priority ?? actionPriority(action),
lockSeconds: options.lockSeconds,
minDuration: options.minDuration,
phase: options.phase || "starting",
specId: action.id,
specKind: action.kind || "need_action",
});
}
function clearBehavior(tarinai, reason = "") {
if (!tarinai) return;
clearTarinaiBehavior(tarinai, { reason });
if (reason) tarinai.thought = reason;
}
function queueForcedTarinaiBehavior(tarinai, actionId, opts = {}) {
if (!tarinai || tarinai.dead || !actionId) return false;
const entry = normalizeForcedBehaviorEntry(tarinai, actionId, opts);
let queue = forcedBehaviorQueueOf(tarinai);
if (entry.replaceSameSource) queue = queue.filter(e => !(e && e.id === entry.id && e.source === entry.source));
queue.push(entry);
queue.sort((a, b) => (Number(b.priority || 0) - Number(a.priority || 0)) || (Number(a.createdAt || 0) - Number(b.createdAt || 0)));
setForcedBehaviorQueue(tarinai, queue.slice(0, 12));
if (opts.target) tarinai.target = opts.target;
if (opts.applyShock && typeof applyNeedShock === "function") applyNeedShock(tarinai, opts.applyShock, opts.target || null);
return true;
}
function completeForcedBehavior(tarinai, behavior = null, status = "completed") {
if (!tarinai) return false;
const b = behavior || (currentTarinaiBehavior(tarinai)) || {};
const forcedId = b.forcedId || "";
if (!forcedId) return false;
const queue = forcedBehaviorQueueOf(tarinai);
const before = queue.length;
const next = queue.filter(entry => entry && entry.uid !== forcedId);
setForcedBehaviorQueue(tarinai, next);
if (typeof clearTarinaiForcedBehavior === "function") clearTarinaiForcedBehavior(tarinai);
return before !== next.length;
}
function retryForcedBehavior(tarinai, behavior = null, reason = "retry") {
if (!tarinai) return false;
const b = behavior || (currentTarinaiBehavior(tarinai)) || {};
const forcedId = b.forcedId || "";
if (!forcedId) return false;
const now = tarinai.world?.time || 0;
const entry = forcedBehaviorQueueOf(tarinai).find(e => e && e.uid === forcedId);
if (!entry) return false;
entry.status = "queued";
entry.failReason = reason;
entry.activeSince = 0;
if (typeof clearTarinaiForcedBehavior === "function") clearTarinaiForcedBehavior(tarinai);
return true;
}
function processForcedBehaviorQueue(tarinai, world, needs) {
if (!tarinai || tarinai.dead) return false;
const now = world?.time || 0;
let queue = forcedBehaviorQueueOf(tarinai).filter(entry => entry && (!Number.isFinite(entry.expiresAt) || entry.expiresAt >= now));
if (!queue.length) {
setForcedBehaviorQueue(tarinai, []);
if (typeof clearTarinaiForcedBehavior === "function") clearTarinaiForcedBehavior(tarinai);
return false;
}
// \u5b9f\u884c\u4e2d\u306e\u5f37\u5236\u884c\u52d5\u306f\u30ad\u30e5\u30fc\u306b\u6b8b\u3057\u3001\u5b8c\u4e86/\u5931\u6557/\u671f\u9650\u5207\u308c\u307e\u3067\u52b9\u679c\u3092\u4fdd\u6301\u3059\u308b\u3002
const activeQueueBehavior = currentTarinaiBehavior(tarinai);
const activeForcedId = activeQueueBehavior?.forcedId || "";
for (const entry of queue) {
if (!entry.uid) entry.uid = `${entry.id}:${entry.source || "external"}:${entry.createdAt || now}:${Math.random().toString(36).slice(2, 8)}`;
if (entry.uid === activeForcedId && behaviorIsForced(activeQueueBehavior) && activeQueueBehavior?.actionId === entry.id) {
markForcedBehaviorActive(tarinai, entry, actionById(entry.id));
} else if (entry.status === "active") {
// behavior \u304c\u5916\u90e8\u8981\u56e0\u3067\u6d88\u3048\u305f\u5834\u5408\u306f\u3001\u671f\u9650\u5185\u306a\u3089\u518d\u8a66\u884c\u3078\u623b\u3059\u3002
entry.status = "queued";
}
}
queue.sort((a, b) => (Number(b.priority || 0) - Number(a.priority || 0)) || (Number(a.createdAt || 0) - Number(b.createdAt || 0)));
setForcedBehaviorQueue(tarinai, queue);
const activePriority = Number(activeQueueBehavior?.priority ?? actionPriority(activeQueueBehavior?.actionId)) || 0;
const activeForced = behaviorIsForced(activeQueueBehavior);
for (let i = 0; i < queue.length; i++) {
const entry = queue[i];
const action = actionById(entry.id);
if (!action) { queue.splice(i, 1); i--; continue; }
if (entry.status === "active" && activeQueueBehavior?.forcedId === entry.uid) continue;
const entryPriority = Number(entry.priority ?? actionPriority(entry.id)) || 0;
if (activeQueueBehavior && (tarinai.behaviorLockTimer || 0) > 0.08) {
if (activeForced && entryPriority <= activePriority + 8) continue;
if (!entry.interrupt && entryPriority <= activePriority) continue;
if (entryPriority <= activePriority && !entry.force) continue;
}
if (now - Number(entry.lastTriedAt || -999) < Number(entry.retryDelay || 0.25)) continue;
entry.lastTriedAt = now;
entry.attempts = (Number(entry.attempts || 0) || 0) + 1;
const target = resolveForcedBehaviorTarget(tarinai, world, entry, action);
if (target) {
tarinai.target = target;
entry.targetId = behaviorTargetId(target);
}
if ((action.id === "fight_rival" || action.id === "intimidate_enemy" || action.id === "approach_mate" || action.id === "birth_ritual") && !target) {
continue;
}
const need = action.need || entry.need || "safety";
const choice = { need, tiedNeeds: [need], max: Math.max(needThreshold(need, "start"), Number(needs?.[need] || 0) || 0) };
const causeText = entry.causeText || forcedCausePhrase(entry.source || "", entry.reasonText || "");
const reasonText = buildReasonText(need, choice.tiedNeeds, action, tarinai, world, { causeText });
if (activeQueueBehavior && entryPriority > activePriority) {
retryForcedBehavior(tarinai, activeQueueBehavior, "interrupted_by_higher_forced_behavior");
clearBehavior(tarinai);
tarinai.behaviorLockTimer = 0;
if (tarinai.state === "sleep" || tarinai.sleeping) {
tarinai.sleeping = false;
tarinai.sleepSession = null;
}
}
const started = startNeedAction(tarinai, world, choice, action, reasonText, {
forced: true,
forcedId: entry.uid,
forcedReasonText: entry.reasonText || reasonText,
sourceReasonText: entry.reasonText || reasonText,
causeText,
priority: entryPriority,
source: entry.source,
target,
forcedRequest: { ...entry, status: "active", reason: entry.reasonText || reasonText, causeText },
lockSeconds: entry.duration || undefined,
minDuration: entry.minDuration || undefined,
});
if (started) {
markForcedBehaviorActive(tarinai, entry, action);
setForcedBehaviorQueue(tarinai, queue);
return true;
}
}
setForcedBehaviorQueue(tarinai, queue);
return false;
}
function effectCauseTextLooksStale(text = "") {
return /\u306E\u52B9\u679C$/.test(String(text || "").trim().replace(/[\u3002\uFF01\uFF1F]+$/, ""));
}
function setBehaviorText(tarinai, { need = null, actionId = null, actionLabel = null, reasonText = null, reason = null, target = undefined, subNeed = "", phase = "active", source = "state", forced = null, forcedId = "", sourceReasonText = "", forcedReasonText = "", causeText = "" } = {}) {
if (!tarinai) return;
const now = tarinai.world?.time || 0;
const previousBehavior = (currentTarinaiBehavior(tarinai)) || {};
const previousActionId = previousBehavior.actionId || "";
const nextNeed = need || previousBehavior.need || "social";
const nextActionId = actionId || previousActionId || tarinai.state || "idle";
const displayReason = reasonText ?? reason;
const nextActionLabel = actionLabel || displayReason || previousBehavior.label || tarinai.state || "\u884c\u52d5\u3057\u3066\u3044\u308b";
const action = actionById(nextActionId);
const previousForced = behaviorIsForced(previousBehavior);
const preserveForced = Boolean(previousForced && source === "state" && (!actionId || previousActionId === nextActionId));
let nextReasonText = displayReason || nextActionLabel;
const rawNeedsForText = tarinai.needRaw || tarinai.needs || {};
const existingTiedNeeds = (Array.isArray(previousBehavior.tiedNeeds) && previousBehavior.tiedNeeds.length ? [...previousBehavior.tiedNeeds] : [nextNeed])
.filter((key, idx) => idx === 0 || Number(rawNeedsForText?.[key] || 0) > 0.5);
if (existingTiedNeeds.some(key => key && key !== nextNeed) && !String(nextReasonText).includes("\u3051\u3069\u3001")) {
nextReasonText = buildReasonText(nextNeed, existingTiedNeeds, { ...(action || {}), id: nextActionId, label: nextActionLabel, subNeed: subNeed || action?.subNeed || "" }, tarinai, tarinai.world || null);
}
const nextForced = forced ?? preserveForced;
const nextSource = nextForced ? "forced" : (source || previousBehavior.source || "state");
const nextForcedId = nextForced ? (forcedId || previousBehavior.forcedId || "") : "";
const nextSourceReason = nextForced ? (sourceReasonText || forcedReasonText || previousBehavior.sourceReasonText || "") : (sourceReasonText || forcedReasonText || "");
const explicitCauseText = String(causeText || "");
const previousCauseText = String(previousBehavior.causeText || "");
const nextCauseText = explicitCauseText || ((nextForced || !effectCauseTextLooksStale(previousCauseText)) ? previousCauseText : "");
if (nextCauseText) {
nextReasonText = buildReasonText(nextNeed, existingTiedNeeds.length ? existingTiedNeeds : [nextNeed], { ...(action || {}), id: nextActionId, label: nextActionLabel, subNeed: subNeed || action?.subNeed || "" }, tarinai, tarinai.world || null, { causeText: nextCauseText });
}
if (target !== undefined) tarinai.target = target;
setBehavior(tarinai, {
actionId: nextActionId,
action,
need: nextNeed,
subNeed: subNeed || action?.subNeed || previousBehavior.subNeed || "",
label: nextActionLabel,
text: nextReasonText,
reason: nextReasonText,
target: target !== undefined ? target : tarinai.target,
tiedNeeds: existingTiedNeeds,
source: nextSource,
sourceReasonText: nextSourceReason,
causeText: nextCauseText,
forced: nextForced,
forcedId: nextForcedId,
forcedRequest: nextForced ? (previousBehavior.forcedRequest || null) : null,
priority: previousBehavior.priority ?? actionPriority(action),
phase,
startedAt: previousBehavior.startedAt || now,
minDuration: previousBehavior.minDuration || 0.8,
lockSeconds: previousBehavior.lockSeconds || 1.0,
});
}
function synchronizeActionTextFromState(tarinai) {
if (!tarinai || tarinai.dead) return;
const state = String(tarinai.state || "");
const catalogText = typeof window !== "undefined" && window.TEXT_CATALOG?.reasonLabel ? window.TEXT_CATALOG.reasonLabel(tarinai) : "";
if (state === "birth_ritual" || (tarinai.birthRitualTimer || 0) > 0.04) {
const partner = tarinai.world?.tarinai?.find?.(o => o && !o.dead && o.id === tarinai.birthPartnerId) || tarinai.target || null;
const label = partner?.name ? `${partner.name}\u3068\u3078\u3053\u3078\u3053\u3057\u3066\u3044\u308b` : "\u3078\u3053\u3078\u3053\u3057\u3066\u3044\u308b";
setBehaviorText(tarinai, { need: "social", actionId: "birth_ritual", actionLabel: "\u3078\u3053\u3078\u3053\u3057\u3066\u3044\u308b", reason: label, target: partner });
return;
}
if (state === "eat" || (tarinai.eatTimer || 0) > 0.04 || (tarinai.grassEatTimer || 0) > 0.04) {
setBehaviorText(tarinai, { need: "food", actionId: "eat_food", actionLabel: "\u98df\u3079\u3066\u3044\u308b", reason: catalogText || "\u98df\u3079\u3066\u3044\u308b" });
return;
}
if (state === "fight" || (tarinai.fightTimer || 0) > 0.04) {
setBehaviorText(tarinai, { need: "social", actionId: "fight_rival", actionLabel: "\u55a7\u5629\u3057\u3066\u3044\u308b", reason: catalogText || "\u55a7\u5629\u3057\u3066\u3044\u308b" });
return;
}
if (state === "panic" || (tarinai.defeatedTimer || 0) > 0.04) {
setBehaviorText(tarinai, { need: "safety", actionId: "panic_escape", actionLabel: "\u9003\u3052\u3066\u3044\u308b", reason: catalogText || "\u6016\u304f\u3066\u9003\u3052\u3066\u3044\u308b" });
return;
}
if (state === "intimidate" || (tarinai.intimidateTimer || 0) > 0.04) {
setBehaviorText(tarinai, { need: "social", actionId: "intimidate_enemy", actionLabel: "\u5a01\u5687\u3057\u3066\u3044\u308b", reason: catalogText || "\u5a01\u5687\u3057\u3066\u3044\u308b" });
return;
}
if (state === "sleep" || tarinai.sleeping) {
setBehaviorText(tarinai, { need: "sleep", actionId: (getTarinaiBehaviorId(tarinai)) || "sleep_anywhere", actionLabel: "\u7720\u3063\u3066\u3044\u308b", reason: catalogText || "\u7720\u3063\u3066\u3044\u308b" });
}
}