feat: implement global SFXManager singleton and integrate into main scene initialization

This commit is contained in:
Yogi Wiguna
2026-03-31 12:40:57 +08:00
parent 82f2811c26
commit cc207bca3d
3 changed files with 36 additions and 8 deletions
+7 -3
View File
@@ -720,8 +720,12 @@ func _auto_start_from_lobby():
func _start_game():
if multiplayer.is_server():
# Delay spawn assignment to allow clients to finish instantiating Player nodes
# via MultiplayerSpawner. If called too early, the RPC is dropped and clients
# are left misplaced at the default starting position.
await get_tree().create_timer(1.0).timeout
# NOW assign spawn positions for EVERYONE (Host, Client, Bots)
# We do this BEFORE the stabilization delay so players are moved away from (0,0) immediately.
_assign_random_spawn_positions()
# Wait for Nakama websocket to actually be open, up to 5 seconds
@@ -735,9 +739,9 @@ func _start_game():
wait_time += 0.2
# Stabilization delay to allow clients to finish loading and spawning
# We wait 1.5s to ensure the 1.2s loading screen buffer has finished
# We wait 0.5s to ensure the remainder of the 1.2s loading screen buffer has finished
# before the countdown starts.
await get_tree().create_timer(1.5).timeout
await get_tree().create_timer(0.5).timeout
# PRE-GAME COUNTDOWN (3s)
# Spawn static obstacles before countdown starts (Stop n Go only)
+19 -1
View File
@@ -76,6 +76,8 @@ var is_attack_mode: bool = false:
return # Prevent infinite recursion / redundant updates
is_attack_mode = value
if is_attack_mode:
attack_mode_timer = MAX_ATTACK_MODE_TIME
_refresh_player_visuals()
# Sync to others if we are the authority
@@ -836,6 +838,8 @@ var slow_timer: float = 0.0
var tekton_carry_timer: float = 0.0
const MAX_TEKTON_CARRY_TIME: float = 3.0
var attack_mode_timer: float = 0.0
const MAX_ATTACK_MODE_TIME: float = 5.0
@rpc("any_peer", "call_local")
func apply_stagger(duration: float = 1.5):
@@ -1184,12 +1188,24 @@ func _process(delta):
if movement_manager:
movement_manager._process(delta)
# Attack/Knock Mode Expiration Timer
if is_multiplayer_authority() and (is_attack_mode or is_knock_mode):
if attack_mode_timer > 0:
attack_mode_timer -= delta
if attack_mode_timer <= 0:
attack_mode_timer = 0.0
is_attack_mode = false
is_knock_mode = false
NotificationManager.send_message(self, "Knock Mode Expired!", NotificationManager.MessageType.WARNING)
if powerup_manager:
powerup_manager.reset_boost()
# Immunity Timer Logic
if immunity_timer > 0:
immunity_timer -= delta
if immunity_timer <= 0:
immunity_timer = 0
_apply_tint_recursive(self , Color.WHITE) # Remove immunity tint
_apply_tint_recursive(self, Color.WHITE) # Remove immunity tint
# Slow Timer Logic
if slow_timer > 0:
@@ -2445,6 +2461,8 @@ var is_knock_mode: bool = false:
set(value):
if is_knock_mode == value: return
is_knock_mode = value
if is_knock_mode:
attack_mode_timer = MAX_ATTACK_MODE_TIME
_refresh_player_visuals()
func enter_attack_mode():