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) {
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));
}
});
}
}

View File

@ -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,
);
}
}
_ => {}

View File

@ -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<DynGd<Node3D, dyn Weapon>>;
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::<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]
@ -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::<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]

View File

@ -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,