This commit is contained in:
33333-33333 2026-06-20 21:41:15 +09:00
commit 10fbeb2327
18 changed files with 794 additions and 16 deletions

View file

@ -58,6 +58,20 @@ class Item {
this.freshness = 1;
this.zunchiVariant = stableUnit(this.id, "zunchi-variant") < 0.5 ? "zunchi" : "zunchi_02";
}
if (type === "ant_nest") {
this.antCount = ANT_NEST_START_COUNT || 6;
this.antSpawnTimer = rand(0.6, 2.2);
this.antSpawnCooldown = rand(0.8, 2.4);
this.antWorkers = typeof buildAntWorkerPool === "function"
? buildAntWorkerPool(this.antCount)
: Array.from({ length: this.antCount }, () => ANT_WORKER_HP || 32);
this.queenSpawnAt = -999;
}
if (type === "ant_corpse") {
this.amount = 24;
this.workerSprite = "ant_worker";
this.decayTimer = 0;
}
if (type === "firecracker") {
this.fuseTimer = 5;
this.fuseMax = 5;
@ -84,6 +98,7 @@ class Item {
if (["sweet", "love_mochi", "fight_mochi", "sleep_drug"].includes(this.type) && !Number.isFinite(this.foodServingsRemaining)) this.amount -= dt * 0.12;
if (this.type === "trace") this.amount -= dt * 1.35;
if (this.type === "splat") this.amount -= dt * 1.05;
if (this.type === "ant_corpse") this.amount -= dt * 0.018;
if (this.type === "firecracker") {
this.fuseTimer = Math.max(0, (this.fuseTimer ?? 5) - dt);
if (this.fuseTimer <= 0) {
@ -460,7 +475,8 @@ class Item {
comfort: this.comfort, wear: this.wear, crawlOpen: this.crawlOpen, zunchiVariant: this.zunchiVariant, toolSize: this.toolSize, foodServingScale: this.foodServingScale, foodServingsMax: this.foodServingsMax, foodServingsRemaining: this.foodServingsRemaining, blastScale: this.blastScale, fuseTimer: this.fuseTimer, fuseMax: this.fuseMax, dropTimer: this.dropTimer, dropMax: this.dropMax,
vx: this.vx, vy: this.vy, prevX: this.prevX, prevY: this.prevY,
spin: this.spin, spinVelocity: this.spinVelocity, lastKickedAt: this.lastKickedAt, lastKickerId: this.lastKickerId,
lastPokedAt: this.lastPokedAt, pokeCombo: this.pokeCombo, lastPokeAngle: this.lastPokeAngle
lastPokedAt: this.lastPokedAt, pokeCombo: this.pokeCombo, lastPokeAngle: this.lastPokeAngle,
antCount: this.antCount, antSpawnTimer: this.antSpawnTimer, antSpawnCooldown: this.antSpawnCooldown, antWorkers: Array.isArray(this.antWorkers) ? this.antWorkers.slice() : undefined, queenSpawnAt: this.queenSpawnAt, workerSprite: this.workerSprite, decayTimer: this.decayTimer
};
}
static from(o) {
@ -511,6 +527,22 @@ class Item {
it.freshness = 1;
it.zunchiVariant = "zunchi";
}
if (type === "ant_nest") {
it.antCount = Number.isFinite(o.antCount) ? clamp(Math.round(o.antCount), 0, ANT_NEST_MAX_COUNT || 10) : (ANT_NEST_START_COUNT || 6);
it.antSpawnTimer = o.antSpawnTimer ?? rand(0.6, 2.2);
it.antSpawnCooldown = o.antSpawnCooldown ?? rand(0.8, 2.4);
const legacyPool = Array.isArray(o.antWorkers) ? o.antWorkers : (Array.isArray(o.workerHpPool) ? o.workerHpPool : null);
it.antWorkers = Array.isArray(legacyPool)
? legacyPool.map(v => clamp(Number(v) || ANT_WORKER_HP || 32, 0.1, ANT_WORKER_HP || 32)).slice(0, ANT_NEST_MAX_COUNT || 10)
: (typeof buildAntWorkerPool === "function"
? buildAntWorkerPool(it.antCount)
: Array.from({ length: it.antCount }, () => ANT_WORKER_HP || 32));
it.queenSpawnAt = Number.isFinite(o.queenSpawnAt) ? o.queenSpawnAt : -999;
}
if (type === "ant_corpse") {
it.workerSprite = o.workerSprite || "ant_worker";
it.decayTimer = o.decayTimer || 0;
}
if (type === "firecracker") {
it.fuseTimer = 5;
it.fuseMax = 5;
@ -541,6 +573,22 @@ class Item {
it.pokeCombo = o.pokeCombo ?? it.pokeCombo ?? 0;
it.lastPokeAngle = o.lastPokeAngle ?? it.lastPokeAngle ?? rand(0, Math.PI * 2);
it.zunchiVariant = o.zunchiVariant || it.zunchiVariant || "zunchi";
it.antCount = Number.isFinite(o.antCount) ? clamp(Math.round(o.antCount), 0, ANT_NEST_MAX_COUNT || 10) : it.antCount;
it.antSpawnTimer = o.antSpawnTimer ?? it.antSpawnTimer;
it.antSpawnCooldown = o.antSpawnCooldown ?? it.antSpawnCooldown;
if (type === "ant_nest") {
const legacyPool = Array.isArray(o.antWorkers) ? o.antWorkers : (Array.isArray(o.workerHpPool) ? o.workerHpPool : null);
if (Array.isArray(legacyPool)) {
it.antWorkers = legacyPool.map(v => clamp(Number(v) || 0, 0, ANT_WORKER_HP || 32)).filter(v => v > 0).slice(0, ANT_NEST_MAX_COUNT || 10);
} else if (!Array.isArray(it.antWorkers)) {
it.antWorkers = typeof buildAntWorkerPool === "function"
? buildAntWorkerPool(it.antCount || (ANT_NEST_START_COUNT || 6))
: Array.from({ length: it.antCount || (ANT_NEST_START_COUNT || 6) }, () => ANT_WORKER_HP || 32);
}
it.queenSpawnAt = Number.isFinite(o.queenSpawnAt) ? o.queenSpawnAt : (it.queenSpawnAt ?? -999);
}
it.workerSprite = o.workerSprite || it.workerSprite;
it.decayTimer = o.decayTimer ?? it.decayTimer;
it.toolSize = o.toolSize || it.toolSize || "medium";
it.foodServingScale = o.foodServingScale || it.foodServingScale || ({ small: 0.68, medium: 1.0, large: 1.48 }[it.toolSize] || 1);
if (isServingFoodType(it.type)) {
@ -779,6 +827,49 @@ class Item {
ctx.ellipse(randSeed(this.seed + i, -this.r * 0.84, this.r * 0.84), randSeed(this.seed + 20 + i, this.r * 0.32, this.r * 0.68), this.r * 0.26, this.r * 0.045, randSeed(this.seed + 40 + i, -0.7, 0.7), 0, Math.PI * 2);
ctx.fill();
}
} else if (this.type === "ant_nest") {
const count = clamp(Math.round(this.antCount ?? ANT_NEST_START_COUNT ?? 6), 0, ANT_NEST_MAX_COUNT ?? 10);
ctx.fillStyle = styleNight ? "#5e4634" : (styleWarm ? "#956b42" : "#77583a");
ctx.strokeStyle = styleNight ? "rgba(43,32,26,0.78)" : "rgba(72,48,31,0.72)";
ctx.lineWidth = 2.2;
ctx.beginPath();
ctx.ellipse(0, 8, this.r * 1.35, this.r * 0.78, 0.08, 0, Math.PI * 2);
ctx.fill(); ctx.stroke();
ctx.fillStyle = styleNight ? "#211a17" : "#30231d";
ctx.beginPath();
ctx.ellipse(0, 2, this.r * 0.58, this.r * 0.36, 0, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = "rgba(38,37,35,0.88)";
for (let i = 0; i < Math.min(6, count); i++) {
const ax = randSeed(this.seed + i * 11, -this.r * 1.0, this.r * 1.0);
const ay = randSeed(this.seed + i * 17, -this.r * 0.45, this.r * 0.55);
ctx.beginPath();
ctx.ellipse(ax, ay, 3.4, 2.1, randSeed(this.seed + i * 23, -0.8, 0.8), 0, Math.PI * 2);
ctx.fill();
}
ctx.fillStyle = "rgba(255,248,220,0.82)";
ctx.font = "bold 10px ui-rounded, sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(`${count}`, 0, this.r * 1.25);
} else if (this.type === "ant_corpse") {
const img = typeof getRenderableImage === "function" ? getRenderableImage("ant_worker", "ant_worker") : images.get("ant_worker");
ctx.save();
ctx.rotate((stableUnit(this.id || this.seed, "ant-corpse-rot") - 0.5) * 0.26);
ctx.scale(1, -1);
ctx.globalAlpha *= clamp((this.amount || 0) / 24, 0.35, 1);
if (img) {
const w = this.r * 3.9;
const metrics = getImageMetrics("ant_worker");
const h = w * (metrics?.ratio || 0.52);
ctx.drawImage(img, -w * 0.5, -h * 0.55, w, h);
} else {
ctx.fillStyle = "rgba(42,39,35,0.85)";
ctx.beginPath();
ctx.ellipse(0, 0, this.r * 1.35, this.r * 0.72, 0, 0, Math.PI * 2);
ctx.fill();
}
ctx.restore();
} else if (this.type === "ball") {
const speed = Math.hypot(this.vx || 0, this.vy || 0);
const moving = clamp(speed / 260, 0, 1);