3 Commits

Author SHA1 Message Date
shawn ef4e4ccb80 Clean up test diagnostic files 2026-07-03 20:07:49 -04:00
shawn 7db8434f7e Fix duplicate _rollback_tick causing WeaponManager compile error
A debug-print attempt from earlier inadvertently appended a second
_rollback_tick function (with spaces instead of tabs) at the end of
weapon_manager.gd:419, causing the entire script to fail compilation.
This meant the WeaponManager node had NO script attached:
- 'has_method("set_default_loadout")' returned false
- Client-side loadout init never ran
- All weapon operations silently did nothing

This is the real root cause of why weapons never worked on the client.
2026-07-03 20:07:40 -04:00
shawn 7bbe4ba71d Fix weapons not working on client: remove is_predicting check + init loadout
- Removed the is_predicting() early-return in weapon_manager._rollback_tick
  which blocked all weapon actions on the client (player owned by server)
- Added client-side weapon loadout initialization in player-spawner._spawn
  so the player has weapons immediately, before server state sync arrives
- Server reconciles via rollback state sync

Movement was fixed in v0.2.2 (window focus grab). This addresses
the remaining 'can't switch or use weapons' issue.
2026-07-03 18:24:21 -04:00
4 changed files with 14 additions and 13 deletions
@@ -173,6 +173,15 @@ func _spawn(id: int):
if rollback_sync and rollback_sync.has_method("process_settings"): if rollback_sync and rollback_sync.has_method("process_settings"):
rollback_sync.process_settings() rollback_sync.process_settings()
# On the client side, initialize weapon loadout locally so the player
# has weapons immediately. The server will reconcile via rollback state sync.
if not multiplayer.is_server():
var weapon_mgr = avatar.find_child("WeaponManager")
if weapon_mgr and weapon_mgr.has_method("set_default_loadout"):
# Default to T team — server will correct via state sync
weapon_mgr.set_default_loadout(1) # TeamManager.Team.T = 1
print("[Spawner] Client-side weapon loadout initialized for peer %s" % id)
func get_team_spawn_point(peer_id: int, spawn_idx: int = 0) -> Vector3: func get_team_spawn_point(peer_id: int, spawn_idx: int = 0) -> Vector3:
var team := team_manager.get_team(peer_id) var team := team_manager.get_team(peer_id)
var points: Array[Marker3D] var points: Array[Marker3D]
@@ -158,12 +158,11 @@ func give_weapon(weapon_id: int):
NetworkRollback.mutate(self) NetworkRollback.mutate(self)
func _rollback_tick(delta: float, tick: int, _is_fresh: bool): func _rollback_tick(delta: float, tick: int, _is_fresh: bool):
if rollback_synchronizer.is_predicting(): # NOTE: On the client, the player CharacterBody3D is owned by the server
return # (peer 1), so `rollback_synchronizer.is_predicting()` may return true
# on early ticks when input history hasn't been built up yet.
# DEBUG: weapon switching # We process weapon actions anyway — the server reconciles via rollback.
if input and (input.slot_1 or input.slot_2 or input.slot_3 or input.slot_4): # Only skip if the player is dead or frozen (checked below).
print("[WEAPON DEBUG] _rollback_tick tick=%d slots=[s1=%s s2=%s s3=%s s4=%s] active=%d inv=%s" % [tick, input.slot_1, input.slot_2, input.slot_3, input.slot_4, active_slot, inventory])
# Skip if player dead # Skip if player dead
if player.death_tick >= 0 and tick >= player.death_tick: if player.death_tick >= 0 and tick >= player.death_tick:
@@ -410,8 +409,3 @@ func _spawn_grenade(origin: Vector3, direction: Vector3, owner_id: int, type_idx
get_tree().current_scene.add_child(grenade) get_tree().current_scene.add_child(grenade)
var gtype: Grenade.GrenadeType = Grenade.GrenadeType.FLASH if type_idx == 0 else Grenade.GrenadeType.SMOKE var gtype: Grenade.GrenadeType = Grenade.GrenadeType.FLASH if type_idx == 0 else Grenade.GrenadeType.SMOKE
grenade.setup(origin, direction, owner_id, gtype) grenade.setup(origin, direction, owner_id, gtype)
func _rollback_tick(delta: float, tick: int, _is_fresh: bool):
# DEBUG: Log when this is called with non-default input
if input and (input.slot_1 or input.slot_2 or input.slot_3 or input.slot_4):
print("[WEAPON DEBUG] _rollback_tick tick=%d slots=[%s %s %s %s]" % [tick, input.slot_1, input.slot_2, input.slot_3, input.slot_4])
-1
View File
@@ -1 +0,0 @@
uid://4mlr8ca8nlg7
-1
View File
@@ -1 +0,0 @@
uid://h5lroui7prfv