many
This commit is contained in:
parent
0b9ff1363b
commit
0a6148c73f
67 changed files with 2653 additions and 1519 deletions
30
js/ants.js
30
js/ants.js
|
|
@ -13,6 +13,15 @@ const ANT_WORKER_RETURN_WEAK_SPEED = 9.0;
|
|||
const ANT_WORKER_DRAG_SPEED = 6.1875;
|
||||
const ANT_QUEEN_SPEED = 13.5;
|
||||
|
||||
const ANT_EXTENSION_HOOKS = Object.freeze({
|
||||
nestHunger: "reserved",
|
||||
nestGrowth: "reserved",
|
||||
queenReproduction: "existing-queen-founding",
|
||||
workerLifecycle: "worker-pool-hp",
|
||||
carryingSuccessRate: "current-deterministic-haul",
|
||||
territorialBehavior: "reserved",
|
||||
});
|
||||
|
||||
function clampAntHp(v) {
|
||||
return clamp(Number(v) || 0, 0, ANT_WORKER_HP);
|
||||
}
|
||||
|
|
@ -30,6 +39,8 @@ function sanitizeAntWorkerPool(list, fallbackCount = 0) {
|
|||
|
||||
function ensureAntNestWorkerPool(nest) {
|
||||
if (!nest || nest.type !== "ant_nest") return [];
|
||||
// Extension hook: future nest hunger/growth state should attach to the nest
|
||||
// item here without changing current worker count balance.
|
||||
if (!Array.isArray(nest.antWorkers)) {
|
||||
nest.antWorkers = buildAntWorkerPool(nest.antCount ?? ANT_NEST_START_COUNT);
|
||||
} else {
|
||||
|
|
@ -150,6 +161,8 @@ class AntActor {
|
|||
}
|
||||
|
||||
chooseTarget(maxDist = 56) {
|
||||
// Extension hook: future carrying success and territorial behavior should
|
||||
// filter or rank candidates here while preserving sleep-disease hauling.
|
||||
let best = null;
|
||||
let bestScore = Infinity;
|
||||
for (const t of this.world?.tarinai || []) {
|
||||
|
|
@ -207,6 +220,8 @@ class AntActor {
|
|||
target.antDraggedBy = this.id;
|
||||
target.fearTimer = Math.max(target.fearTimer || 0, 0.55);
|
||||
target.thought = "\u30a2\u30ea\u306b\u904b\u3070\u308c\u3066\u3044\u308b";
|
||||
target.recordChangeCause?.("\u30a2\u30ea\u306b\u904b\u3070\u308c\u305f", "\u72b6\u614b");
|
||||
this.world?.emit?.("ant:grabbed", { ant: this, target });
|
||||
audio.antDrag?.();
|
||||
this.world.drawListDirty = true;
|
||||
return;
|
||||
|
|
@ -268,17 +283,21 @@ class AntActor {
|
|||
const targetWasSleeping = Boolean(target.sleeping || target.state === "sleep");
|
||||
target.antDraggedTimer = Math.max(target.antDraggedTimer || 0, 0.35);
|
||||
target.antDraggedBy = this.id;
|
||||
if (leadHauler && (this.world?.time || 0) - (this.lastCarryEventAt || -999) > 0.75) {
|
||||
this.lastCarryEventAt = this.world?.time || 0;
|
||||
this.world?.emit?.("ant:carried", { ant: this, target, lead: true, haulers });
|
||||
}
|
||||
target.target = null;
|
||||
if (targetWasSleeping) {
|
||||
target.sleeping = true;
|
||||
target.state = "sleep";
|
||||
target.sleepTimer = Math.max(target.sleepTimer || 0, 0.8);
|
||||
target.thought = "眠ったままアリに運ばれている";
|
||||
target.thought = "\u7720\u3063\u305f\u307e\u307e\u30a2\u30ea\u306b\u904b\u3070\u308c\u3066\u3044\u308b";
|
||||
} else {
|
||||
target.state = "panic";
|
||||
target.sleeping = false;
|
||||
target.fearTimer = Math.max(target.fearTimer || 0, 0.36);
|
||||
target.thought = "アリに巣へ運ばれている";
|
||||
target.thought = "\u30a2\u30ea\u306b\u5de3\u3078\u904b\u3070\u308c\u3066\u3044\u308b";
|
||||
}
|
||||
const dHome = distXY(target.x, target.y, home.x, home.y) || 1;
|
||||
if (dHome < Math.max(18, home.r * 0.66)) {
|
||||
|
|
@ -290,7 +309,8 @@ class AntActor {
|
|||
return;
|
||||
}
|
||||
const hpFactor = clamp(this.hp / ANT_WORKER_HP, 0.45, 1.0);
|
||||
const speed = ANT_WORKER_DRAG_SPEED * hpFactor;
|
||||
const haulerBoost = 1 + Math.min(0.18, Math.max(0, haulers - 1) * 0.045);
|
||||
const speed = ANT_WORKER_DRAG_SPEED * hpFactor * haulerBoost;
|
||||
const ux = (home.x - target.x) / dHome;
|
||||
const uy = (home.y - target.y) / dHome;
|
||||
if (leadHauler) {
|
||||
|
|
@ -324,6 +344,7 @@ class AntActor {
|
|||
if (this.dead) return;
|
||||
this.dead = true;
|
||||
audio.antDie?.();
|
||||
this.world?.emit?.("ant:died", { ant: this, home, reason: "hp" });
|
||||
const corpse = new Item("ant_corpse", this.x, this.y);
|
||||
corpse.amount = 24;
|
||||
corpse.workerSprite = this.workerSpriteId();
|
||||
|
|
@ -336,6 +357,8 @@ class AntActor {
|
|||
|
||||
buildNestAtFoundingSpot(force = false) {
|
||||
if (!this.world) return null;
|
||||
// Extension hook: queen reproduction currently means founding a new nest.
|
||||
// Future growth rules should branch here without changing current behavior.
|
||||
const base = new Item("ant_nest", this.foundingX, this.foundingY);
|
||||
let spot = null;
|
||||
if (this.world.findPlacementSpot) {
|
||||
|
|
@ -466,6 +489,7 @@ window.ANT_NEST_MAX_COUNT = ANT_NEST_MAX_COUNT;
|
|||
window.ANT_NEST_MAX_OUTSIDE = ANT_NEST_MAX_OUTSIDE;
|
||||
window.ANT_WORKER_HP = ANT_WORKER_HP;
|
||||
window.ANT_QUEEN_HP = ANT_QUEEN_HP;
|
||||
window.ANT_EXTENSION_HOOKS = ANT_EXTENSION_HOOKS;
|
||||
window.buildAntWorkerPool = buildAntWorkerPool;
|
||||
window.ensureAntNestWorkerPool = ensureAntNestWorkerPool;
|
||||
window.syncAntNestCount = syncAntNestCount;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue