Files
zombie-fps/docs/GRENADES-WAVES.md
T

5.2 KiB
Raw Blame History

Grenades and growing waves

Rifle grenade: contact detonation

  • Right mouse button / touch GRENADE: launch while alive (mouse captured on desktop).
  • Cooldown: 15 seconds from launch, displayed in HUD; repeated clicks cannot bypass it.
  • Physical RigidBody3D: sphere radius 0.12 m, mass 0.4 kg, no bounce, friction 0.65, gravity and continuous collision detection (CCD). Velocity: forward 12 m/s + up 3 m/s
    • player velocity. The thrower is excluded from projectile collision, not blast damage.
  • First contact detonates immediately: ground, walls, office props and enemies. contact_monitor=true, max_contacts_reported=8; _integrate_forces() captures the physics position, body_entered is a fallback. One synchronous exploded guard and one deferred _explode() prevent duplicate effects/damage and scene changes during physics callbacks. Damage rays start at the sphere centre, on the free side of the wall.
  • Window panes are Area3D, layer 8, not physical bodies: a swept ray between physics positions detects these separately, including fast crossings of thin glass. This does not add environmental destruction (the existing zombie-entry glass shatter is unchanged).
  • No 4-second fuse anymore. A lost projectile is deleted after 15 seconds without an explosion, avoiding orphan nodes or delayed airborne blasts.
  • Blast radius 5 m, maximum damage 160, linear falloff; a world-mask ray prevents damage through walls. The living thrower is still included.

Original Half-Life explosion

scripts/grenade_explosion.gd uses Valve's sprites/zerogxplode.spr, the fireball referenced by Half-Life's TE_EXPLOSION. The original SDK uses 15 FPS and the sprite has 15 frames, 64×64 each: one second, no looping.

tools/extract_explosion_sprite.py reads the local Steam installation without changing it, validates IDSP v2 / additive format, and converts the original RGB palette/frames to assets/effects/explosion/zerogxplode_atlas.png. Source/output SHA256, frame origins, format and timing are recorded in the adjacent source_manifest.json.

  • PNG atlas 340×204, 5×3 frames with 2-pixel black gutters; UVs crop the gutters to avoid bleeding between frames under linear filtering.
  • Camera-facing 3.2 m quad, additive and unshaded, normal depth testing (not visible through walls), no shadows. Original RGB is preserved: black contributes zero under additive blending; do not treat the last palette index as alpha-test transparency.
  • Fireball raised 0.8 m above the physical blast centre to reduce floor clipping. Damage stays at the actual impact; visual position does not change blast distance or occlusion.
  • Orange flash fades over 0.3 s, with no shadow-casting light; 18 small CPU embers are secondary to the fireball. Original weapons/explode3–5.wav unchanged. The effect node remains alive 4 s for audio, while the sprite disappears after its single playback.
  • Plain PNG/QuadMesh/StandardMaterial3D and CPU particles: compatible with the Web Compatibility renderer; no native SPR importer or GPU-only effects at runtime.

Other original assets: grenade.mdl (two embedded textures), native grenade.scn for Web and explosion WAVs; provenance assets/half_life_manifest.json, extraction tools/extract_grenade_assets.py.

Growing waves

Ordinary wave size: 4 + 2 × wave (6, 8, 10, ...), no old cap of 24. Every tenth wave (10, 20, 30, ...) is instead one Alien Grunt boss, with no ordinary zombies; see docs/BOSS.md for scaling, teleport arrival and the native-only test sandbox. Next wave three seconds after all enemies die and spawning completes. Scheduling guard prevents duplicate wave timers. Corpses remain.

Tests and visual verification

Godot 4.7.1, not the older binary on PATH:

G="$HOME/.local/opt/godot-4.7.1/Godot_v4.7.1-stable_linux.x86_64"
"$G" --headless --path . --script res://tools/test_grenade.gd
"$G" --headless --path . --script res://tools/test_wave_growth.gd
DISPLAY=:0 "$G" --display-driver x11 --rendering-method gl_compatibility --path . \
  --script res://tools/shot_grenade.gd

test_grenade: 24 checks, real floor/desk/thin-wall/enemy/glass collisions, rapid crossings at 80 m/s, single detonation, enemy damage, motion/gravity/thrower exclusion, real 15-second cooldown, blast LOS/range/self-damage, absence of a 4-second fuse, non-explosive cleanup, additive billboard atlas and one-shot frame timing, wave growth.

Visual harness captures original frames 0/3/7/11/14 after an actual floor impact in the office (/tmp/zombie-grenade-frame-*.png). Desktop tests use no public scores API. The start-screen GUI regression needs a real display, not the headless dummy driver.

Sources:

Historical first grenade release: 4e181f0fe5d02cc9 used the old 4-second fuse and a particle-only explosion. It is superseded; current behavior is described above.