fix(match): guard kickoff countdown against a post-match resume

The coroutine stalls mid-countdown while the tree is paused for the
results screen, but _end_match unpauses before the deferred scene
change actually tears things down — letting it resume for a frame and
re-emit kickoff_countdown / unfreeze bodies in the dying scene.
This commit is contained in:
Josh Creek
2026-08-04 19:35:41 +01:00
parent fa9590d9c3
commit c96325144a
2 changed files with 12 additions and 2 deletions
+11 -1
View File
@@ -29,6 +29,7 @@ const KICKOFF_COUNTDOWN_SECONDS := 3
var match_timer: Timer
var _in_overtime := false
var _match_over := false
func _get_arena_scene_path() -> String:
@@ -67,6 +68,8 @@ func _process(_delta):
func _on_goal_scored(conceding_team: int) -> void:
if _match_over:
return
var scoring_team := 1 - conceding_team
_record_goal(scoring_team)
score_changed.emit(score.duplicate())
@@ -82,6 +85,8 @@ func _on_goal_scored(conceding_team: int) -> void:
# changes to ship.gd/ball.gd/ship_controller.gd, keeping training_mode.gd
# (which never calls into this file) completely untouched.
func _run_kickoff_countdown() -> void:
if _match_over:
return
reset_ball()
reset_ships()
_set_frozen(true)
@@ -90,8 +95,12 @@ func _run_kickoff_countdown() -> void:
# process_always=false: if full-time fires mid-countdown (see
# _on_match_timer_timeout's get_tree().paused = true), this stalls
# harmlessly in lockstep with the pause instead of ticking a
# countdown label over the results screen.
# countdown label over the results screen. _end_match unpauses the
# tree before the scene teardown actually lands, so the _match_over
# check below is what stops this from resuming into a dying scene.
await get_tree().create_timer(1.0, false).timeout
if _match_over:
return
kickoff_countdown.emit(0)
_set_frozen(false)
@@ -121,6 +130,7 @@ func _start_overtime() -> void:
func _end_match(winning_team: int) -> void:
_match_over = true
print("Match over! Final score: %d - %d" % [score[0], score[1]])
match_ended.emit(winning_team, score.duplicate())
# Freeze gameplay while the HUD (process_mode ALWAYS) shows the result.