stable
This commit is contained in:
parent
8bd4405fe8
commit
d5c661bc22
53 changed files with 4264 additions and 950 deletions
|
|
@ -43,15 +43,15 @@
|
|||
|
||||
colonyMoodDefinition(id = "relaxed") {
|
||||
const defs = {
|
||||
calm: { id: "calm", label: "おだやか", description: "社交性プラス", effects: { personality: { sociability: 0.42 } } },
|
||||
prickly: { id: "prickly", label: "ピリピリ", description: "攻撃性プラス", effects: { personality: { aggression: 0.46 } } },
|
||||
stinky: { id: "stinky", label: "くさい", description: "開放性マイナス", effects: { personality: { openness: -0.44 } } },
|
||||
weaklings: { id: "weaklings", label: "ざこだらけ", description: "ずんちどれい以外のストレス減少", effects: { personality: {} } },
|
||||
zunda_party: { id: "zunda_party", label: "ずんだぱーてぃー", description: "社交性と開放性プラス。ストレス減少", effects: { personality: { sociability: 0.38, openness: 0.38 } } },
|
||||
ball_party: { id: "ball_party", label: "ぼーるぱーてぃー", description: "社交性と開放性プラス。ストレス減少", effects: { personality: { sociability: 0.38, openness: 0.38 } } },
|
||||
sun_party: { id: "sun_party", label: "おひさまぱーてぃー", description: "日光浴頻度増加", effects: { personality: {} } },
|
||||
ant_overrun: { id: "ant_overrun", label: "ありだらけ", description: "アリを見るとパニック", effects: { personality: {} } },
|
||||
relaxed: { id: "relaxed", label: "のんびり", description: "何も無し", effects: { personality: {} } },
|
||||
calm: { id: "calm", label: "\u304a\u3060\u3084\u304b", description: "\u793e\u4ea4\u6027\u30d7\u30e9\u30b9", effects: { personality: { sociability: 0.42 } } },
|
||||
prickly: { id: "prickly", label: "\u30d4\u30ea\u30d4\u30ea", description: "\u653b\u6483\u6027\u30d7\u30e9\u30b9", effects: { personality: { aggression: 0.46 } } },
|
||||
stinky: { id: "stinky", label: "\u304f\u3055\u3044", description: "\u958b\u653e\u6027\u30de\u30a4\u30ca\u30b9", effects: { personality: { openness: -0.44 } } },
|
||||
weaklings: { id: "weaklings", label: "\u3056\u3053\u3060\u3089\u3051", description: "\u305a\u3093\u3061\u3069\u308c\u3044\u4ee5\u5916\u306e\u30b9\u30c8\u30ec\u30b9\u6e1b\u5c11", effects: { personality: {} } },
|
||||
zunda_party: { id: "zunda_party", label: "\u305a\u3093\u3060\u3071\u30fc\u3066\u3043\u30fc", description: "\u793e\u4ea4\u6027\u3068\u958b\u653e\u6027\u30d7\u30e9\u30b9\u3002\u30b9\u30c8\u30ec\u30b9\u6e1b\u5c11", effects: { personality: { sociability: 0.38, openness: 0.38 } } },
|
||||
ball_party: { id: "ball_party", label: "\u307c\u30fc\u308b\u3071\u30fc\u3066\u3043\u30fc", description: "\u793e\u4ea4\u6027\u3068\u958b\u653e\u6027\u30d7\u30e9\u30b9\u3002\u30b9\u30c8\u30ec\u30b9\u6e1b\u5c11", effects: { personality: { sociability: 0.38, openness: 0.38 } } },
|
||||
sun_party: { id: "sun_party", label: "\u304a\u3072\u3055\u307e\u3071\u30fc\u3066\u3043\u30fc", description: "\u65e5\u5149\u6d74\u983b\u5ea6\u5897\u52a0", effects: { personality: {} } },
|
||||
ant_overrun: { id: "ant_overrun", label: "\u3042\u308a\u3060\u3089\u3051", description: "\u30a2\u30ea\u3092\u898b\u308b\u3068\u30d1\u30cb\u30c3\u30af", effects: { personality: {} } },
|
||||
relaxed: { id: "relaxed", label: "\u306e\u3093\u3073\u308a", description: "\u4f55\u3082\u7121\u3057", effects: { personality: {} } },
|
||||
};
|
||||
return defs[id] || defs.relaxed;
|
||||
},
|
||||
|
|
@ -76,7 +76,7 @@
|
|||
const nextId = candidates.length ? candidates[Math.floor(Math.random() * candidates.length)] : "relaxed";
|
||||
this.colonyMood = this.colonyMoodDefinition(nextId);
|
||||
this.lastColonyMoodDay = this.day || 1;
|
||||
this.log?.(`今日のコロニーの雰囲気は「${this.colonyMood.label}」。`, "event");
|
||||
this.log?.(`\u4eca\u65e5\u306e\u30b3\u30ed\u30cb\u30fc\u306e\u96f0\u56f2\u6c17\u306f\u300c${this.colonyMood.label}\u300d\u3002`, "event");
|
||||
return this.colonyMood;
|
||||
},
|
||||
|
||||
|
|
@ -86,12 +86,47 @@
|
|||
const tFamilyKey = this.tarinaiFamilyKey(t);
|
||||
if ((s.parents || []).includes(tFamilyKey)) return "parent";
|
||||
if ((s.children || []).includes(tFamilyKey)) return "child";
|
||||
const friendThreshold = typeof FRIEND_AFFINITY_THRESHOLD === "number" ? FRIEND_AFFINITY_THRESHOLD : 14;
|
||||
const rel = s.relationTo ? s.relationTo(t.id) : null;
|
||||
if (rel && (rel.affinity || 0) >= FRIEND_AFFINITY_THRESHOLD) return "friend";
|
||||
if (rel && (rel.fear || 0) >= 8) return "enemy";
|
||||
const reverse = t.relationTo ? t.relationTo(s.id) : null;
|
||||
if ((rel && (rel.affinity || 0) >= friendThreshold) || (reverse && (reverse.affinity || 0) >= friendThreshold)) return "friend";
|
||||
if ((rel && (rel.fear || 0) >= 8) || (reverse && (reverse.fear || 0) >= 8)) return "enemy";
|
||||
return "";
|
||||
},
|
||||
|
||||
resolveOwnedBedSleepConflicts() {
|
||||
const alive = (this.tarinai || []).filter(t => t && !t.dead);
|
||||
if (alive.length < 2) return 0;
|
||||
const friendThreshold = typeof FRIEND_AFFINITY_THRESHOLD === "number" ? FRIEND_AFFINITY_THRESHOLD : 14;
|
||||
const isFriendPair = (a, b) => {
|
||||
const relAB = a?.relationTo ? a.relationTo(b?.id) : null;
|
||||
const relBA = b?.relationTo ? b.relationTo(a?.id) : null;
|
||||
return Boolean((relAB && (relAB.affinity || 0) >= friendThreshold) || (relBA && (relBA.affinity || 0) >= friendThreshold));
|
||||
};
|
||||
const bedSleepers = new Map();
|
||||
for (const sleeper of alive) {
|
||||
if (!(sleeper.sleeping || sleeper.state === "sleep")) continue;
|
||||
const bed = sleeper.target;
|
||||
if (!bed || bed.dead || bed.type !== "grass_bed") continue;
|
||||
if (distXY(sleeper.x, sleeper.y, bed.x, bed.y) > Math.max((bed.r || 18) * 1.55, 32)) continue;
|
||||
if (!bedSleepers.has(bed.id)) bedSleepers.set(bed.id, []);
|
||||
bedSleepers.get(bed.id).push(sleeper);
|
||||
}
|
||||
let conflicts = 0;
|
||||
for (const intruder of alive) {
|
||||
if (!(intruder.state === "seek_bed" || intruder.state === "sleep")) continue;
|
||||
const bed = intruder.target;
|
||||
if (!bed || bed.dead || bed.type !== "grass_bed") continue;
|
||||
const sleepers = bedSleepers.get(bed.id) || [];
|
||||
if (!sleepers.length) continue;
|
||||
if (distXY(intruder.x, intruder.y, bed.x, bed.y) > Math.max((bed.r || 18) * 2.2, 54)) continue;
|
||||
const defender = sleepers.find(other => other && other !== intruder && !this.areParentChild?.(intruder, other) && !isFriendPair(intruder, other));
|
||||
if (!defender) continue;
|
||||
if (this.startForcedFight?.(defender, intruder)) conflicts += 1;
|
||||
}
|
||||
return conflicts;
|
||||
},
|
||||
|
||||
nestBoxOccupants(box, limit = 5) {
|
||||
if (!box || box.dead || box.type !== "nest_box") return [];
|
||||
const occupants = this.tarinai.filter(t => t && !t.dead && t.insideNestBoxId === box.id);
|
||||
|
|
@ -188,24 +223,30 @@
|
|||
this.updateWeather(dt);
|
||||
this.foodSpoilagePenalty = Math.max(0, (this.foodSpoilagePenalty || 0) - dt * 0.010);
|
||||
this.updateTerrainDirtyState?.(dt);
|
||||
this.rebuildSpatial();
|
||||
this.spatialRebuildsThisFrame = 0;
|
||||
this.spatialDirtyMarksThisFrame = 0;
|
||||
this.ensureSpatial?.("update-start");
|
||||
|
||||
const perf = this.performanceLevel();
|
||||
const itemCountBefore = this.items.length;
|
||||
for (const it of this.items) it.update(dt, this);
|
||||
if (this.items.length) this.markSpatialDirty?.("items-updated");
|
||||
if (this.itemCounts?.ball) {
|
||||
this.rebuildSpatial();
|
||||
this.ensureSpatial?.("ball-ball-collisions");
|
||||
this.resolveBallBallCollisions(dt);
|
||||
this.rebuildSpatial();
|
||||
this.markSpatialDirty?.("ball-ball-collisions");
|
||||
}
|
||||
this.updateAnts?.(dt);
|
||||
if ((this.ants || []).length) this.markSpatialDirty?.("ants-updated");
|
||||
|
||||
for (const ef of this.effects) ef.update(dt);
|
||||
|
||||
for (const t of this.tarinai) {
|
||||
t.update(dt);
|
||||
}
|
||||
this.rebuildSpatial();
|
||||
this.resolveOwnedBedSleepConflicts?.();
|
||||
if (this.tarinai.length) this.markSpatialDirty?.("tarinai-updated");
|
||||
this.ensureSpatial?.("post-tarinai-update");
|
||||
this.limitBallChasers();
|
||||
this.resolveBallInteractions(dt);
|
||||
this.resolveTarinaiHighSpeedCollisions(dt);
|
||||
|
|
@ -259,7 +300,7 @@
|
|||
|
||||
|
||||
const grassCount = this.itemCounts.grass || 0;
|
||||
if (grassCount < Math.min(54, this.grassLimit ? this.grassLimit() : (CONFIG.grassLimit ?? 180)) && Math.random() < dt * 0.082) {
|
||||
if (grassCount < Math.min(108, this.grassLimit ? this.grassLimit() : (CONFIG.grassLimit ?? 360)) && Math.random() < dt * 0.109) {
|
||||
const spot = this.findGrassPlantingSpot(rand(60, this.w - 60), rand(60, this.h - 60), {
|
||||
allowOriginal: true,
|
||||
minRadius: 28,
|
||||
|
|
@ -270,9 +311,7 @@
|
|||
const sprout = new Item("grass", spot.x, spot.y);
|
||||
sprout.amount = rand(30, 62);
|
||||
sprout.growth = rand(0.18, 0.38);
|
||||
this.items.push(sprout);
|
||||
this.itemCounts.grass = grassCount + 1;
|
||||
this.markTerrainDirty?.("grass-spawn");
|
||||
this.addItem?.(sprout, "grass-spawn") || this.items.push(sprout);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -281,12 +320,12 @@
|
|||
// share the rain overlay renderer.
|
||||
if (window.TarinaiWeatherSystem?.shouldDropRainWater?.(this, dt)) {
|
||||
const drop = window.TarinaiWeatherSystem.createRainWaterItem(this);
|
||||
this.items.push(drop);
|
||||
this.itemCounts.water = (this.itemCounts.water || 0) + 1;
|
||||
this.markTerrainDirty?.("rain-water");
|
||||
this.addItem?.(drop, "rain-water") || this.items.push(drop);
|
||||
this.emit?.("rain:itemDropped", { item: drop, type: "water" });
|
||||
}
|
||||
|
||||
this.lastRuntimeDiagnostics = this.runtimeDiagnostics?.() || null;
|
||||
|
||||
},
|
||||
|
||||
sanitizeOutOfBounds() {
|
||||
|
|
@ -360,7 +399,8 @@
|
|||
if (changedItems) {
|
||||
this.compactItems();
|
||||
this.updateItemCounts();
|
||||
this.rebuildSpatial();
|
||||
this.markSpatialDirty?.("sanitize-out-of-bounds");
|
||||
this.ensureSpatial?.("sanitize-out-of-bounds");
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue