From e60645f0f672d9f826433c3ccfdee21a69a0bf96 Mon Sep 17 00:00:00 2001 From: Sofia Date: Fri, 24 Jul 2026 18:27:07 +0300 Subject: [PATCH] Make weapon swapping and ball dropping work correctly --- rust/src/game_manager.rs | 13 +++++- rust/src/net/protocol.rs | 16 ++++--- rust/src/player/mod.rs | 99 +++++++++++++++++++--------------------- 3 files changed, 69 insertions(+), 59 deletions(-) diff --git a/rust/src/game_manager.rs b/rust/src/game_manager.rs index 919a3e0..dba797f 100644 --- a/rust/src/game_manager.rs +++ b/rust/src/game_manager.rs @@ -503,6 +503,7 @@ impl Game { killing_spree: 0, killing_spree_cd: 0., character: None, + last_held_weapon: WeaponType::Raygun, }); self.run_deferred(move |s| s.signals().on_new_player().emit(id)); @@ -698,7 +699,10 @@ impl Game { if let Some(player) = self.find_player_mut(player_id) && let Some(character) = &mut player.character { - character.dyn_bind_mut().spawn_weapon_common(weapon_type); + if weapon_type != WeaponType::Ball { + player.last_held_weapon = weapon_type; + } + character.dyn_bind_mut().swap_weapon(weapon_type, true); let player_id = player.id(); self.run_deferred(move |_| { if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer @@ -725,6 +729,11 @@ impl Game { .spawn_player(id, team, id == self.self_id.unwrap_or(0), None); if let Some(character) = &mut character { + if let Some(player) = self.find_player(id) { + character + .dyn_bind_mut() + .swap_weapon(player.last_held_weapon, true); + } if let Ok(mut local_player) = character.clone().try_cast::() { local_player.bind_mut().signals().on_die().connect_other( self, @@ -982,6 +991,7 @@ pub struct Player { pub character: Option>, pub killing_spree: u16, pub killing_spree_cd: f64, + pub last_held_weapon: WeaponType, } impl Player { @@ -1099,6 +1109,7 @@ impl From for Player { character: None, killing_spree: 0, killing_spree_cd: 0., + last_held_weapon: WeaponType::Raygun, } } } diff --git a/rust/src/net/protocol.rs b/rust/src/net/protocol.rs index 1c91859..d48ae13 100644 --- a/rust/src/net/protocol.rs +++ b/rust/src/net/protocol.rs @@ -387,12 +387,16 @@ impl NetworkManager { } } Package::SwapWeapon(_, weapon_type) => { - if let Some(game) = &mut Game::singleton() - && let Some(player) = - game.bind_mut().find_player_by_addr_mut(&conn.address) - && let Some(character) = &mut player.character - { - character.dyn_bind_mut().swap_weapon_proxy(weapon_type); + if let Some(game) = &mut Game::singleton() { + let player = + game.bind().find_player_by_addr(&conn.address).cloned(); + if let Some(player) = player { + game.bind_mut().handle_swap_weapon( + player.id(), + weapon_type, + false, + ); + } } } _ => {} diff --git a/rust/src/player/mod.rs b/rust/src/player/mod.rs index f9a447f..f61d0a0 100644 --- a/rust/src/player/mod.rs +++ b/rust/src/player/mod.rs @@ -58,8 +58,7 @@ pub trait IPlayer { fn is_dead(&self) -> bool; fn kill(&mut self, source_player: DamageSource); fn dead_for(&self) -> f64; - fn spawn_weapon_common(&mut self, weapon: WeaponType); - fn swap_weapon_proxy(&mut self, weapon: WeaponType); + fn swap_weapon(&mut self, weapon: WeaponType, drop_ball: bool); fn get_weapon(&self) -> Option>; fn take_weapon(&mut self) -> Option>; fn drop_ball(&mut self, with_velocity: bool) -> bool; @@ -70,7 +69,6 @@ pub trait PlayerCommon { fn player_update(&mut self, delta: f64); fn try_jump(&mut self) -> bool; fn drop_ball_common(&mut self, with_velocity: bool) -> bool; - fn swap_weapon(&mut self, ty: WeaponType); fn get_look_dir(&self) -> Vector3; fn can_take_damage(&self, source: &DamageSource) -> bool; } @@ -108,18 +106,16 @@ impl PlayerCommon for T { } fn drop_ball_common(&mut self, with_velocity: bool) -> bool { - if let Some(weapon) = self.take_weapon() + if let Some(weapon) = self.get_weapon() && let Ok(_) = weapon.try_cast::() { self.run_deferred(move |s| { - if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer - && let PeerKind::Server(peer, _) = peer + if let Some(game) = Game::singleton() + && let Some(player) = game.bind().find_player(s.get_player_id().unwrap_or(0)) { - s.spawn_weapon_common(WeaponType::Raygun); - peer.broadcast_reliable(Package::SwapWeapon( - s.get_player_id().unwrap_or(0), - WeaponType::Raygun, - )); + s.swap_weapon(player.last_held_weapon, false); + } + if NetworkManager::singleton().bind().is_host() { if let Some(mut game) = Game::singleton() { if let Some(ball_origin) = &s.get_camera_origin() { let velocity = if with_velocity { @@ -146,28 +142,6 @@ impl PlayerCommon for T { } } - fn swap_weapon(&mut self, ty: WeaponType) { - if ty == WeaponType::Ball { - return; - } - self.spawn_weapon_common(ty); - self.run_deferred(move |s| { - if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer { - match peer { - PeerKind::Client(peer, socket_addr) => { - peer.send_reliable(socket_addr, Package::SwapWeapon(0, ty)); - } - PeerKind::Server(peer, _) => { - peer.broadcast_reliable(Package::SwapWeapon( - s.get_player_id().unwrap_or(0), - ty, - )); - } - } - } - }); - } - fn get_look_dir(&self) -> Vector3 { if let Some(camera_origin) = self.get_camera_origin() { camera_origin.get_global_basis().col_c().neg() @@ -384,8 +358,10 @@ impl IPlayer for LocalPlayer { } } - fn spawn_weapon_common(&mut self, weapon: WeaponType) { - self.drop_ball(true); + fn swap_weapon(&mut self, weapon: WeaponType, drop_ball: bool) { + if drop_ball { + self.drop_ball(true); + } if let Some(mesh) = self.soldier_mesh.clone() { match weapon { @@ -408,16 +384,12 @@ impl IPlayer for LocalPlayer { } } - fn swap_weapon_proxy(&mut self, weapon: WeaponType) { - self.swap_weapon(weapon); - } - fn get_weapon(&self) -> Option> { self.weapon.clone() } fn take_weapon(&mut self) -> Option> { - self.weapon.as_ref().take().cloned() + self.weapon.take() } fn drop_ball(&mut self, with_velocity: bool) -> bool { @@ -467,7 +439,7 @@ impl ICharacterBody3D for LocalPlayer { .connect_other(self, |s| s.update_lock()); } - self.spawn_weapon_common(WeaponType::Raygun); + self.swap_weapon(WeaponType::Raygun, false); if let Some(camera) = &mut self.camera { camera.set_current(true); @@ -642,10 +614,35 @@ impl ICharacterBody3D for LocalPlayer { } } } - } else if event.is_action_pressed("weapon_1") { - self.swap_weapon(WeaponType::Raygun); - } else if event.is_action_pressed("weapon_2") { - self.swap_weapon(WeaponType::Shotgun); + } + if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer { + let weapon_type = if event.is_action_pressed("weapon_1") { + Some(WeaponType::Raygun) + } else if event.is_action_pressed("weapon_2") { + Some(WeaponType::Shotgun) + } else { + None + }; + if let Some(weapon_type) = weapon_type { + self.swap_weapon(weapon_type, true); + match peer { + PeerKind::Client(peer, socket_addr) => { + peer.send_reliable(socket_addr, Package::SwapWeapon(0, weapon_type)); + } + PeerKind::Server(peer, _) => { + if let Some(game) = &mut Game::singleton() + && let Some(player) = + game.bind_mut().find_player_mut(self.player_id.unwrap_or(0)) + { + player.last_held_weapon = weapon_type; + } + peer.broadcast_reliable(Package::SwapWeapon( + self.player_id.unwrap_or(0), + weapon_type, + )); + } + } + } } if let Ok(event) = event.try_cast::() { @@ -894,8 +891,10 @@ impl IPlayer for RemotePlayer { self.is_dead = true; } - fn spawn_weapon_common(&mut self, weapon: WeaponType) { - self.drop_ball(true); + fn swap_weapon(&mut self, weapon: WeaponType, drop_ball: bool) { + if drop_ball { + self.drop_ball(true); + } if let Some(mesh) = &mut self.soldier_mesh { match weapon { @@ -906,10 +905,6 @@ impl IPlayer for RemotePlayer { } } - fn swap_weapon_proxy(&mut self, weapon: WeaponType) { - self.swap_weapon(weapon); - } - fn get_weapon(&self) -> Option> { self.soldier_mesh .as_ref() @@ -946,7 +941,7 @@ impl ICharacterBody3D for RemotePlayer { } }); - self.spawn_weapon_common(WeaponType::Raygun); + self.swap_weapon(WeaponType::Raygun, false); } fn process(&mut self, delta: f64) {