Propagate teleport when teleport grenade collides

This commit is contained in:
Sofia 2026-07-27 22:43:57 +03:00
parent 3a2b2d609d
commit a6e6e66d28
8 changed files with 57 additions and 3 deletions

View File

@ -15,6 +15,8 @@ size = Vector3(0.1, 0.1, 0.1)
[node name="teleport_grenade" type="Telegrenade" unique_id=1670808846]
collision_layer = 0
collision_mask = 4
contact_monitor = true
max_contacts_reported = 1
[node name="collision_shape_3d" type="CollisionShape3D" parent="." unique_id=1124839205]
shape = SubResource("SphereShape3D_1cgct")

View File

@ -1300,6 +1300,14 @@ impl Game {
character.dyn_bind_mut().try_throw_telegrenade(to.into());
}
}
pub fn handle_telegrenade_teleport(&mut self, player_id: u16, to: NetVector3) {
if let Some(player) = self.find_player_mut(player_id)
&& let Some(character) = &mut player.character
{
character.dyn_bind_mut().telegrenade_teleport(to.into());
}
}
}
#[derive(Clone, Debug)]

View File

@ -316,6 +316,7 @@ pub enum Package {
Announcement(u16, Announcement),
Pickup(u8, u16),
ThrowTelegrenade(u16, NetVector3),
TelegrenadeTeleport(u16, NetVector3),
// End-of-Game packages
FinishGame,

View File

@ -238,6 +238,11 @@ impl NetworkManager {
}
}
}
Package::TelegrenadeTeleport(player_id, to) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().handle_telegrenade_teleport(player_id, to);
}
}
_ => {}
},
},

View File

@ -341,6 +341,10 @@ impl IPlayer for LocalPlayer {
self.telegrenade.clone()
}
fn telegrenade_teleport(&mut self, to: Vector3) {
self.telegrenade_teleport_common(to);
}
fn as_gd(&self) -> DynGd<CharacterBody3D, dyn IPlayer> {
self.to_gd().into_dyn().upcast()
}

View File

@ -70,6 +70,7 @@ pub trait IPlayer {
fn try_throw_telegrenade(&mut self, to: Vector3) -> bool;
fn set_telegrenade(&mut self, telegrenade: Option<Gd<Telegrenade>>);
fn get_telegrenade(&self) -> Option<Gd<Telegrenade>>;
fn telegrenade_teleport(&mut self, to: Vector3);
fn as_gd(&self) -> DynGd<CharacterBody3D, dyn IPlayer>;
}
@ -82,6 +83,7 @@ pub trait PlayerCommon {
fn try_shoot_common(&mut self, to: Vector3, deal_damage: bool) -> bool;
fn try_punch_common(&mut self, to: Vector3, deal_damage: bool) -> bool;
fn throw_telegrenade_common(&mut self, to: Vector3) -> bool;
fn telegrenade_teleport_common(&mut self, to: Vector3);
}
impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
@ -290,6 +292,14 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
true
}
fn telegrenade_teleport_common(&mut self, to: Vector3) {
if let Some(mut telegrenade) = self.get_telegrenade() {
telegrenade.queue_free();
}
self.set_telegrenade(None);
self.base_mut().set_global_position(to);
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]

View File

@ -281,6 +281,10 @@ impl IPlayer for RemotePlayer {
self.telegrenade.clone()
}
fn telegrenade_teleport(&mut self, to: Vector3) {
self.telegrenade_teleport_common(to);
}
fn as_gd(&self) -> DynGd<CharacterBody3D, dyn IPlayer> {
self.to_gd().into_dyn().upcast()
}

View File

@ -4,7 +4,10 @@ use godot::{
};
use crate::{
net::util::NetVector3,
net::{
network_manager::{NetworkManager, Package, PeerKind},
util::NetVector3,
},
player::{IPlayer, NetTransform},
};
@ -18,11 +21,28 @@ pub struct Telegrenade {
#[godot_api]
impl IRigidBody3D for Telegrenade {
fn ready(&mut self) {}
fn ready(&mut self) {
self.base()
.signals()
.body_entered()
.connect_other(self, |s, _| s.on_collision());
}
}
impl Telegrenade {
pub fn teleport(&mut self) {}
pub fn on_collision(&mut self) {
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer
&& let PeerKind::Server(peer, _) = peer
&& let Some(mut player) = self.player.clone()
{
let pos = self.base().get_global_position();
player.dyn_bind_mut().telegrenade_teleport(pos);
peer.broadcast_reliable(Package::TelegrenadeTeleport(
player.dyn_bind().get_player_id().unwrap_or(0),
pos.into(),
));
}
}
pub fn get_transform(&self) -> NetTransform {
NetTransform {