import { expect, test } from "bun:test"; import { fade, firedNow, gunFire, gunSnapshot, gunTick, hitMarked, makeGun } from "../static/gun.js"; const snap = (over: Record = {}, shots: unknown[] = []) => ({ me: { x: 100, y: 100, ammo: 25, reloading: false, alive: true, ...over }, shots, }); test("the magazine going down is a shot; a reload is not", () => { expect(firedNow(25, 24, false)).toBe(true); expect(firedNow(25, 25, false)).toBe(false); expect(firedNow(1, 25, true)).toBe(false); expect(firedNow(null, 25, false)).toBe(false); }); test("a hit marker comes from a shot of mine the server says landed", () => { const mine = [{ x1: 102, y1: 99, x2: 400, y2: 100, hit: true }]; expect(hitMarked(mine, { x: 100, y: 100 })).toBe(true); const missed = [{ x1: 102, y1: 99, x2: 400, y2: 100, hit: false }]; expect(hitMarked(missed, { x: 100, y: 100 })).toBe(false); const somebody_else = [{ x1: 900, y1: 900, x2: 400, y2: 100, hit: true }]; expect(hitMarked(somebody_else, { x: 100, y: 100 })).toBe(false); }); test("a snapshot with a shot in it kicks the gun, and the kick fades", () => { const gun = makeGun(); gunSnapshot(gun, snap()); expect(gun.kick).toBe(0); gunSnapshot(gun, snap({ ammo: 24 })); expect(gun.kick).toBe(1); gunTick(gun, 0.06); expect(gun.kick).toBeLessThan(1); gunTick(gun, 1); expect(gun.kick).toBe(0); }); test("a landed shot marks, and the mark fades on its own clock", () => { const gun = makeGun(); gunSnapshot(gun, snap({ ammo: 24 }, [{ x1: 100, y1: 100, x2: 300, y2: 100, hit: true }])); expect(gun.mark).toBe(1); gunTick(gun, 0.2); expect(gun.mark).toBeGreaterThan(0); gunTick(gun, 0.2); expect(gun.mark).toBe(0); }); test("pulling the trigger kicks the gun now, and the snapshot's word is not a second kick", () => { const gun = makeGun(); gunSnapshot(gun, snap()); expect(gunFire(gun, snap())).toBe(true); expect(gun.kick).toBe(1); // The kick is well under way when the server's word arrives: no restart. gunTick(gun, 0.08); const shown = gun.kick; gunSnapshot(gun, snap({ ammo: 24 })); expect(gun.kick).toBe(shown); // A second shot the server fired on its own (a held trigger) still kicks. gunSnapshot(gun, snap({ ammo: 23 })); expect(gun.kick).toBe(1); // No kick with nothing to fire: dead, reloading, or empty. expect(gunFire(makeGun(), snap({ alive: false }))).toBe(false); expect(gunFire(makeGun(), snap({ reloading: true }))).toBe(false); expect(gunFire(makeGun(), snap({ ammo: 0 }))).toBe(false); // A kick the server never answered is forgotten once it has faded. const refused = makeGun(); gunFire(refused, snap()); gunTick(refused, 1); gunSnapshot(refused, snap()); expect(refused.owed).toBe(0); }); test("fade never goes below nothing", () => { expect(fade(0.1, 10, 0.2)).toBe(0); });