Normalize ammo economy: per-weapon refill, stream drain, behavior fixes

- Every special weapon gets an explicit 'refill' (units per ammo pickup,
  tuned so one pickup funds ~10 kills) replacing the ammoRefillFraction
  log2 heuristic and ammoWeight overrides
- Bile Blunderbuss + The Cauterizer join Red Right Hand as time-denominated
  stream weapons ('drain' per second) instead of per-shot cost
- Sawblades ricochet through enemies (bounce fix), traps catch 3 victims,
  lobbed projectiles arc overhead and always trigger at the target point
  (Flesh Masher / Trap Queen / Swarm Jar payloads now actually deploy)
- Boss rooms stock one ammo on entry and drop one guaranteed on death
- Cauterizer burn trimmed (2.2s x2 -> 1.5s x0.8), bile acid pools trimmed
  (3.5s x1.5 -> 2.5s x0.8), Marrow Draught now covers stream drain
- New tools/ammo_sim.js calibrates every weapon into the 8-13 kills/refill
  band (all 15 pass); smoke test guards the ammo structure
- v0.3.0, cache bump v=44
This commit is contained in:
MeatSlicer Developer committed 2026-07-30 22:06:10 +10:00
1 parent 7d33e36c1e
commit d9eae34df4
18 files changed
+380 -101

No files matched your search

+9 -3
View File
@@ -82,6 +82,8 @@ function enterRoom(gx, gy) {
} else if (room.type === 'boss') {
const boss = spawnBoss(G.floor);
room.bossSpawned = true;
// boss fights are a pure ammo drain, so stock the room on the way in
spawnPickup('ammo', W / 2, H / 2 + 140);
Music.playBoss(boss.bossKind);
} else if (room.type === 'item') {
spawnItemPedestal(W / 2 - 45, H / 2, null, 'room');
@@ -239,14 +241,18 @@ function updateHazards(dt) {
}
if (h.kind === 'trap') {
for (const e of G.enemies) {
if (e.boss) continue;
if (e.boss || e.hp <= 0) continue;
if (h.caught && h.caught.has(e)) continue; // each victim springs it once
if (dist2(h.x, h.y, e.x, e.y) < (h.r + e.r) * (h.r + e.r)) {
e.rootT = 2.2;
damageEnemy(e, h.dmg, rand(0, TAU), false);
spawnBlood(e.x, e.y, 0, 6);
Sfx.trapSnap({ x: h.x, y: h.y });
G.hazards.splice(i, 1);
break;
// a trap snaps shut on a few victims before it breaks
if (!h.caught) h.caught = new Set();
h.caught.add(e);
h.charges = (h.charges === undefined ? 1 : h.charges) - 1;
if (h.charges <= 0) { G.hazards.splice(i, 1); break; }
}
}
} else if (!h.hostile || h.dps > 0) { // weapon pools hurt enemies; zero-DPS boss pools do not