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

+4 -12
View File
@@ -16,17 +16,9 @@ function spawnGems(x, y, value) {
}
// Ammo drops preserve useful trigger time: low-damage rapid weapons receive
// a larger share, while heavy multi-pellet shots receive fewer rounds.
function ammoRefillFraction(w) {
const effectiveDamage = Math.max(1, (w.dmg || 1) * (w.pellets || 1));
const interval = Math.max(0.05, w.interval ?? 0.3);
const damageWeight = Math.log2(effectiveDamage / 8);
const rateWeight = Math.log2(interval / 0.3);
// Heavy, slow attacks push the fraction down; light, rapid attacks push it up.
const heaviness = clamp((damageWeight + rateWeight) / 4, -1, 1);
return clamp(0.62 - heaviness * 0.28, 0.30, 0.88) * (w.ammoWeight || 1) * AMMO_REFILL_SCALE;
}
// Ammo pickups hand back each weapon's authored `refill` (see WEAPONS), tuned
// so one pickup funds roughly ten kills. Magazine size (`ammo`) is a separate
// feel dial; the economy dial lives on `refill`.
// room-clear reward burst (weapons come from bosses / item rooms, not room clears)
function spawnRoomReward(x, y, floor) {
@@ -87,7 +79,7 @@ function collectPickup(k) {
for (const inst of carried) {
const def = WEAPONS[inst.id];
const cap = def.ammo * 1.5;
const wanted = Math.max(1, Math.ceil(def.ammo * ammoRefillFraction(def) * p.stats.ammoPickupMul));
const wanted = Math.max(1, Math.ceil((def.refill || 1) * p.stats.ammoPickupMul));
const add = Math.max(0, Math.min(wanted, cap - inst.ammo));
inst.ammo += add;
total += add;