This commit is contained in:
33333-33333 2026-06-23 22:39:20 +09:00
commit 8bd4405fe8
33 changed files with 2478 additions and 610 deletions

View file

@ -64,8 +64,6 @@
}
for (let i = 0; i < grassCount; i++) this.items.push(new Item("grass", rand(70, this.w - 70), rand(70, this.h - 70)));
this.items.push(new Item("stone", this.w * 0.68, this.h * 0.32));
this.items.push(new Item("bed", this.w * 0.82, this.h * 0.22));
this.items.push(new Item("bed", this.w * 0.18, this.h * 0.78));
this.updateItemCounts();
this.updateEffectCounts();
this.markTerrainDirty?.("reset");
@ -430,8 +428,12 @@
b.birthRitualRole = 1;
a.birthRitualLeader = true;
b.birthRitualLeader = false;
a.setActionState("birth_ritual", { target: b, reason: "近くで体をゆすっている" });
b.setActionState("birth_ritual", { target: a, reason: "近くで体をゆすっている" });
a.setActionState("birth_ritual", { target: b, reason: "繁殖の前ぶれをしている" });
b.setActionState("birth_ritual", { target: a, reason: "繁殖の前ぶれをしている" });
if (typeof setLiveActionText === "function") {
setLiveActionText(a, { need: "social", actionId: "birth_ritual", actionLabel: "繁殖の前ぶれをしている", reasonText: `${b.name || "相手"}と繁殖の前ぶれをしている`, target: b });
setLiveActionText(b, { need: "social", actionId: "birth_ritual", actionLabel: "繁殖の前ぶれをしている", reasonText: `${a.name || "相手"}と繁殖の前ぶれをしている`, target: a });
}
a.reproductionTimer = CONFIG.reproductionCooldown + rand(2, 10);
b.reproductionTimer = CONFIG.reproductionCooldown + rand(2, 10);
a.surpriseTimer = Math.max(a.surpriseTimer, 0.35);
@ -496,7 +498,7 @@
},
canStartFight(t) {
if (!t || t.dead) return false;
if (!t || t.dead || typeof t.relationTo !== "function") return false;
if (t.sleepDisease) return false;
// Disease fight rule: explosion, zunchi, and fight disease can lash out;
// sleep disease cannot fight or be challenged, and other diseases cannot start fights.
@ -508,7 +510,7 @@
},
canBeFightTarget(t) {
return Boolean(t && !t.dead && !t.sleepDisease);
return Boolean(t && !t.dead && typeof t.relationTo === "function" && !t.sleepDisease);
},
canFightPair(actor, target) {
@ -540,7 +542,7 @@
loneliness: rand(30, 56),
energy: rand(55, 95),
stress: rand(0, 14),
need: Math.random() < 0.6 ? pick([a.need, b.need]) : pick(NEEDS),
need: "",
generation: Math.max(a.generation, b.generation) + 1,
lifeSpan: rand(1500, 2200) * (childGenetics.lifeSpanMul || 1),
parents: [this.tarinaiFamilyKey(a), this.tarinaiFamilyKey(b)],
@ -628,14 +630,15 @@
startConflict(a, b) {
if (!a || !b || a.dead || b.dead) return;
if (typeof a.relationTo !== "function" || typeof b.relationTo !== "function") return;
if ((a.fightMochiTimer || 0) > 0.04 || (b.fightMochiTimer || 0) > 0.04) { this.startForcedFight(a, b); return; }
if (this.areParentChild(a, b) || this.areCoParents?.(a, b)) return;
if ((a.postBirthPeaceTimer || 0) > 0 || (b.postBirthPeaceTimer || 0) > 0) return;
if (a.fightTimer > 0.04 || b.fightTimer > 0.04 || a.intimidateTimer > 0.04 || b.intimidateTimer > 0.04) return;
const aAggressiveIntent = a.shouldApplyPersonalityBehavior?.("aggression", 1) ? 1 : 0;
const bAggressiveIntent = b.shouldApplyPersonalityBehavior?.("aggression", 1) ? 1 : 0;
const scoreA = a.energy * 0.38 + a.mood * 0.18 + a.stress * 0.12 + (a.type === "angry" ? 12 : 0) + aAggressiveIntent * 8 + ((b.relationTo(a.id).fear || 0) * 0.65) + (a.isZunchiSlave ? -10 : 0) + ((a.fightMochiTimer || 0) > 0.04 ? 9 : 0) + rand(-5, 5);
const scoreB = b.energy * 0.38 + b.mood * 0.18 + b.stress * 0.12 + (b.type === "angry" ? 12 : 0) + bAggressiveIntent * 8 + ((a.relationTo(b.id).fear || 0) * 0.65) + (b.isZunchiSlave ? -10 : 0) + ((b.fightMochiTimer || 0) > 0.04 ? 9 : 0) + rand(-5, 5);
const scoreA = a.energy * 0.38 + a.mood * 0.18 + a.stress * 0.12 + (a.type === "angry" ? 12 : 0) + aAggressiveIntent * 8 + ((typeof b.relationTo === "function" ? (b.relationTo(a.id).fear || 0) : 0) * 0.65) + (a.isZunchiSlave ? -10 : 0) + ((a.fightMochiTimer || 0) > 0.04 ? 9 : 0) + rand(-5, 5);
const scoreB = b.energy * 0.38 + b.mood * 0.18 + b.stress * 0.12 + (b.type === "angry" ? 12 : 0) + bAggressiveIntent * 8 + ((typeof a.relationTo === "function" ? (a.relationTo(b.id).fear || 0) : 0) * 0.65) + (b.isZunchiSlave ? -10 : 0) + ((b.fightMochiTimer || 0) > 0.04 ? 9 : 0) + rand(-5, 5);
const actor = scoreA >= scoreB ? a : b;
const target = actor === a ? b : a;
if (!this.canFightPair(actor, target)) return;
@ -654,7 +657,7 @@
startIntimidation(actor, target, actorScore = 0, targetScore = 0) {
if (!actor || !target || actor.dead || target.dead) return false;
if (actor.lowHealthSprite && actor.lowHealthSprite()) return false;
const fearLoad = (target.relationTo(actor.id).fear || 0) * 0.72 + target.personalityProfile().fear * 8;
const fearLoad = ((typeof target.relationTo === "function" ? (target.relationTo(actor.id).fear || 0) : 0) * 0.72) + target.personalityProfile().fear * 8;
const actorAggression = Math.max(0, actor.currentPersonality?.aggression || 0);
const targetAggression = Math.max(0, target.currentPersonality?.aggression || 0);
const actorSize = actor.effectiveScale ? actor.effectiveScale() : (actor.scale || 0.28);
@ -670,6 +673,7 @@
actor.intimidateTimer = Math.max(actor.intimidateTimer, rand(2.45, 3.35));
actor.intimidateTargetId = target.id;
actor.setActionState("intimidate", { target, reason: "相手を威嚇している" });
if (typeof setLiveActionText === "function") setLiveActionText(actor, { need: "social", subNeed: "conflict", actionId: "intimidate_enemy", actionLabel: "威嚇している", reasonText: `${target.name || "相手"}を威嚇している`, target, phase: "perform", source: "behavior" });
this.effects.push(new Effect("ring", actor.x, actor.y - actor.radius * 0.65, {
life: 0.42,
size: actor.radius * 0.55,
@ -716,6 +720,10 @@
if ((a.postBirthPeaceTimer || 0) > 0 || (b.postBirthPeaceTimer || 0) > 0) return;
a.setActionState("fight", { target: b, reason: `${b.name || "相手"}と喧嘩している` });
b.setActionState("fight", { target: a, reason: `${a.name || "相手"}と喧嘩している` });
if (typeof setLiveActionText === "function") {
setLiveActionText(a, { need: "social", subNeed: "conflict", actionId: "fight_rival", actionLabel: "喧嘩している", reasonText: `${b.name || "相手"}と喧嘩している`, target: b, phase: "perform", source: "behavior" });
setLiveActionText(b, { need: "social", subNeed: "conflict", actionId: "fight_rival", actionLabel: "喧嘩している", reasonText: `${a.name || "相手"}と喧嘩している`, target: a, phase: "perform", source: "behavior" });
}
a.fightTimer = Math.max(a.fightTimer, rand(4.5, 7.0));
b.fightTimer = Math.max(b.fightTimer, rand(4.5, 7.0));
a.nextHeadbutt = this.time + rand(0.08, 0.18);