diff --git a/rust/src/game_manager.rs b/rust/src/game_manager.rs index d179671..ed29f04 100644 --- a/rust/src/game_manager.rs +++ b/rust/src/game_manager.rs @@ -330,24 +330,35 @@ impl Game { } pub fn handle_ball_pickup(&mut self, player_id: u16) { - if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer - && let PeerKind::Server(peer, _) = peer - { + if NetworkManager::singleton().bind_mut().is_host() { self.despawn_ball(); - if let Some(player) = self.find_player_mut(player_id) - && let Some(character) = &mut player.character - { - character.dyn_bind_mut().swap_weapon(WeaponType::Ball); - peer.broadcast_reliable(Package::SwapWeapon(player.id, WeaponType::Ball)); - } + self.run_deferred(move |s| s.handle_swap_weapon(player_id, WeaponType::Ball, true)); } } - pub fn handle_swap_weapon(&mut self, player_id: u16, weapon_type: WeaponType) { + // Handle a swap-weapon command package + pub fn handle_swap_weapon( + &mut self, + player_id: u16, + weapon_type: WeaponType, + allow_ball: bool, + ) { + if weapon_type == WeaponType::Ball && !allow_ball { + return; + } + if let Some(player) = self.find_player_mut(player_id) && let Some(character) = &mut player.character { character.dyn_bind_mut().swap_weapon(weapon_type); + let player_id = player.id; + self.run_deferred(move |_| { + if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer + && let PeerKind::Server(peer, _) = peer + { + peer.broadcast_reliable(Package::SwapWeapon(player_id, weapon_type)); + } + }); } } diff --git a/rust/src/net/network_manager.rs b/rust/src/net/network_manager.rs index 7872f90..d528d4c 100644 --- a/rust/src/net/network_manager.rs +++ b/rust/src/net/network_manager.rs @@ -270,7 +270,11 @@ impl INode for NetworkManager { } Package::SwapWeapon(id, weapon_type) => { if let Some(game) = &mut Game::singleton() { - game.bind_mut().handle_swap_weapon(id, weapon_type); + game.bind_mut().handle_swap_weapon( + id, + weapon_type, + true, + ); } } _ => {} diff --git a/rust/src/player.rs b/rust/src/player.rs index 7b2d9fe..2981c89 100644 --- a/rust/src/player.rs +++ b/rust/src/player.rs @@ -15,14 +15,14 @@ use crate::{ net::{ network_manager::{ NetworkManager, - Package::{Jump, Shoot}, + Package::{self, Jump, Shoot}, PeerKind, }, util::{NetVector3, cast_ray}, }, soldier_mesh::SoldierMesh, ui::cli::CommandLinePanel, - weapon::{Weapon, WeaponType}, + weapon::{BallWeapon, Weapon, WeaponType}, }; #[derive(Debug, Clone, Copy, Serialize, Deserialize)] @@ -51,6 +51,7 @@ pub trait IPlayer { fn dead_for(&self) -> f64; fn swap_weapon(&mut self, weapon: WeaponType); fn get_weapon(&self) -> Option>; + fn drop_ball(&mut self, with_velocity: bool) -> bool; } pub trait PlayerMovement { @@ -183,11 +184,13 @@ impl IPlayer for LocalPlayer { return false; } + if self.drop_ball(true) { + return true; + } + if self.shoot_cd <= 0. { let rid = self.base().get_rid(); - if let Some(mesh) = &mut self.soldier_mesh - && let Some(mut weapon) = mesh.bind().get_weapon() - { + if let Some(mut weapon) = self.get_weapon() { weapon .dyn_bind_mut() .shoot(rid, self.player_id.unwrap_or(0), to, deal_damage); @@ -248,6 +251,30 @@ impl IPlayer for LocalPlayer { .as_ref() .and_then(|m| m.bind().get_weapon()) } + + fn drop_ball(&mut self, with_velocity: bool) -> bool { + if let Some(weapon) = self.get_weapon() + && let Ok(_) = weapon.try_cast::() + { + self.run_deferred(|s| { + if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer + && let PeerKind::Server(peer, _) = peer + { + s.swap_weapon(WeaponType::Raygun); + peer.broadcast_reliable(Package::SwapWeapon( + s.player_id.unwrap_or(0), + WeaponType::Raygun, + )); + if let Some(mut game) = Game::singleton() { + game.bind_mut().spawn_ball(None); + } + } + }); + true + } else { + false + } + } } #[godot_api] @@ -517,6 +544,10 @@ impl IPlayer for RemotePlayer { return false; } + if self.drop_ball(true) { + return true; + } + if self.shoot_cd <= 0. { let rid = self.base().get_rid(); if let Some(mesh) = &mut self.soldier_mesh @@ -579,6 +610,30 @@ impl IPlayer for RemotePlayer { .as_ref() .and_then(|m| m.bind().get_weapon()) } + + fn drop_ball(&mut self, with_velocity: bool) -> bool { + if let Some(weapon) = self.get_weapon() + && let Ok(_) = weapon.try_cast::() + { + self.run_deferred(|s| { + if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer + && let PeerKind::Server(peer, _) = peer + { + s.swap_weapon(WeaponType::Raygun); + peer.broadcast_reliable(Package::SwapWeapon( + s.player_id.unwrap_or(0), + WeaponType::Raygun, + )); + if let Some(mut game) = Game::singleton() { + game.bind_mut().spawn_ball(None); + } + } + }); + true + } else { + false + } + } } #[godot_api] diff --git a/rust/src/weapon.rs b/rust/src/weapon.rs index 91b5bd2..e131889 100644 --- a/rust/src/weapon.rs +++ b/rust/src/weapon.rs @@ -12,7 +12,7 @@ pub trait Weapon { fn get_type(&self) -> WeaponType; } -#[derive(Debug, Clone, Copy, Deserialize, Serialize)] +#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, PartialOrd)] pub enum WeaponType { Raygun, Ball,