Add engine flames, damage numbers, nameplates, music, and combat/collision fixes

Feature work (CLAUDE.md items 17-18):
- Race roster art rework (Apex/ISN/ORC) plus per-ship engine-flame sprites
  that swap in on thrust
- Floating damage-number VFX, per-ship nameplates, energy bar rework
- Background music manager and per-race ship SFX

Bugfixes/tuning from live testing:
- No friendly fire: bullets stop on a teammate's hull but deal no damage
  (bullet.gd), decided by race via PlayerRegistry
- Ships no longer physically block each other (own collision layer,
  ship.tscn/bullet.tscn) -- fixes ramming/parking trolling and the stuck-on-
  corpse bug after a kill
- Explosions ghost any ship's sprite passing through instead of blocking it
  (effects/explosion.gd's GhostArea)
- Fixed two "flushing physics queries" crashes from the above: explosion
  spawn and death/respawn collision toggling are now deferred
  (ship_movement.gd)
- Dead ships stop blocking bullets during their respawn delay
- Bots fly a mixed roster (1 Tank + 2 Gunner + rest Fighter per team)
  instead of always the Fighter (bot_manager.gd)
- Camera zoom knob, larger/longer-lived damage numbers and nameplate text,
  red (not yellow) enemy name color for better contrast

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 23:55:18 -04:00
parent 7b44b2f2dc
commit 2f6607af8c
67 changed files with 979 additions and 125 deletions
+22 -1
View File
@@ -18,16 +18,19 @@ const RACES := [
"name": "LANCET", "role": "Fighter",
"desc": "A single, high-precision bolt of blue coherent light. Built to poke from range and vanish before anything can return fire — the sharpest shot in the fleet, if you can land it.",
"path": "res://assets/images/ships/apex/lancet.png", "scale": 0.296, "speed_factor": SPEED_BY_ROLE.Fighter,
"sound_path": "res://assets/sound/ships/apex/apex_1.wav",
},
{
"name": "PULSAR", "role": "Gunner",
"desc": "A wide, rapid-fire fan of low-damage green plasma pulses. Trades precision for volume — spray enough bolts and something connects.",
"path": "res://assets/images/ships/apex/pulsar.png", "scale": 0.373, "speed_factor": SPEED_BY_ROLE.Gunner,
"sound_path": "res://assets/sound/ships/apex/apex_1.wav",
},
{
"name": "SOVEREIGN", "role": "Tank",
"desc": "Homing micro-missiles alongside dual heavy plasma batteries. Slow and telegraphed, but its lock-on missiles punish anyone who tries to just outrun it.",
"path": "res://assets/images/ships/apex/sovereign.png", "scale": 0.348, "speed_factor": SPEED_BY_ROLE.Tank,
"sound_path": "res://assets/sound/ships/apex/apex_1.wav",
},
],
},
@@ -39,16 +42,22 @@ const RACES := [
"name": "PATRIOT", "role": "Fighter",
"desc": "A single, hard-hitting high-caliber explosive shell. Standard-issue and dependable — a clean, punishing hit if you land it.",
"path": "res://assets/images/ships/isn/patriot.png", "scale": 0.504, "speed_factor": SPEED_BY_ROLE.Fighter,
"sound_path": "res://assets/sound/ships/isn/isn_1.wav",
"flame_path": "res://assets/images/ships/isn/patriot_flame.png",
},
{
"name": "BARRAGE", "role": "Gunner",
"desc": "A relentless quad-barrel spray of fast, low-damage light bullets. Built for sustained suppressing fire rather than any one killing blow.",
"path": "res://assets/images/ships/isn/barrage.png", "scale": 0.516, "speed_factor": SPEED_BY_ROLE.Gunner,
"sound_path": "res://assets/sound/ships/isn/isn_1.wav",
"flame_path": "res://assets/images/ships/isn/barrage_flame.png",
},
{
"name": "BEHEMOTH", "role": "Tank",
"desc": "Heavy tracking torpedoes plus massive physical deck-guns. The navy's flagship-killer — slow to turn, but nothing stands in its way for long.",
"path": "res://assets/images/ships/isn/behemoth.png", "scale": 0.331, "speed_factor": SPEED_BY_ROLE.Tank,
"sound_path": "res://assets/sound/ships/isn/isn_1.wav",
"flame_path": "res://assets/images/ships/isn/behemoth_flame.png",
},
],
},
@@ -60,16 +69,22 @@ const RACES := [
"name": "RAIL-JACK", "role": "Fighter",
"desc": "A single, heavy magnetic railgun slug. Repurposed mining hardware — one slug, but it hits like a dropped asteroid.",
"path": "res://assets/images/ships/orc/rail_jack.png", "scale": 0.492, "speed_factor": SPEED_BY_ROLE.Fighter,
"sound_path": "res://assets/sound/ships/orc/orc_1.wav",
"flame_path": "res://assets/images/ships/orc/rail_jack_flame.png",
},
{
"name": "SCRAP-SPITTER", "role": "Gunner",
"desc": "A rotary scrap-cannon spraying rapid, low-damage metal shrapnel. Loud, dirty, and built to keep the pressure on.",
"path": "res://assets/images/ships/orc/scrap_spitter.png", "scale": 0.462, "speed_factor": SPEED_BY_ROLE.Gunner,
"sound_path": "res://assets/sound/ships/orc/orc_1.wav",
"flame_path": "res://assets/images/ships/orc/scrap_spitter_flame.png",
},
{
"name": "IRON-CLAD", "role": "Tank",
"desc": "Unguided explosive rockets plus continuous vulcan machine-gun fire. Bolted-together and brutal — built to grind a fight down, not finesse it.",
"path": "res://assets/images/ships/orc/iron_clad.png", "scale": 0.495, "speed_factor": SPEED_BY_ROLE.Tank,
"sound_path": "res://assets/sound/ships/orc/orc_1.wav",
"flame_path": "res://assets/images/ships/orc/iron_clad_flame.png",
},
],
},
@@ -331,8 +346,14 @@ func _show_ship_selection() -> void:
func _on_ship_chosen(ship: Dictionary) -> void:
PlayerRegistry.submit_local_loadout(
GameConfig.player_name, _chosen_race.id, ship.path, ship.scale, ship.speed_factor, ship.role
GameConfig.player_name, _chosen_race.id, ship.path, ship.scale, ship.speed_factor, ship.role,
ship.get("flame_path", ""), ship.get("sound_path", "")
)
# Only the mandatory pre-spawn pick should end the menu music — a
# mid-match reopen (pause menu SELECT TEAM) leaves it alone since it's
# already stopped by this point (see _reopenable).
if not _reopenable:
MusicManager.stop_menu_music()
_reopenable = true
_close()