refactor(*): DRY up arena scenes, game modes, and HUD instruments

Arenas inherit from a new arena_base.tscn instead of restating ~40 shared
lines each; only sky/ambient/glow/tint/decoration vary, exposed via new
Arena exports since nested Environment properties aren't overridable
through scene inheritance. Bot construction and score-keeping move onto
GameMode, shared by match and spectate modes while preserving their
differing GameSettings-override behavior and the HUD's score-row
duck-typing. HUD instruments share a HudInstrument base for the
smoothing-weight calc and angle-lerp helper. Also dedupes
MAIN_MENU_SCENE_PATH into ScenePaths and documents why DIFFICULTIES
tiers share one checkpoint.
This commit is contained in:
Josh Creek
2026-08-04 15:07:33 +01:00
parent b285d012dc
commit 08a0f74391
18 changed files with 203 additions and 268 deletions
+5 -13
View File
@@ -27,7 +27,6 @@ const KICKOFF_COUNTDOWN_SECONDS := 3
@export_range(1, 60) var bot_reaction_ticks: int = 8
@export_range(0.0, 1.0) var bot_action_noise: float = 0.0
var score := {0: 0, 1: 0}
var match_timer: Timer
var _in_overtime := false
@@ -56,15 +55,9 @@ func _make_opponent_controller() -> ShipController:
# The main menu's dropdown selection (GameSettings autoload) wins over the
# scene's export, which stays as the fallback for direct-scene runs.
var path := bot_model_path if GameSettings.selected_bot_path.is_empty() else GameSettings.selected_bot_path
if not path.is_empty() and FileAccess.file_exists(path):
var bot := AIShipController.new()
bot.model_path = path
bot.reaction_ticks = bot_reaction_ticks if GameSettings.selected_bot_reaction_ticks < 0 else GameSettings.selected_bot_reaction_ticks
bot.action_noise = bot_action_noise if GameSettings.selected_bot_action_noise < 0.0 else GameSettings.selected_bot_action_noise
return bot
if not path.is_empty():
push_warning("MatchMode: bot model not found at %s, spawning inert opponent" % path)
return ShipController.new() # inert placeholder
var reaction_ticks := bot_reaction_ticks if GameSettings.selected_bot_reaction_ticks < 0 else GameSettings.selected_bot_reaction_ticks
var action_noise := bot_action_noise if GameSettings.selected_bot_action_noise < 0.0 else GameSettings.selected_bot_action_noise
return _build_opponent(path, reaction_ticks, action_noise, "MatchMode")
func _process(_delta):
@@ -75,9 +68,8 @@ func _process(_delta):
func _on_goal_scored(conceding_team: int) -> void:
var scoring_team := 1 - conceding_team
score[scoring_team] += 1
_record_goal(scoring_team)
score_changed.emit(score.duplicate())
print("Goal for team %d! Score: %d - %d" % [scoring_team, score[0], score[1]])
if _in_overtime:
# Golden goal: the first score after a draw ends the match outright.
_end_match(scoring_team)
@@ -136,4 +128,4 @@ func _end_match(winning_team: int) -> void:
await get_tree().create_timer(RESULT_SCREEN_SECONDS).timeout
# Unpause before leaving, or the menu arrives paused and unresponsive.
get_tree().paused = false
get_tree().change_scene_to_file(MAIN_MENU_SCENE_PATH)
get_tree().change_scene_to_file(ScenePaths.MAIN_MENU)