y
This commit is contained in:
parent
61718e2981
commit
f657b6a4a4
94 changed files with 3970 additions and 1241 deletions
|
|
@ -127,7 +127,7 @@ function inheritedChampionPersonality(seed = "", parents = [], opts = {}) {
|
|||
const p = worldRef.pointer;
|
||||
if (!p?.inside) return null;
|
||||
let best = null, bestD = Infinity;
|
||||
for (const it of worldRef.nearbyItems(p.x, p.y, 140)) {
|
||||
for (const it of worldRef.nearbyNonGrassItems?.(p.x, p.y, 140) || worldRef.nearbyItems?.(p.x, p.y, 140) || []) {
|
||||
if (!it || it.dead || it.type !== "grass_bed") continue;
|
||||
const d = distXY(p.x, p.y, it.x, it.y);
|
||||
if (d < bestD && d <= Math.max(60, (it.r || 24) * 2.0)) { best = it; bestD = d; }
|
||||
|
|
@ -152,6 +152,7 @@ function inheritedChampionPersonality(seed = "", parents = [], opts = {}) {
|
|||
this.setViewportSize(this.viewportW, this.viewportH);
|
||||
this.time = 0;
|
||||
this.day = 1;
|
||||
this.elapsedDays = 0;
|
||||
this.paused = false;
|
||||
this.speed = 1;
|
||||
this.toolSize = this.toolSize || "medium";
|
||||
|
|
@ -181,12 +182,19 @@ function inheritedChampionPersonality(seed = "", parents = [], opts = {}) {
|
|||
this.nextWeatherChange = rand(CONFIG.weatherChangeMin, CONFIG.weatherChangeMax);
|
||||
global.TarinaiAchievements?.resetWorldProgress?.(this);
|
||||
|
||||
generatePresetWorld(this, field, preset, seedPopulation);
|
||||
this._suspendAchievementEvents = true;
|
||||
try {
|
||||
generatePresetWorld(this, field, preset, seedPopulation);
|
||||
} finally {
|
||||
this._suspendAchievementEvents = false;
|
||||
}
|
||||
|
||||
this.rebuildTarinaiCountCache?.("reset");
|
||||
this.updateItemCounts();
|
||||
this.enforceGrassLimit?.("reset-grass-limit");
|
||||
this.updateItemCounts();
|
||||
this.updateEffectCounts();
|
||||
global.TarinaiAchievements?.evaluateEvent?.(this, "restore", { source: "reset" });
|
||||
this.markTerrainDirty?.("reset");
|
||||
this.rebuildSpatial(true);
|
||||
const label = resetPresetLabel(preset);
|
||||
|
|
@ -514,18 +522,55 @@ function inheritedChampionPersonality(seed = "", parents = [], opts = {}) {
|
|||
if (opts.normalize !== false) this.normalizeFamily();
|
||||
const family = this.family || {};
|
||||
const nodes = Object.values(family).filter(Boolean).filter(n => n.hasPaired || (n.parents || []).length || (n.children || []).length);
|
||||
if (!nodes.length) return;
|
||||
if (!nodes.length) return false;
|
||||
const components = globalThis.TarinaiFamilyGraph.connectedComponents
|
||||
? globalThis.TarinaiFamilyGraph.connectedComponents(nodes)
|
||||
: [];
|
||||
const remove = components.length
|
||||
? components.filter(comp => !comp.some(n => family[n.id]?.alive)).flat().map(n => n.id)
|
||||
: [];
|
||||
if (!remove.length) return;
|
||||
const remove = new Set();
|
||||
for (const component of components) {
|
||||
const members = component.map(n => family[n.id]).filter(Boolean);
|
||||
if (!members.length) continue;
|
||||
if (!members.some(n => n.alive)) {
|
||||
for (const n of members) remove.add(n.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prune generation-by-generation inside each family component. A fully
|
||||
// dead generation may disappear only when there is no living older
|
||||
// generation above it. This preserves the visible lineage of surviving
|
||||
// ancestors while allowing extinct leading generations to be discarded.
|
||||
const oldestLivingGeneration = Math.min(...members.filter(n => n.alive).map(n => Math.max(1, Number(n.generation) || 1)));
|
||||
const byGeneration = new Map();
|
||||
for (const n of members) {
|
||||
const generation = Math.max(1, Number(n.generation) || 1);
|
||||
if (!byGeneration.has(generation)) byGeneration.set(generation, []);
|
||||
byGeneration.get(generation).push(n);
|
||||
}
|
||||
for (const generation of Array.from(byGeneration.keys()).sort((a, b) => a - b)) {
|
||||
if (generation >= oldestLivingGeneration) break;
|
||||
const generationMembers = byGeneration.get(generation) || [];
|
||||
if (generationMembers.length && generationMembers.every(n => !n.alive)) {
|
||||
for (const n of generationMembers) remove.add(n.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!remove.size) return false;
|
||||
for (const id of remove) delete family[id];
|
||||
const known = new Set(Object.keys(family));
|
||||
for (const n of Object.values(family)) {
|
||||
n.parents = Array.from(new Set((n.parents || []).filter(id => known.has(id))));
|
||||
n.children = Array.from(new Set((n.children || []).filter(id => known.has(id))));
|
||||
}
|
||||
for (const t of this.tarinai || []) {
|
||||
if (!t || t.dead) continue;
|
||||
t.parents = Array.from(new Set((t.parents || []).filter(id => known.has(id))));
|
||||
t.children = Array.from(new Set((t.children || []).filter(id => known.has(id))));
|
||||
}
|
||||
this.familyVersion = (this.familyVersion || 0) + 1;
|
||||
this.markFamilyTreeDirty("family-prune");
|
||||
this.markFamilyTreeDirty("family-generation-prune");
|
||||
this.familyCleanVersion = this.familyVersion || 0;
|
||||
return true;
|
||||
},
|
||||
|
||||
addTarinai(opts = {}) {
|
||||
|
|
@ -566,6 +611,8 @@ function inheritedChampionPersonality(seed = "", parents = [], opts = {}) {
|
|||
}
|
||||
this.assignTarinaiLiveId(t);
|
||||
this.tarinai.push(t);
|
||||
this.syncTarinaiCountEntry?.(t);
|
||||
if (!this._suspendAchievementEvents) global.TarinaiAchievements?.evaluateEvent?.(this, "population", { tarinai: t, delta: 1, reason: "add-tarinai" });
|
||||
this.drawListDirty = true;
|
||||
if (t.hasPaired || (t.parents || []).length || (t.children || []).length) this.recordFamily(t);
|
||||
this.maxGeneration = Math.max(this.maxGeneration, t.generation);
|
||||
|
|
@ -580,7 +627,7 @@ function inheritedChampionPersonality(seed = "", parents = [], opts = {}) {
|
|||
const p = this.pointer;
|
||||
if (!p?.inside) return null;
|
||||
let best = null, bestD = Infinity;
|
||||
for (const it of this.nearbyItems(p.x, p.y, 140)) {
|
||||
for (const it of this.nearbyNonGrassItems?.(p.x, p.y, 140) || this.nearbyItems?.(p.x, p.y, 140) || []) {
|
||||
if (!it || it.dead || !globalThis.TarinaiToolRuntime?.isNestContainerItem?.(it)) continue;
|
||||
const d = distXY(p.x, p.y, it.x, it.y);
|
||||
if (d < bestD && d <= Math.max(80, it.r * 2.1)) { best = it; bestD = d; }
|
||||
|
|
@ -970,11 +1017,11 @@ function inheritedChampionPersonality(seed = "", parents = [], opts = {}) {
|
|||
target.fearTimer = Math.max(target.fearTimer || 0, 0.72 * targetProfile.fear);
|
||||
actor.adjustRelation(target, -0.05, 0.06, "intimidate");
|
||||
target.adjustRelation(actor, -0.12, 0.30 * targetProfile.fear, "intimidate");
|
||||
this.effects.push(new Effect("ring", actor.x, actor.y - actor.radius * 0.65, {
|
||||
this.spawnEffect("ring", actor.x, actor.y - actor.radius * 0.65, {
|
||||
life: 0.34,
|
||||
size: actor.radius * 0.62,
|
||||
color: "rgba(154, 88, 42, 0.74)",
|
||||
}));
|
||||
});
|
||||
this.spawnBubble(actor.x, actor.y - actor.radius * 1.30, "!", "rgba(120,62,38,0.82)");
|
||||
return true;
|
||||
},
|
||||
|
|
@ -1033,11 +1080,11 @@ function inheritedChampionPersonality(seed = "", parents = [], opts = {}) {
|
|||
actor.intimidateTargetId = target.id;
|
||||
actor.setActionState("intimidate", { target, reason: "\u76f8\u624b\u3092\u5a01\u5687\u3057\u3066\u3044\u308b" });
|
||||
setBehaviorText(actor, { need: "social", subNeed: "conflict", actionId: "intimidate_enemy", actionLabel: "\u5a01\u5687\u3057\u3066\u3044\u308b", reasonText: `${target.name || "\u76f8\u624b"}\u3092\u5a01\u5687\u3057\u3066\u3044\u308b`, target, phase: "perform", source: "behavior" });
|
||||
this.effects.push(new Effect("ring", actor.x, actor.y - actor.radius * 0.65, {
|
||||
this.spawnEffect("ring", actor.x, actor.y - actor.radius * 0.65, {
|
||||
life: 0.42,
|
||||
size: actor.radius * 0.55,
|
||||
color: "rgba(145, 106, 55, 0.70)",
|
||||
}));
|
||||
});
|
||||
this.spawnBubble(actor.x, actor.y - actor.radius * 1.30, "\u306f\u3046\u30fc\uff01", "rgba(92,62,34,0.82)");
|
||||
target.intimidatedTimer = Math.max(target.intimidatedTimer || 0, deterministicRange(this, "intimidation-target-prep-timer", 0.28, 0.52, actor, target));
|
||||
target.fearTimer = Math.max(target.fearTimer, 0.65 * targetProfile.fear);
|
||||
|
|
@ -1129,11 +1176,11 @@ function inheritedChampionPersonality(seed = "", parents = [], opts = {}) {
|
|||
a.vx -= dx / d * deterministicRange(this, "fight-pulse-knockback-ax", 32, 62, a, b); a.vy -= dy / d * deterministicRange(this, "fight-pulse-knockback-ay", 32, 62, a, b);
|
||||
b.vx += dx / d * deterministicRange(this, "fight-pulse-knockback-bx", 32, 62, a, b); b.vy += dy / d * deterministicRange(this, "fight-pulse-knockback-by", 32, 62, a, b);
|
||||
a.surpriseTimer = 0.24; b.surpriseTimer = 0.24;
|
||||
this.effects.push(new Effect("fight", (a.x + b.x) / 2, (a.y + b.y) / 2 - 8, {
|
||||
this.spawnEffect("fight", (a.x + b.x) / 2, (a.y + b.y) / 2 - 8, {
|
||||
size: deterministicRange(this, "fight-pulse-effect-size", 12, 20, a, b),
|
||||
life: deterministicRange(this, "fight-pulse-effect-life", 0.32, 0.52, a, b),
|
||||
color: "rgba(116, 73, 38, 0.82)",
|
||||
}));
|
||||
});
|
||||
audio.fight();
|
||||
if (this.time - Math.max(a.lastLog, b.lastLog) > 6) {
|
||||
this.log(`${a.name}\u3068${b.name}\u304c\u5c0f\u3055\u306a\u55a7\u5629\u3092\u3057\u305f\u3002`, "fight", { participants: [a, b], sound: false });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue