feat: dash ability; ammo pressure scaling, full-HP hearts, muzzle alignment, holstered debug ammo
- Shift dash: 0.45*v*0.6 instant burst then 0.6s of 50% slow (net 95% of walking distance); slow doubles as cooldown, no dash while idle/slowed. - Generic ammo refills scale with the live pressure dial at 80% of the HP multiplier via ammoPressureMul(). - Hearts at full HP stay on the floor (magnet ignores them) instead of converting to score. - Muzzle audit: flame FX and pellets share one right-hand origin, Spinal Tap beam starts at the muzzle, saw flash suppressed (blade sparks are the effect). - Debug REFILL/INF AMMO and the ammo row now cover a spent special holstered behind the Bone Popper. - Sfx.duck() defaults its args; a no-arg call crashed the loop with a non-finite AudioParam value (found via the dash E2E).
This commit is contained in:
1 parent
684a54f5ad
commit
4b9e4a1e97
6 files changed
+49
-24
No files matched your search
+9
-8
@@ -48,6 +48,10 @@ function fireWeapon(p, w) {
|
||||
const ang = p.aim;
|
||||
const muzzle = w.muzzle || 35;
|
||||
let bx = p.x + Math.cos(ang) * muzzle, by = p.y + Math.sin(ang) * muzzle;
|
||||
if (w.behavior === 'flame') {
|
||||
const rh = ang + Math.PI / 2;
|
||||
bx += Math.cos(rh) * 26; by += Math.sin(rh) * 26; // right-hand hold: FX and bullets share one origin
|
||||
}
|
||||
const dmgMul = st.dmgMul * st.dmgLiveMul;
|
||||
const spdMul = st.shotSpeedMul;
|
||||
spawnMuzzleFx(bx, by, ang, w.behavior);
|
||||
@@ -86,10 +90,6 @@ function fireWeapon(p, w) {
|
||||
break;
|
||||
}
|
||||
case 'cone': case 'flame': {
|
||||
if (w.behavior === 'flame') {
|
||||
const rh = ang + Math.PI / 2;
|
||||
bx += Math.cos(rh) * 26; by += Math.sin(rh) * 26; // right-hand hold: origin right of the body
|
||||
}
|
||||
for (const center of volley) {
|
||||
for (let i = 0; i < 2; i++) mk(center + rand(-w.spread, w.spread), { pierce: 2 + st.pierce, r: 6 * st.sizeMul });
|
||||
}
|
||||
@@ -173,6 +173,7 @@ function sawTick(p, def, inst, dt) {
|
||||
// fire the Spinal Tap beam
|
||||
function fireBeam(p, def, charge) {
|
||||
const st = p.stats;
|
||||
const muzzle = def.muzzle || 35;
|
||||
const angles = [p.aim];
|
||||
for (let i = 1; i <= st.split; i++) angles.push(p.aim + (i % 2 ? 1 : -1) * 0.025);
|
||||
for (let i = 1; i <= st.fan; i++) { angles.push(p.aim + 0.16 * i); angles.push(p.aim - 0.16 * i); }
|
||||
@@ -182,16 +183,16 @@ function fireBeam(p, def, charge) {
|
||||
const dmg = def.dmg * st.dmgMul * st.dmgLiveMul * (0.4 + 0.6 * charge) * inert;
|
||||
const width = 14 * Math.sqrt(st.sizeMul);
|
||||
for (const ang of angles) {
|
||||
const x2 = p.x + Math.cos(ang) * len, y2 = p.y + Math.sin(ang) * len;
|
||||
const x0 = p.x + Math.cos(ang) * muzzle, y0 = p.y + Math.sin(ang) * muzzle;
|
||||
const x2 = x0 + Math.cos(ang) * len, y2 = y0 + Math.sin(ang) * len;
|
||||
for (const e of G.enemies) {
|
||||
if (distToSegment(e.x, e.y, p.x, p.y, x2, y2) < e.r + width) {
|
||||
if (distToSegment(e.x, e.y, x0, y0, x2, y2) < e.r + width) {
|
||||
damageEnemy(e, dmg, ang, true, { source: 'player' });
|
||||
}
|
||||
}
|
||||
spawnBeam(p.x, p.y, ang, len);
|
||||
spawnBeam(x0, y0, ang, len);
|
||||
}
|
||||
const ang = p.aim;
|
||||
const muzzle = def.muzzle || 35;
|
||||
spawnMuzzleFx(p.x + Math.cos(ang) * muzzle, p.y + Math.sin(ang) * muzzle, ang, 'beam');
|
||||
p.recoil = 1;
|
||||
p.muzzleT = 0.11;
|
||||
|
||||
Reference in new issue
Block a user