"use strict"; // ActionSpec factories and TARINAI_ACTIONS registry. function selectRoleTarget(role, range) { return function selectTarget(tarinai, world) { return findNearestItemWithRole(world, tarinai, role, range); }; } function startMoveToTarget(state, fallbackLabel = "\u884c\u52d5\u3057\u3066\u3044\u308b") { return function start(tarinai, world, ctx = {}) { const target = ctx.target ?? this.selectTarget?.(tarinai, world, ctx) ?? null; return moveToOrUse(tarinai, target, state, this.label || fallbackLabel); }; } function selectOwnedStructure(type, range = Infinity) { return function selectTarget(tarinai, world) { return findOwnedStructure(world, tarinai, type, range); }; } function selectMateTarget(tarinai, world, range = 440) { const eligible = other => other && other !== tarinai && !other.dead && !world.areParentChild?.(tarinai, other) && !!tarinai.isZunchiSlave === !!other.isZunchiSlave && !other.sleepDisease && !other.fightDisease; if (tarinai?.isTarinaiChampion) { const champion = world?.nearestOther?.(tarinai, range + 260, other => eligible(other) && other.isTarinaiChampion) || null; if (champion) return champion; } return world?.nearestOther?.(tarinai, range, eligible) || null; } function basicCanStartWithTarget(t, world, ctx = {}) { return !!(ctx.target ?? this.selectTarget?.(t, world, ctx)); } function createConsumableActionSpec({ id, subNeed = "", state, label, phrase, weight, role, range }) { return { id, need: role === "medicine" ? "health" : "food", subNeed, state, label, phrase, weight, timerBacked: true, selectTarget: selectRoleTarget(role, range), canStart: basicCanStartWithTarget, start: startMoveToTarget(state, label), tick(t, world, dt) { return updateConsumableBehavior(t, world, dt, role); }, finish(t) { if (role === "drink" && typeof applyNeedSatisfaction === "function") applyNeedSatisfaction(t, { food: 8, health: 2 }, "drink"); return true; }, fail(t) { if (t) t.target = null; return false; }, }; } function createSleepInBedActionSpec() { return { id: "sleep_in_bed", need: "sleep", state: "seek_bed", label: "\u5bdd\u308b\u5834\u6240\u3092\u63a2\u3057\u3066\u3044\u308b", phrase: "\u5bdd\u308b\u5834\u6240\u3078\u623b\u3063\u305f", weight: 42, timerBacked: true, selectTarget(t, world) { return findNearestSleepPlace(world, t, 760); }, canStart: basicCanStartWithTarget, start(t, world, ctx = {}) { const bed = ctx.target ?? this.selectTarget(t, world, ctx); if (!bed) return false; if (dist(t, bed) > (t.radius || 20) + 18) return moveToOrUse(t, bed, "seek_bed", this.label); const isEasyBed = bed.type === "grass_bed"; bed.use?.(t, world, isEasyBed ? { purpose: "sleep" } : undefined); const sleepText = bed.type === "pipe" ? "\u571f\u7ba1\u306e\u4e2d\u3067\u5bdd\u3066\u3044\u308b" : (bed.type === "nest_box" ? "\u5de3\u7bb1\u306e\u4e2d\u3067\u5bdd\u3066\u3044\u308b" : (isEasyBed ? "\u304b\u3093\u305f\u3093\u30d9\u30c3\u30c9\u3067\u5bdd\u3066\u3044\u308b" : "\u30d9\u30c3\u30c9\u3067\u5bdd\u3066\u3044\u308b")); t.startSleeping?.(bed, sleepText); return true; }, tick(t) { if (t?.state === "sleep" || t?.sleeping) return true; return basicCanStartWithTarget.call(this, t, t?.world || null, {}) ? true : false; }, }; } function createSleepBuildGrassBedActionSpec() { return { id: "sleep_build_grass_bed", need: "sleep", subNeed: "bed", state: "build", label: "\u5bdd\u308b\u5834\u6240\u304c\u306a\u3044\u306e\u3067\u304b\u3093\u305f\u3093\u30d9\u30c3\u30c9\u3092\u4f5c\u3063\u3066\u3044\u308b", phrase: "\u304b\u3093\u305f\u3093\u30d9\u30c3\u30c9\u3092\u4f5c\u3063\u305f", weight: 26, timerBacked: true, selectTarget(t, world) { return (typeof findNearbyBuildMaterial === "function" ? findNearbyBuildMaterial(world, t, "grass_bed", 520) : null) || findNearbyMaterial(world, t, "grassMaterial", 520); }, canStart(t, world, ctx = {}) { const higherPriorityPlace = typeof findPrioritySleepPlaceBeforeGrassBedBuild === "function" ? findPrioritySleepPlaceBeforeGrassBedBuild(world, t, 760) : findNearestSleepPlace(world, t, 760); return canBuildOwnedStructureByAge(t) && !higherPriorityPlace && !findOwnedStructure(world, t, "grass_bed") && !!(ctx.target ?? this.selectTarget(t, world, ctx)) && !(Number(t?.actionIdCooldowns?.sleep_build_grass_bed || 0) > 0.01) && !["fight", "panic", "intimidate", "birth_ritual"].includes(t.state); }, start(t, world) { return buildOwnedStructureFromGrass(t, world, "grass_bed", this.label); }, tick(t, world, dt) { if (findOwnedStructure(world, t, "grass_bed")) return "finished"; return continueBuildPlan(t, world, dt) ? true : false; }, }; } function createSleepAnywhereActionSpec() { return { id: "sleep_anywhere", need: "sleep", state: "sleep", label: "\u306a\u306b\u3082\u306a\u3044\u6240\u3067\u5bdd\u3066\u3044\u308b", phrase: "\u305d\u306e\u307e\u307e\u5bdd\u305f", weight: 8, timerBacked: true, canStart(t, world) { if (findNearestSleepPlace(world, t, 760)) { if (t) t.noBedNoBuildSince = NaN; return false; } const now = world?.time || 0; const failedRecently = (t?.lastFailedGrassBedBuildAt || -999) + 14 > now; const buildTarget = this.selectBuildTarget ? this.selectBuildTarget(t, world, {}) : findNearbyMaterial(world, t, "grassMaterial", 520); const canTryBuild = canBuildOwnedStructureByAge(t) && !!buildTarget && !(Number(t?.actionIdCooldowns?.sleep_build_grass_bed || 0) > 0.01); if (canTryBuild && !failedRecently) { if (t) t.noBedNoBuildSince = NaN; return false; } if (t && !Number.isFinite(t.noBedNoBuildSince)) t.noBedNoBuildSince = now; const since = Number.isFinite(t?.noBedNoBuildSince) ? t.noBedNoBuildSince : now; const waited = now - since; const urgent = (t?.energy || 100) < 18 || (t?.needRaw?.sleep || t?.needs?.sleep || 0) >= 92; return failedRecently || urgent || waited >= 6.0; }, selectBuildTarget: selectRoleTarget("grassMaterial", 520), start(t) { t.startSleeping?.(null, this.label); return true; }, tick(t) { return (t?.state === "sleep" || t?.sleeping) ? true : false; }, }; } function createRestActionSpec() { return { id: "rest_to_recover", need: "health", state: "idle", label: "\u5143\u6c17\u306b\u306a\u308b\u307e\u3067\u4f11\u3093\u3067\u3044\u308b", phrase: "\u4f11\u3093\u3060", weight: 24, canStart() { return true; }, start(t) { t.setActionState?.("idle", { target: null, reason: this.label, sleeping: false }); t.energy = clamp((t.energy || 0) + 1.6, 0, typeof tarinaiMaxEnergy === "function" ? tarinaiMaxEnergy(t) : (Number(t.maxEnergy) || 100)); return true; }, tick(t) { t.energy = clamp((t.energy || 0) + 0.8, 0, typeof tarinaiMaxEnergy === "function" ? tarinaiMaxEnergy(t) : (Number(t.maxEnergy) || 100)); return true; }, }; } function createSunbathActionSpec() { return { id: "sunbath", need: "health", subNeed: "sunbath", state: "sunbath", label: "\u65e5\u5149\u6d74\u3057\u3066\u3044\u308b", phrase: "\u65e5\u5149\u6d74\u3057\u3066\u3044\u308b", weight: 32, timerBacked: true, canStart(t, world, ctx = {}) { const healthNeed = Number(t?.needRaw?.health ?? t?.needs?.health ?? 0) || 0; return (ctx.leisure || healthNeed >= needThreshold("health", "start")) && !!t?.canStartSunbath?.({ leisure: !!ctx.leisure }); }, start(t, world, ctx = {}) { return !!t?.startSunbath?.({ leisure: !!ctx.leisure }); }, tick(t) { return (t?.sunbathTimer || 0) > 0.04 ? true : "finished"; }, finish(t) { if ((t?.sunbathTimer || 0) <= 0 && t?.state === "sunbath") t.finishSunbath?.(); return true; }, fail(t) { if (t && t.state === "sunbath") { t.sunbathTimer = 0; t.goIdle?.("\u65e5\u5149\u6d74\u3092\u3084\u3081\u305f"); } return false; }, }; } function createTemperatureComfortActionSpec() { return { id: "seek_comfort_temperature", need: "health", subNeed: "temperature", state: "seek_temperature", label: "\u5FEB\u9069\u306A\u6E29\u5EA6\u5E2F\u3078\u79FB\u52D5\u3057\u3066\u3044\u308B", phrase: "\u5FEB\u9069\u306A\u6E29\u5EA6\u5E2F\u3092\u63A2\u3057\u3066\u3044\u308B", text(t, world) { const felt = world?.feltTemperatureFor?.(t) ?? world?.temperatureAt?.(t?.x, t?.y, t) ?? t?.feltTemperature ?? t?.tempComfort ?? (CONFIG.standardTemperature ?? 15); const status = world?.temperatureStatusFor?.(felt, t) || t?.temperatureStatus || null; return status?.direction === "cold" ? "\u5BD2\u3044\u306E\u3067\u6E29\u307E\u308D\u3046\u3068\u3057\u3066\u3044\u308B\u3002" : "\u6691\u3044\u306E\u3067\u6DBC\u3082\u3046\u3068\u3057\u3066\u3044\u308B\u3002"; }, weight: 42, selectTarget(t, world, ctx = {}) { return world?.findComfortTemperatureSpot?.(t, { force: !!ctx.force, requireComfort: false }) || null; }, canStart(t, world, ctx = {}) { const felt = world?.feltTemperatureFor?.(t) ?? world?.temperatureAt?.(t.x, t.y, t); const status = world?.temperatureStatusFor?.(Number.isFinite(Number(felt)) ? felt : (t?.feltTemperature ?? CONFIG.standardTemperature ?? 15), t); if (!status || status.comfortable || (status.discomfort || 0) < 2.5) return false; return !!(ctx.target ?? this.selectTarget(t, world, ctx)); }, start(t, world, ctx = {}) { const status = world?.temperatureStatusFor?.(world?.feltTemperatureFor?.(t) ?? world?.temperatureAt?.(t.x, t.y, t) ?? t?.feltTemperature ?? (CONFIG.standardTemperature ?? 15), t); const label = status?.direction === "cold" ? "\u3042\u305F\u305F\u304B\u3044\u5834\u6240\u3078\u79FB\u52D5\u3057\u3066\u3044\u308B" : (status?.direction === "hot" ? "\u6DBC\u3057\u3044\u5834\u6240\u3078\u79FB\u52D5\u3057\u3066\u3044\u308B" : this.label); const target = ctx.target ?? this.selectTarget(t, world, ctx); return moveToOrUse(t, target, "seek_temperature", label); }, tick(t, world, dt, needs, ctx = {}) { const felt = world?.feltTemperatureFor?.(t) ?? world?.temperatureAt?.(t.x, t.y, t) ?? t?.feltTemperature ?? (CONFIG.standardTemperature ?? 15); const status = world?.temperatureStatusFor?.(felt, t); if (status?.comfortable || (status?.discomfort || 0) <= 1.5) { if (typeof applyNeedSatisfaction === "function") applyNeedSatisfaction(t, { health: 10, safety: 8 }, "temperature"); t.goIdle?.("\u5FEB\u9069\u306A\u6E29\u5EA6\u306B\u306A\u3063\u305F"); return "finished"; } const target = t.target && !t.target.dead ? t.target : (ctx.target ?? this.selectTarget(t, world, { force: true, requireComfort: false })); if (!target) return false; t.target = target; if (distXY(t.x, t.y, target.x, target.y) < Math.max(24, (t.radius || 20) * 0.9)) { const shelter = target.shelterItem && !target.shelterItem.dead ? target.shelterItem : ((target.type === "nest_box" || target.type === "pipe") ? target : null); if (shelter && (shelter.type === "nest_box" || shelter.type === "pipe")) { if (typeof t.enterNestBox === "function" && t.enterNestBox(shelter, dt, { purpose: "temperature" })) { t.thought = shelter.type === "pipe" ? "\u571f\u7ba1\u306e\u4e2d\u3067\u6c17\u6e29\u3092\u3057\u306e\u3044\u3067\u3044\u308b" : "\u5de3\u7bb1\u306e\u4e2d\u3067\u6c17\u6e29\u3092\u3057\u306e\u3044\u3067\u3044\u308b"; return true; } } const next = this.selectTarget(t, world, { force: true, requireComfort: false }); if (!next || distXY(t.x, t.y, next.x, next.y) < Math.max(28, (t.radius || 20))) return "finished"; t.target = next; } return true; }, }; } function createWanderActionSpec() { function targetFor(t, world) { const radius = rand(80, 180); return { x: clamp(t.x + Math.cos(t.wanderAngle) * radius, t.radius || 20, (world?.w || 1600) - (t.radius || 20)), y: clamp(t.y + Math.sin(t.wanderAngle) * radius, t.radius || 20, (world?.h || 900) - (t.radius || 20)), dead: false, detour: true, }; } return { id: "wander_lightly", need: "fulfill", state: "wander", label: "\u5c11\u3057\u6b69\u3044\u3066\u3044\u308b", phrase: "\u5c11\u3057\u6b69\u3044\u305f", weight: 14, canStart() { return true; }, selectTarget: targetFor, start(t, world, ctx = {}) { t.wanderAngle += rand(-1.2, 1.2); const target = ctx.target && Number.isFinite(ctx.target.x) ? ctx.target : targetFor(t, world); t.wanderTarget = target; t.setActionState?.("wander", { target, reason: this.label, sleeping: false }); return true; }, tick(t, world) { const target = t?.wanderTarget || currentBehaviorTarget(t) || null; if (!target || !Number.isFinite(target.x) || dist(t, target) <= Math.max(28, (t.radius || 20) + 10)) return "finished"; moveToOrUse(t, target, "wander", this.label); return true; }, }; } function selectFightRivalTarget(tarinai, world, range = 360) { const candidate = conflictTargetFor(tarinai, world, (tarinai?.fightMochiTimer || 0) > 0.04 || isCurrentBehaviorForced(tarinai) ? 18 : 14); const current = currentBehaviorTarget(tarinai); return isLiveTarinaiEntity(candidate?.target) ? candidate.target : (isLiveTarinaiEntity(current) ? current : nearestForcedFightTarget(tarinai, world, isCurrentBehaviorForced(tarinai) ? 760 : range)); } function createPanicEscapeActionSpec() { return { id: "panic_escape", need: "safety", subNeed: "panic", state: "panic", label: "\u6016\u304f\u3066\u9003\u3052\u3066\u3044\u308b", phrase: "\u9003\u3052\u305f", weight: 62, timerBacked: true, selectTarget(t, world) { return t.lastNeedShockBreaker || findNearbyDanger(world, t, 240) || ((t.defeatedById && world?.tarinai) ? world.liveTarinaiById?.(t.defeatedById) : null); }, canStart(t, world, ctx = {}) { const threat = ctx.target ?? this.selectTarget(t, world, ctx); const safety = Number(t?.needRaw?.safety ?? t?.needs?.safety ?? 0) || 0; // Do not start panic from ordinary safety pressure alone. Panic needs a // concrete trigger, lingering fear, defeat, or an extreme safety spike. return !!threat || (t?.defeatedTimer || 0) > 0.04 || (safety >= 92 && !!activePanicBreaker(t, world, 260)); }, start(t, world, ctx = {}) { const threat = ctx.target ?? this.selectTarget(t, world, ctx); if (threat && threat !== t) t.lastPanicThreat = threat; t.setActionState?.("panic", { target: t.panicDestination?.(threat, true), reason: this.label, wake: true, sleeping: false }); t.fearTimer = Math.max(t.fearTimer || 0, 1.6); return true; }, tick: updatePanicBehavior, }; } function createCrowdEscapeActionSpec() { return { id: "crowd_escape", need: "social", subNeed: "crowd", state: "wander", label: "\u6df7\u96d1\u304b\u3089\u5c11\u3057\u96e2\u308c\u3088\u3046\u3068\u3057\u3066\u3044\u308b", phrase: "\u6df7\u96d1\u304b\u3089\u5c11\u3057\u96e2\u308c\u305f", weight: 5, selectTarget(t, world) { return t.target?.crowdEscape ? t.target : findSocialCrowdEscapeTarget(t, world); }, canStart(t, world) { const sample = t?.socialCrowdSample || null; const now = Number(world?.time || 0) || 0; const age = sample ? now - (Number(sample.at || 0) || 0) : Infinity; const crowd = Number(t?.socialReasonParts?.crowd || 0) || 0; return age <= 3.5 && crowd >= 18 && Number(sample?.count || 0) >= Number(sample?.upper || Infinity); }, start(t, world, ctx = {}) { const target = ctx.target ?? this.selectTarget(t, world, ctx); if (!target) return false; t.setActionState?.("wander", { target, reason: SOCIAL_CROWD_ESCAPE_REASON, wake: true, sleeping: false, actionId: "crowd_escape", actionLabel: this.label, need: "social", subNeed: "crowd", }); return true; }, tick: updateCrowdEscapeBehavior, }; } function createApproachFriendActionSpec() { return { id: "approach_friend", need: "social", subNeed: "bond", state: "seek_friend", label: "\u4ef2\u9593\u306b\u8fd1\u3065\u3044\u3066\u3044\u308b", phrase: "\u4ef2\u9593\u306b\u8fd1\u3065\u3044\u305f", weight: 46, selectTarget(t, world) { return t.bestFriendLive?.(FRIEND_AFFINITY_THRESHOLD, 520) || world.nearestOther?.(t, 420) || null; }, canStart: basicCanStartWithTarget, start: startMoveToTarget("seek_friend", "\u4ef2\u9593\u306b\u8fd1\u3065\u3044\u3066\u3044\u308b"), tick(t, world, dt) { return updateSocialContactBehavior(t, world, dt, "bond"); }, }; } function createApproachFamilyActionSpec() { return { id: "approach_parent_or_child", need: "social", subNeed: "family", state: "follow_parent", label: "\u5bb6\u65cf\u306b\u8fd1\u3065\u3044\u3066\u3044\u308b", phrase: "\u5bb6\u65cf\u306b\u8fd1\u3065\u3044\u305f", weight: 28, selectTarget(t) { return t.parentToFollow?.() || null; }, canStart: basicCanStartWithTarget, start: startMoveToTarget("follow_parent", "\u5bb6\u65cf\u306b\u8fd1\u3065\u3044\u3066\u3044\u308b"), tick(t, world, dt) { return updateSocialContactBehavior(t, world, dt, "family"); }, }; } function createApproachMateActionSpec() { return { id: "approach_mate", need: "social", subNeed: "mate", state: "seek_friend", label: "\u7e41\u6b96\u3067\u304d\u308b\u76f8\u624b\u306b\u8fd1\u3065\u3044\u3066\u3044\u308b", phrase: "\u7e41\u6b96\u3067\u304d\u308b\u76f8\u624b\u306b\u8fd1\u3065\u3044\u3066\u3044\u308b", weight: 48, selectTarget(t, world) { return selectMateTarget(t, world, 520); }, canStart(t, world, ctx = {}) { return !t.juvenile && (t.reproductionTimer || 0) <= 12 && (world?.canAddTarinai?.(1) ?? true) && !!(ctx.target ?? this.selectTarget(t, world, ctx)); }, start(t, world, ctx = {}) { const other = ctx.target ?? this.selectTarget(t, world, ctx); if (!other) return false; if (dist(t, other) <= Math.max(48, (t.radius || 20) + (other.radius || 20) + 12) && world.startBirthRitual?.(t, other)) return true; return moveToOrUse(t, other, "seek_friend", this.label); }, tick: updateMateBehavior, }; } function createFightRivalActionSpec() { return { id: "fight_rival", need: "social", subNeed: "conflict", state: "seek_enemy", label: "\u6c17\u306b\u5165\u3089\u306a\u3044\u76f8\u624b\u306b\u5411\u304b\u3063\u3066\u3044\u308b", phrase: "\u55a7\u5629\u3092\u59cb\u3081\u305f", weight: 18, timerBacked: true, selectTarget(t, world) { return selectFightRivalTarget(t, world); }, canStart(t, world, ctx = {}) { if ((t.fightCooldown || 0) > 0.04 || (t.postConflictPeaceTimer || 0) > 0.04) return false; const forced = (t?.fightMochiTimer || 0) > 0.04 || isCurrentBehaviorForced(t); const candidate = conflictTargetFor(t, world, forced ? 24 : 7); if (!candidate?.target && !ctx.target) return false; return !!(ctx.target ?? candidate?.target ?? this.selectTarget(t, world, ctx)); }, start(t, world, ctx = {}) { const candidate = conflictTargetFor(t, world, (t?.fightMochiTimer || 0) > 0.04 || isCurrentBehaviorForced(t) ? 18 : 7); const rival = ctx.target ?? this.selectTarget(t, world, ctx); if (!isLiveTarinaiEntity(rival)) return false; t.conflictTargetId = rival.id; t.conflictUrge = Math.max(t.conflictUrge || 0, candidate?.score || 48); if (dist(t, rival) > Math.max(42, (t.radius || 20) + (rival.radius || 20) + 12)) return moveToOrUse(t, rival, "seek_enemy", this.label); if (candidate?.forced || isCurrentBehaviorForced(t) || (t.fightMochiTimer || 0) > 0.04 || (rival.fightMochiTimer || 0) > 0.04) return !!world.startForcedFight?.(t, rival); world.startConflict?.(t, rival); return true; }, tick: updateFightBehavior, }; } function createIntimidateEnemyActionSpec() { return { id: "intimidate_enemy", need: "social", subNeed: "conflict", state: "intimidate", label: "\u6c17\u306b\u306a\u308b\u76f8\u624b\u3092\u5a01\u5687\u3057\u3066\u3044\u308b", phrase: "\u5a01\u5687\u3057\u305f", weight: 8, timerBacked: true, selectTarget(t) { return t.recentFightRival?.(80, 180) || null; }, canStart(t, world, ctx = {}) { // \u5A01\u5687\u306F\u901A\u5E38\u306E\u6B32\u6C42\u884C\u52D5\u3068\u3057\u3066\u306F\u9078\u3070\u305A\u3001\u55A7\u5629\u5224\u5B9A\u6642\u306E30%\u5206\u5C90\u3067\u5B9F\u884C\u3059\u308B\u3002 if (!isCurrentBehaviorForced(t)) return false; if ((t.intimidateTimer || 0) > 0.04 || (t.intimidationCooldown || 0) > 0.04 || (t.postConflictPeaceTimer || 0) > 0.04) return false; const target = ctx.target ?? this.selectTarget(t, world, ctx); if (!isLiveTarinaiEntity(target) || target === t) return false; if (target?.isTarinaiChampion || (target?.intimidationCooldown || 0) > 0.04) return false; return basicCanStartWithTarget.call(this, t, world, { ...ctx, target }); }, start(t, world, ctx = {}) { const rival = ctx.target ?? this.selectTarget(t, world, ctx); if (!isLiveTarinaiEntity(rival) || rival === t || rival.isTarinaiChampion) return false; t.setActionState?.("intimidate", { target: rival, reason: this.label, sleeping: false }); t.intimidateTimer = Math.max(t.intimidateTimer || 0, 0.42); return true; }, tick(t, world) { if ((t.intimidateTimer || 0) > 0.04) return true; const rival = currentBehaviorTarget(t) || t.recentFightRival?.(80, 180); if (!isLiveTarinaiEntity(rival) || rival === t || rival.isTarinaiChampion) return "finished"; return world?.startIntimidation?.(t, rival) ? "finished" : false; }, }; } function createBirthRitualActionSpec() { return { id: "birth_ritual", need: "social", subNeed: "mate", label: "\u3078\u3053\u3078\u3053\u3057\u3066\u3044\u308b", phrase: "\u3078\u3053\u3078\u3053\u3057\u3066\u3044\u308b", weight: 0, state: "birth_ritual", timerBacked: true, canStart(t) { return (t.birthRitualTimer || 0) > 0.04; }, start() { return true; }, tick(t) { return (t.birthRitualTimer || 0) > 0.04 ? true : "finished"; }, }; } const TARINAI_ACTION_DEFINITIONS = [ createConsumableActionSpec({ id: "eat_food", subNeed: "meal", state: "seek_food", label: "\u98df\u3079\u7269\u3092\u63a2\u3057\u3066\u3044\u308b", phrase: "\u98df\u3079\u7269\u3092\u98df\u3079\u3066\u3044\u308b", weight: 62, role: "food", range: 760, }), createConsumableActionSpec({ id: "drink_water", subNeed: "water", state: "seek_water", label: "\u6c34\u3092\u63a2\u3057\u3066\u3044\u308b", phrase: "\u6c34\u3092\u98f2\u3093\u3060", weight: 24, role: "drink", range: 560, }), createSleepInBedActionSpec(), createSleepBuildGrassBedActionSpec(), createSleepAnywhereActionSpec(), createConsumableActionSpec({ id: "use_medicine", subNeed: "medicine", state: "seek_food", label: "\u5143\u6c17\u306b\u306a\u308b\u3082\u306e\u3092\u63a2\u3057\u3066\u3044\u308b", phrase: "\u5143\u6c17\u306b\u306a\u3063\u305f", weight: 34, role: "medicine", range: 620, }), createRestActionSpec(), createSunbathActionSpec(), createTemperatureComfortActionSpec(), createPanicEscapeActionSpec(), { id: "hide_at_owned_structure", need: "safety", state: "seek_bed", label: "\u81ea\u5206\u306e\u5834\u6240\u306b\u96a0\u308c\u3066\u3044\u308b", phrase: "\u81ea\u5206\u306e\u5834\u6240\u3078\u623b\u3063\u305f", weight: 30, selectTarget: selectOwnedStructure("grass_bed", 620), canStart(t, world, ctx = {}) { return !!(ctx.target ?? this.selectTarget(t, world, ctx)); }, start: startMoveToTarget("seek_bed", "\u81ea\u5206\u306e\u5834\u6240\u306b\u96a0\u308c\u3066\u3044\u308b"), }, createApproachFriendActionSpec(), createApproachFamilyActionSpec(), createApproachMateActionSpec(), createFightRivalActionSpec(), createIntimidateEnemyActionSpec(), { id: "play_seesaw", need: "fulfill", subNeed: "social_play", state: "play_seesaw", label: "\u30b7\u30fc\u30bd\u30fc\u3067\u904a\u307c\u3046\u3068\u3057\u3066\u3044\u308b", phrase: "\u4e00\u7dd2\u306b\u30b7\u30fc\u30bd\u30fc\u3067\u904a\u3093\u3060", weight: 31, timerBacked: true, selectTarget(t, world) { return globalThis.TarinaiSeesawSystem?.findAvailable?.(world, t, 620)?.item || null; }, canStart(t, world, ctx = {}) { return !!(ctx.target ?? this.selectTarget(t, world, ctx)); }, start(t, world, ctx = {}) { return Boolean(globalThis.TarinaiSeesawSystem?.start?.(t, world, ctx.target ?? this.selectTarget(t, world, ctx))); }, tick(t, world) { return globalThis.TarinaiSeesawSystem?.tickAction?.(t, world) ?? false; }, finish(t) { globalThis.TarinaiSeesawSystem?.release?.(t); return true; }, fail(t) { globalThis.TarinaiSeesawSystem?.release?.(t); return false; }, }, { id: "play", need: "fulfill", state: "play_ball", label: "\u904a\u3093\u3067\u3044\u308b", phrase: "\u904a\u3093\u3060", weight: 24, selectTarget(t, world) { return world.nearest?.(t, ["ball", "balloon"], 520) || null; }, canStart(t, world, ctx = {}) { return !!(ctx.target ?? this.selectTarget(t, world, ctx)); }, start: startMoveToTarget("play_ball", "\u904a\u3093\u3067\u3044\u308b"), }, { id: "build_grass_bed", need: "fulfill", state: "build", label: "\u304b\u3093\u305f\u3093\u30d9\u30c3\u30c9\u3092\u4f5c\u3063\u3066\u3044\u308b", phrase: "\u304b\u3093\u305f\u3093\u30d9\u30c3\u30c9\u3092\u4f5c\u3063\u305f", weight: 34, selectTarget(t, world) { return (typeof findNearbyBuildMaterial === "function" ? findNearbyBuildMaterial(world, t, "grass_bed", 520) : null) || findNearbyMaterial(world, t, "grassMaterial", 520); }, canStart(t, world, ctx = {}) { return canBuildOwnedStructureByAge(t) && !findOwnedStructure(world, t, "grass_bed") && !!(ctx.target ?? this.selectTarget(t, world, ctx)) && !["sleep", "fight", "panic", "intimidate"].includes(t.state); }, start(t, world) { return buildOwnedStructureFromGrass(t, world, "grass_bed", this.label); }, }, { id: "build_plushie", need: "fulfill", state: "build", label: "\u306c\u3044\u3050\u308b\u307f\u3092\u4f5c\u3063\u3066\u3044\u308b", phrase: "\u306c\u3044\u3050\u308b\u307f\u3092\u4f5c\u3063\u305f", weight: 28, selectTarget(t, world) { return (typeof findNearbyBuildMaterial === "function" ? findNearbyBuildMaterial(world, t, "plushie", 520) : null) || findNearbyMaterial(world, t, "grassMaterial", 520); }, canStart(t, world, ctx = {}) { return canBuildOwnedStructureByAge(t) && !findOwnedStructure(world, t, "plushie") && !!(ctx.target ?? this.selectTarget(t, world, ctx)) && !["sleep", "fight", "panic", "intimidate"].includes(t.state); }, start(t, world) { return buildOwnedStructureFromGrass(t, world, "plushie", this.label); }, }, { id: "return_owned_structure", need: "fulfill", state: "seek_bed", label: "\u81ea\u5206\u306e\u5834\u6240\u3078\u623b\u3063\u3066\u3044\u308b", phrase: "\u81ea\u5206\u306e\u5834\u6240\u3078\u623b\u3063\u305f", weight: 22, selectTarget: selectOwnedStructure("grass_bed", 620), canStart(t, world, ctx = {}) { return !!(ctx.target ?? this.selectTarget(t, world, ctx)); }, start: startMoveToTarget("seek_bed", "\u81ea\u5206\u306e\u5834\u6240\u3078\u623b\u3063\u3066\u3044\u308b"), }, { id: "use_plushie", need: "fulfill", state: "idle", label: "\u306c\u3044\u3050\u308b\u307f\u3092\u62b1\u3048\u3066\u3044\u308b", phrase: "\u306c\u3044\u3050\u308b\u307f\u3092\u62b1\u3048\u305f", weight: 18, selectTarget: selectOwnedStructure("plushie", Infinity), canStart(t, world, ctx = {}) { return !!(ctx.target ?? this.selectTarget(t, world, ctx)); }, start(t, world, ctx = {}) { const plushie = ctx.target ?? this.selectTarget(t, world, ctx); plushie?.use?.(t, world); t.setActionState?.("idle", { target: plushie, reason: this.label, sleeping: false }); return true; }, }, createBirthRitualActionSpec(), createWanderActionSpec(), ]; const TARINAI_ACTIONS = typeof registerTarinaiActionSpecs === "function" ? registerTarinaiActionSpecs(TARINAI_ACTION_DEFINITIONS) : TARINAI_ACTION_DEFINITIONS; if (typeof window !== "undefined") Object.assign(window, { TARINAI_ACTION_DEFINITIONS, TARINAI_ACTIONS });