Implement dropping the ball

This commit is contained in:
Sofia 2026-07-21 21:41:58 +03:00
parent ba7da5614c
commit a5e1a945a8
4 changed files with 87 additions and 17 deletions

View File

@ -330,24 +330,35 @@ impl Game {
} }
pub fn handle_ball_pickup(&mut self, player_id: u16) { pub fn handle_ball_pickup(&mut self, player_id: u16) {
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer if NetworkManager::singleton().bind_mut().is_host() {
&& let PeerKind::Server(peer, _) = peer
{
self.despawn_ball(); self.despawn_ball();
if let Some(player) = self.find_player_mut(player_id) self.run_deferred(move |s| s.handle_swap_weapon(player_id, WeaponType::Ball, true));
&& let Some(character) = &mut player.character
{
character.dyn_bind_mut().swap_weapon(WeaponType::Ball);
peer.broadcast_reliable(Package::SwapWeapon(player.id, WeaponType::Ball));
}
} }
} }
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) if let Some(player) = self.find_player_mut(player_id)
&& let Some(character) = &mut player.character && let Some(character) = &mut player.character
{ {
character.dyn_bind_mut().swap_weapon(weapon_type); 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));
}
});
} }
} }

View File

@ -270,7 +270,11 @@ impl INode for NetworkManager {
} }
Package::SwapWeapon(id, weapon_type) => { Package::SwapWeapon(id, weapon_type) => {
if let Some(game) = &mut Game::singleton() { 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,
);
} }
} }
_ => {} _ => {}

View File

@ -15,14 +15,14 @@ use crate::{
net::{ net::{
network_manager::{ network_manager::{
NetworkManager, NetworkManager,
Package::{Jump, Shoot}, Package::{self, Jump, Shoot},
PeerKind, PeerKind,
}, },
util::{NetVector3, cast_ray}, util::{NetVector3, cast_ray},
}, },
soldier_mesh::SoldierMesh, soldier_mesh::SoldierMesh,
ui::cli::CommandLinePanel, ui::cli::CommandLinePanel,
weapon::{Weapon, WeaponType}, weapon::{BallWeapon, Weapon, WeaponType},
}; };
#[derive(Debug, Clone, Copy, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
@ -51,6 +51,7 @@ pub trait IPlayer {
fn dead_for(&self) -> f64; fn dead_for(&self) -> f64;
fn swap_weapon(&mut self, weapon: WeaponType); fn swap_weapon(&mut self, weapon: WeaponType);
fn get_weapon(&self) -> Option<DynGd<Node3D, dyn Weapon>>; fn get_weapon(&self) -> Option<DynGd<Node3D, dyn Weapon>>;
fn drop_ball(&mut self, with_velocity: bool) -> bool;
} }
pub trait PlayerMovement { pub trait PlayerMovement {
@ -183,11 +184,13 @@ impl IPlayer for LocalPlayer {
return false; return false;
} }
if self.drop_ball(true) {
return true;
}
if self.shoot_cd <= 0. { if self.shoot_cd <= 0. {
let rid = self.base().get_rid(); let rid = self.base().get_rid();
if let Some(mesh) = &mut self.soldier_mesh if let Some(mut weapon) = self.get_weapon() {
&& let Some(mut weapon) = mesh.bind().get_weapon()
{
weapon weapon
.dyn_bind_mut() .dyn_bind_mut()
.shoot(rid, self.player_id.unwrap_or(0), to, deal_damage); .shoot(rid, self.player_id.unwrap_or(0), to, deal_damage);
@ -248,6 +251,30 @@ impl IPlayer for LocalPlayer {
.as_ref() .as_ref()
.and_then(|m| m.bind().get_weapon()) .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::<BallWeapon>()
{
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] #[godot_api]
@ -517,6 +544,10 @@ impl IPlayer for RemotePlayer {
return false; return false;
} }
if self.drop_ball(true) {
return true;
}
if self.shoot_cd <= 0. { if self.shoot_cd <= 0. {
let rid = self.base().get_rid(); let rid = self.base().get_rid();
if let Some(mesh) = &mut self.soldier_mesh if let Some(mesh) = &mut self.soldier_mesh
@ -579,6 +610,30 @@ impl IPlayer for RemotePlayer {
.as_ref() .as_ref()
.and_then(|m| m.bind().get_weapon()) .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::<BallWeapon>()
{
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] #[godot_api]

View File

@ -12,7 +12,7 @@ pub trait Weapon {
fn get_type(&self) -> WeaponType; fn get_type(&self) -> WeaponType;
} }
#[derive(Debug, Clone, Copy, Deserialize, Serialize)] #[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, PartialOrd)]
pub enum WeaponType { pub enum WeaponType {
Raygun, Raygun,
Ball, Ball,