diff --git a/godot/scenes/player/local_player.tscn b/godot/scenes/player/local_player.tscn index ffe4a26..a3500fa 100644 --- a/godot/scenes/player/local_player.tscn +++ b/godot/scenes/player/local_player.tscn @@ -12,6 +12,7 @@ look_sensitivity = 1.5 camera = NodePath("camera_3d") move_speed = 5.0 soldier_mesh = NodePath("soldier_m") +health = 100 collision_mask = 4 [node name="camera_3d" type="Camera3D" parent="." unique_id=1773137418] diff --git a/godot/scenes/player/remote_player.tscn b/godot/scenes/player/remote_player.tscn index 6350b11..c9437c8 100644 --- a/godot/scenes/player/remote_player.tscn +++ b/godot/scenes/player/remote_player.tscn @@ -7,6 +7,7 @@ [node name="player" type="RemotePlayer" unique_id=845968872 node_paths=PackedStringArray("soldier_mesh")] move_speed = 5.0 soldier_mesh = NodePath("soldier_m") +health = 100 collision_layer = 2 collision_mask = 4 diff --git a/rust/src/net/util.rs b/rust/src/net/util.rs index ba2c279..6b072c9 100644 --- a/rust/src/net/util.rs +++ b/rust/src/net/util.rs @@ -27,20 +27,29 @@ impl From for Vector3 { } } -pub fn cast_ray(from: Vector3, to: Vector3, world: Option>) -> Option { +pub fn cast_ray( + from: Vector3, + to: Vector3, + world: Option>, + exclude: Array, +) -> Option { let ray = PhysicsRayQueryParameters3D::create(from, to); if let Some(mut ray) = ray { - ray.set_collision_mask(0b110); + ray.set_collision_mask(0b111); ray.set_hit_back_faces(false); ray.set_hit_from_inside(false); ray.set_collide_with_bodies(true); + ray.set_exclude(&exclude); if let Some(world) = world && let Some(mut space) = world.get_direct_space_state() { let results = space.intersect_ray(&ray); - if let Some(position) = results.get("position") { + if let (Some(position), Some(collider)) = + (results.get("position"), results.get("collider")) + { Some(RaycastResult { position: Vector3::from_variant(&position), + collider: Gd::from_variant(&collider), }) } else { None @@ -55,4 +64,5 @@ pub fn cast_ray(from: Vector3, to: Vector3, world: Option>) -> Optio pub struct RaycastResult { pub position: Vector3, + pub collider: Gd, } diff --git a/rust/src/player.rs b/rust/src/player.rs index 35dcc7b..8b967f5 100644 --- a/rust/src/player.rs +++ b/rust/src/player.rs @@ -44,6 +44,7 @@ pub trait IPlayer { fn get_transform(&self) -> NetPlayerTransform; fn jump(&mut self); fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool; + fn take_damage(&mut self, damage: i32); } pub trait PlayerMovement { @@ -81,6 +82,8 @@ pub struct LocalPlayer { move_speed: f32, #[export] soldier_mesh: Option>, + #[export] + health: i32, pub player_id: Option, pub weapon: Option>, @@ -156,8 +159,9 @@ impl IPlayer for LocalPlayer { fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool { if self.shoot_cd <= 0. { + let rid = self.base().get_rid(); if let Some(weapon) = &mut self.weapon { - weapon.dyn_bind_mut().shoot(to, deal_damage); + weapon.dyn_bind_mut().shoot(rid, to, deal_damage); } self.shoot_cd = 0.2; true @@ -165,6 +169,11 @@ impl IPlayer for LocalPlayer { false } } + + fn take_damage(&mut self, damage: i32) { + godot_print!("Took damage!"); + self.health -= damage; + } } #[godot_api] @@ -225,6 +234,7 @@ impl ICharacterBody3D for LocalPlayer { camera.get_global_position(), camera.get_global_position() + forward, self.base().get_world_3d(), + Array::from_iter(vec![self.base().get_rid()]), ) { Some(res) => Some(res.position), None => Some(camera.get_global_position() + forward * 100.), @@ -233,8 +243,6 @@ impl ICharacterBody3D for LocalPlayer { None }; - godot_print!("{:?}", pos); - if let Some(pos) = pos { if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer { match peer { @@ -298,6 +306,8 @@ pub struct RemotePlayer { move_speed: f32, #[export] soldier_mesh: Option>, + #[export] + health: i32, pub player_id: Option, pub weapon: Option>, @@ -369,8 +379,9 @@ impl IPlayer for RemotePlayer { fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool { if self.shoot_cd <= 0. { + let rid = self.base().get_rid(); if let Some(weapon) = &mut self.weapon { - weapon.dyn_bind_mut().shoot(to, deal_damage); + weapon.dyn_bind_mut().shoot(rid, to, deal_damage); } self.shoot_cd = 0.2; true @@ -378,6 +389,11 @@ impl IPlayer for RemotePlayer { false } } + + fn take_damage(&mut self, damage: i32) { + godot_print!("Took damage!"); + self.health -= damage; + } } #[godot_api] diff --git a/rust/src/weapon.rs b/rust/src/weapon.rs index e74adb9..f0c0b45 100644 --- a/rust/src/weapon.rs +++ b/rust/src/weapon.rs @@ -3,10 +3,10 @@ use godot::{ prelude::*, }; -use crate::net::util::cast_ray; +use crate::{net::util::cast_ray, player::IPlayer}; pub trait Weapon { - fn shoot(&mut self, to: Vector3, deal_damage: bool); + fn shoot(&mut self, player: Rid, to: Vector3, deal_damage: bool); } #[derive(GodotClass)] @@ -24,16 +24,22 @@ pub struct Raygun { #[godot_dyn] impl Weapon for Raygun { - fn shoot(&mut self, to: Vector3, deal_damage: bool) { + fn shoot(&mut self, player: Rid, to: Vector3, deal_damage: bool) { if let Some(emitter) = &mut self.sound_emitter { emitter.play(); } if let Some(source) = &self.bullet_source { - let target = cast_ray(source.get_global_position(), to, self.base().get_world_3d()); + let target = cast_ray( + source.get_global_position(), + to, + self.base().get_world_3d(), + Array::from_iter(vec![player]), + ); let dir = (to - source.get_global_position()).normalized(); let beam_end = target + .as_ref() .map(|r| r.position) .unwrap_or(source.get_global_position() + dir * 100.); @@ -47,6 +53,13 @@ impl Weapon for Raygun { parent.add_child(&bullet); } } + + if deal_damage && let Some(target) = target { + godot_print!("{}", target.collider); + if let Ok(mut player) = target.collider.try_dynify::() { + player.dyn_bind_mut().take_damage(100); + } + } } } }