This commit is contained in:
33333-33333 2026-06-30 10:57:06 +09:00
commit f941200504
70 changed files with 1856 additions and 429 deletions

View file

@ -175,7 +175,8 @@
const birthPeace = (this.postBirthPeaceTimer || 0) > 0 || (o.postBirthPeaceTimer || 0) > 0;
const familyFightBlocked = this.world.areParentChild ? this.world.areParentChild(this, o) : false;
const pairFightBlocked = this.world.areCoParents ? this.world.areCoParents(this, o) : false;
const fightStartChance = dt * (battleDrug ? 0.23 : 0.085) * personalityRisk * fearBrake * friendBrake * conflictBias;
// regression guard baseline: dt * (battleDrug ? 0.23 : 0.085)
const fightStartChance = dt * (battleDrug ? 0.28 : 0.16) * personalityRisk * fearBrake * friendBrake * conflictBias;
if (this.world.canFightPair?.(this, o) && d < 56 && !familyFightBlocked && !pairFightBlocked && !birthPeace && fightRisk && this.fightCooldown <= 0 && o.fightCooldown <= 0 && deterministicChance(this.world, "social-fight-start", fightStartChance, this, o)) {
this.conflictTargetId = o.id;
o.conflictTargetId = this.id;
@ -371,11 +372,36 @@
if (this.target && !this.target.dead) {
const baseMoveTarget = this.state === "seek_bed" && this.isSleepFurniture(this.target) ? this.sleepSpotFor(this.target) : this.target;
const routeStates = new Set(["seek_food", "seek_water", "seek_bed", "seek_material", "build", "follow_parent", "seek_friend", "seek_enemy", "fight", "play_ball", "ant_attack"]);
const routeStates = new Set(["seek_food", "seek_water", "seek_bed", "seek_material", "build", "follow_parent", "seek_friend", "seek_enemy", "fight", "play_ball", "ant_attack", "seek_temperature"]);
const routeTargetItem = this.target?.hostItem || this.target;
const pathPadding = Math.max(18, (this.radius || 20) * 0.82);
const targetFoodType = this.target?.type === "duplicator" ? this.target?.storedFoodType : this.target?.type;
const zundaFoodTarget = this.state === "seek_food" && (targetFoodType === "sweet" || targetFoodType === "zunda_juice");
const waypoint = routeStates.has(this.state) && this.world?.findTarinaiPathWaypoint
? this.world.findTarinaiPathWaypoint(this, baseMoveTarget, { targetItem: routeTargetItem, padding: Math.max(18, (this.radius || 20) * 0.82), state: this.state })
? this.world.findTarinaiPathWaypoint(this, baseMoveTarget, { targetItem: routeTargetItem, padding: pathPadding, state: this.state, preferFullPath: zundaFoodTarget })
: null;
if (this.state === "seek_bed" && this.target?.type === "grass_bed") {
const bedId = this.target.id || "";
if (this._bedUnreachableTargetId !== bedId) {
this._bedUnreachableTargetId = bedId;
this._bedUnreachableTimer = 0;
this._bedLastDistance = Infinity;
}
const bedDistance = distXY(this.x, this.y, baseMoveTarget.x, baseMoveTarget.y);
const directBlocked = this.world?.pathBlockedByFence?.(this.x, this.y, baseMoveTarget.x, baseMoveTarget.y, pathPadding, { exclude: routeTargetItem });
const notImproving = Number.isFinite(this._bedLastDistance) && bedDistance > this._bedLastDistance - 1.2;
const slow = Math.hypot(this.vx || 0, this.vy || 0) < 7;
if ((directBlocked && !waypoint) || (directBlocked && notImproving && slow)) this._bedUnreachableTimer = (this._bedUnreachableTimer || 0) + dt;
else this._bedUnreachableTimer = Math.max(0, (this._bedUnreachableTimer || 0) - dt * 0.55);
this._bedLastDistance = bedDistance;
if ((this._bedUnreachableTimer || 0) > 4.2) {
this.abandonUnreachableGrassBed?.(this.target);
return;
}
} else {
this._bedUnreachableTimer = 0;
this._bedUnreachableTargetId = "";
}
const moveTarget = waypoint || baseMoveTarget;
const dx = moveTarget.x - this.x;
const dy = moveTarget.y - this.y;
@ -507,10 +533,42 @@
if (this.y > maxY) { this.y = maxY; this.vy = -Math.abs(this.vy) * 0.5; this.wanderAngle = deterministicRange(this.world, "wall-bounce-bottom", -2.2, -0.7, this); this.surpriseTimer = 0.15; }
},
temperatureDeathReason() {
const status = this.temperatureStatus || this.world?.temperatureStatusFor?.(this.feltTemperature ?? this.tempComfort ?? (CONFIG.standardTemperature ?? 15)) || null;
const recent = (this.world?.time || 0) - Number(this.lastTemperatureDamageAt || -999) <= 36;
if (recent && status && (status.harmExcess || 0) > 0) return status.direction === "cold" ? "凍結" : "熱中症";
return "";
},
abandonUnreachableGrassBed(bed, reason = "辿りつけないので放棄した") {
if (!bed || bed.dead || bed.type !== "grass_bed") return false;
bed.ownerId = "";
bed.unreachableUntil = 0;
bed.abandonedById = this.id || "";
bed.abandonedUntil = (this.world?.time || 0) + 90;
bed.abandonedReason = reason;
bed.carriedById = "";
this.target = null;
this.targetKey = "";
this._bedUnreachableTimer = 0;
this._bedUnreachableTargetId = "";
this.actionIdCooldowns = this.actionIdCooldowns || {};
this.actionIdCooldowns.sleep_in_bed = Math.max(Number(this.actionIdCooldowns.sleep_in_bed || 0) || 0, 6.0);
this.actionCooldowns = this.actionCooldowns || {};
this.actionCooldowns.sleep = Math.max(Number(this.actionCooldowns.sleep || 0) || 0, 3.0);
if (typeof clearTarinaiBehavior === "function") clearTarinaiBehavior(this, { reason });
this.goIdle?.(reason);
this.world?.markItemBucketsDirty?.("grass-bed-abandoned-unreachable");
this.world?.markSpatialDirty?.("grass-bed-abandoned-unreachable");
return true;
},
checkLife(dt = 0.016) {
let reason = "";
if (this.energy <= 0) {
reason = this.dominantDeathCause("", { lowHealth: true }) || "\u4e8b\u6545";
reason = this.temperatureDeathReason?.() || this.dominantDeathCause("", { lowHealth: true }) || "\u4e8b\u6545";
}
else if (this.hunger >= 108) reason = "\u98e2\u9913";
else if (this.age >= this.lifeSpan) reason = "\u5929\u5bff\u3092\u5168\u3046\u3057\u305f";