Make sure that ball cannot be picked up by the same player instantly

This commit is contained in:
Sofia 2026-07-21 21:54:09 +03:00
parent b93cb1eb39
commit 179f10e449
5 changed files with 38 additions and 13 deletions

View File

@ -8,6 +8,10 @@ use crate::player::{IPlayer, NetTransform};
#[derive(GodotClass)]
#[class(base=RigidBody3D, init)]
pub struct Ball {
pub dropper: Option<u16>,
alive_for: f64,
base: Base<RigidBody3D>,
}
@ -19,6 +23,10 @@ impl IRigidBody3D for Ball {
.body_entered()
.connect_other(self, |s, body| s.on_collision(body));
}
fn process(&mut self, delta: f64) {
self.alive_for += delta;
}
}
#[godot_api]
@ -37,6 +45,12 @@ impl Ball {
if let Ok(player) = node.try_dynify::<dyn IPlayer>()
&& let Some(player_id) = player.dyn_bind().get_player_id()
{
if let Some(dropper_id) = self.dropper
&& dropper_id == player_id
&& self.alive_for < 1.0
{
return;
}
self.run_deferred(move |s| s.signals().on_ball_pickup().emit(player_id));
}
}

View File

@ -303,27 +303,30 @@ impl Game {
for player in s.players.clone() {
s.spawn_player_server(player.id);
}
s.spawn_ball(None);
s.spawn_ball(None, None);
});
}
}
}
pub fn spawn_ball(&mut self, transform: Option<NetTransform>) {
pub fn spawn_ball(&mut self, transform: Option<NetTransform>, player_id: Option<u16>) {
if let Some(map) = &mut self.current_map {
let ball = map.bind_mut().spawn_ball(transform);
let ball = map.bind_mut().spawn_ball(transform, player_id);
if let Some(ball) = &ball {
self.world_ball = Some(ball.clone());
ball.signals()
.on_ball_pickup()
.connect_other(self, |s, player_id| s.handle_ball_pickup(player_id));
}
self.run_deferred(|_| {
self.run_deferred(move |_| {
if let Some(ball) = ball
&& let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer
&& let PeerKind::Server(peer, _) = peer
{
peer.broadcast_reliable(Package::SpawnBall(ball.bind().get_transform()));
peer.broadcast_reliable(Package::SpawnBall(
ball.bind().get_transform(),
player_id,
));
}
});
}

View File

@ -90,11 +90,16 @@ impl Map {
}
}
pub fn spawn_ball(&mut self, transform: Option<NetTransform>) -> Option<Gd<Ball>> {
pub fn spawn_ball(
&mut self,
transform: Option<NetTransform>,
player_id: Option<u16>,
) -> Option<Gd<Ball>> {
if let Some(ball_spawner) = self.ball_spawner.clone()
&& let Some(ball_prefab) = &self.ball
{
let mut ball = ball_prefab.instantiate_as::<Ball>();
ball.bind_mut().dropper = player_id;
self.base_mut().add_child(&ball);
if let Some(transform) = transform {
ball.set_global_position(transform.location.into());

View File

@ -258,9 +258,9 @@ impl INode for NetworkManager {
.handle_kill(source_player_id, target_player_id);
}
}
Package::SpawnBall(transform) => {
Package::SpawnBall(transform, player_id) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().spawn_ball(Some(transform));
game.bind_mut().spawn_ball(Some(transform), player_id);
}
}
Package::DespawnBall => {
@ -594,7 +594,7 @@ pub enum Package {
Shoot(u16, NetVector3, NetTransform, f32),
TakeDamage(DamageSource, u16, i32),
Kill(DamageSource, u16),
SpawnBall(NetTransform),
SpawnBall(NetTransform, Option<u16>),
DespawnBall,
SwapWeapon(u16, WeaponType),
}

View File

@ -98,10 +98,13 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerMovement for T {
));
if let Some(mut game) = Game::singleton() {
if let Some(ball_origin) = &s.get_ball_origin() {
game.bind_mut().spawn_ball(Some(NetTransform {
location: ball_origin.get_global_position().into(),
rotation: ball_origin.get_global_rotation().into(),
}));
game.bind_mut().spawn_ball(
Some(NetTransform {
location: ball_origin.get_global_position().into(),
rotation: ball_origin.get_global_rotation().into(),
}),
s.get_player_id(),
);
}
}
}