e
This commit is contained in:
parent
f657b6a4a4
commit
d163ceb291
76 changed files with 1385 additions and 524 deletions
|
|
@ -4,16 +4,15 @@
|
|||
(function (global) {
|
||||
const World = global.World;
|
||||
if (!World) throw new Error("World is not available for mixin: world_combat_effects.js");
|
||||
const EFFECT_POOL_TYPES = new Set(["ring", "fight", "flame", "fall"]);
|
||||
const EFFECT_POOL_TYPES = new Set(["ring", "fight", "flame", "fall", "bleed", "bubble", "eat", "explosion", "heart", "shoot_impact", "zunchi_miasma", "electric_shock", "wind"]);
|
||||
const EFFECT_POOL_LIMIT_PER_TYPE = 96;
|
||||
const effectPool = new Map();
|
||||
|
||||
function acquireEffect(type, x, y, options) {
|
||||
const key = String(type || "");
|
||||
const bucket = EFFECT_POOL_TYPES.has(key) ? effectPool.get(key) : null;
|
||||
const effect = bucket?.length ? bucket.pop() : new Effect(key, x, y, options);
|
||||
if (bucket?.length >= 0) effect.reset(key, x, y, options);
|
||||
return effect;
|
||||
if (bucket?.length) return bucket.pop().reset(key, x, y, options);
|
||||
return new Effect(key, x, y, options);
|
||||
}
|
||||
|
||||
function releaseEffect(effect) {
|
||||
|
|
@ -28,7 +27,25 @@
|
|||
}
|
||||
|
||||
Object.defineProperties(World.prototype, Object.getOwnPropertyDescriptors({
|
||||
queueEffect(type, x, y, options = {}) {
|
||||
// The visual-effects toggle is a true simulation gate: when disabled,
|
||||
// do not allocate, enqueue, update, or draw transient Effect objects.
|
||||
if (global.TarinaiPerf?.visualLevel?.("effects", "high") === "off") return null;
|
||||
const opts = options || {};
|
||||
const importance = Math.max(0, Math.min(3, Number(opts.importance ?? (type === "explosion" || type === "electric_shock" || type === "bubble" || type === "heart" ? 3 : type === "ring" || type === "fall" ? 2 : 1))));
|
||||
const effect = acquireEffect(type, x, y, opts);
|
||||
effect._effectImportance = importance;
|
||||
this.effects.push(effect);
|
||||
if (global.TarinaiPerf?.diagnosticsEnabled?.() === true) {
|
||||
this._effectSpawnStats = this._effectSpawnStats || {};
|
||||
this._effectSpawnStats.requested = (this._effectSpawnStats.requested || 0) + 1;
|
||||
if (EFFECT_POOL_TYPES.has(String(type || ""))) this._effectSpawnStats.poolEligible = (this._effectSpawnStats.poolEligible || 0) + 1;
|
||||
}
|
||||
return effect;
|
||||
},
|
||||
|
||||
spawnEffect(type, x, y, options = {}) {
|
||||
if (global.TarinaiPerf?.visualLevel?.("effects", "high") === "off") return null;
|
||||
const opts = options || {};
|
||||
const importance = Math.max(0, Math.min(3, Number(opts.importance ?? (type === "explosion" || type === "electric_shock" || type === "bubble" || type === "heart" ? 3 : type === "ring" || type === "fall" ? 2 : 1))));
|
||||
if (importance <= 1 && opts.allowOffscreen !== true) {
|
||||
|
|
@ -45,15 +62,7 @@
|
|||
return null;
|
||||
}
|
||||
}
|
||||
const effect = acquireEffect(type, x, y, opts);
|
||||
effect._effectImportance = importance;
|
||||
this.effects.push(effect);
|
||||
if (global.TarinaiPerf?.diagnosticsEnabled?.() === true) {
|
||||
this._effectSpawnStats = this._effectSpawnStats || {};
|
||||
this._effectSpawnStats.requested = (this._effectSpawnStats.requested || 0) + 1;
|
||||
if (EFFECT_POOL_TYPES.has(String(type || ""))) this._effectSpawnStats.poolEligible = (this._effectSpawnStats.poolEligible || 0) + 1;
|
||||
}
|
||||
return effect;
|
||||
return this.queueEffect(type, x, y, opts);
|
||||
},
|
||||
|
||||
releaseEffect(effect) {
|
||||
|
|
@ -463,7 +472,7 @@
|
|||
if (this.addItem?.(it, "zunchi-burst")) spawned += 1;
|
||||
}
|
||||
if (!spawned) return 0;
|
||||
this.effects?.push(new Effect("zunchi_miasma", sx, sy, { size: 28, life: 0.65, color: "rgba(74,91,50,0.48)" }));
|
||||
this.queueEffect?.("zunchi_miasma", sx, sy, { size: 28, life: 0.65, color: "rgba(74,91,50,0.48)" });
|
||||
this.log?.(`${source?.name || "\u305f\u308a\u306a\u3044"}\u304b\u3089\u6e9c\u307e\u3063\u3066\u3044\u305f\u305a\u3093\u3061\u304c\u5f3e\u3051\u98db\u3093\u3060\u3002`, "accident", { participants: source?.name ? [source] : [] });
|
||||
audio.place?.("zunchi");
|
||||
this.ensureSpatial?.("zunchi-burst");
|
||||
|
|
@ -677,10 +686,13 @@
|
|||
|
||||
resolveFightOutcome(winner, loser) {
|
||||
if (!winner || !loser || winner.dead || loser.dead) return;
|
||||
const key = `${winner.id}:${loser.id}:${Math.floor(this.time / 2)}`;
|
||||
// Keep only one timestamp per directional pair. The old time-bucket key
|
||||
// created a new permanent property every two seconds for recurring fights.
|
||||
const key = `${winner.id}:${loser.id}`;
|
||||
if (!this.resolvedFightIds) this.resolvedFightIds = {};
|
||||
if (this.resolvedFightIds[key]) return;
|
||||
this.resolvedFightIds[key] = true;
|
||||
const resolvedAt = Number(this.resolvedFightIds[key]);
|
||||
if (Number.isFinite(resolvedAt) && this.time - resolvedAt < 2) return;
|
||||
this.resolvedFightIds[key] = this.time;
|
||||
winner.defeatedById = null;
|
||||
winner.defeatedTimer = 0;
|
||||
winner.fearTimer = Math.max(0, winner.fearTimer - 0.75);
|
||||
|
|
@ -797,7 +809,6 @@
|
|||
ball.amount = Math.max(ball.amount || 999, 999);
|
||||
audio.ballHit?.();
|
||||
this.spawnEffect("ring", ball.x, ball.y, { size: Math.max(16, ball.r * (0.95 + ball.pokeCombo * 0.05)), life: 0.22, color: isBalloon ? "rgba(94,188,236,0.56)" : "rgba(255,255,255,0.58)" });
|
||||
if (!isBalloon) this.log("\u30dc\u30fc\u30eb\u3092\u3064\u3064\u3044\u3066\u8ee2\u304c\u3057\u305f\u3002", "observe", { eventType: "ball_poke" });
|
||||
return true;
|
||||
},
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue