From d4f4dc43b0d890dd8f5f4d792d865ea494568d8a Mon Sep 17 00:00:00 2001 From: Sofia Date: Mon, 20 Jul 2026 20:44:49 +0300 Subject: [PATCH] Improve how raycasting is done --- rust/src/net/util.rs | 35 ++++++++++++++++++++++++++++++++++- rust/src/player.rs | 30 +++++++----------------------- rust/src/weapon.rs | 23 ++++++++++++++++------- 3 files changed, 57 insertions(+), 31 deletions(-) diff --git a/rust/src/net/util.rs b/rust/src/net/util.rs index ed1ea00..ba2c279 100644 --- a/rust/src/net/util.rs +++ b/rust/src/net/util.rs @@ -1,4 +1,7 @@ -use godot::prelude::*; +use godot::{ + classes::{PhysicsRayQueryParameters3D, World3D}, + prelude::*, +}; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, Serialize, Deserialize)] @@ -23,3 +26,33 @@ impl From for Vector3 { Vector3::new(value.x, value.y, value.z) } } + +pub fn cast_ray(from: Vector3, to: Vector3, world: Option>) -> Option { + let ray = PhysicsRayQueryParameters3D::create(from, to); + if let Some(mut ray) = ray { + ray.set_collision_mask(0b110); + ray.set_hit_back_faces(false); + ray.set_hit_from_inside(false); + ray.set_collide_with_bodies(true); + 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") { + Some(RaycastResult { + position: Vector3::from_variant(&position), + }) + } else { + None + } + } else { + None + } + } else { + None + } +} + +pub struct RaycastResult { + pub position: Vector3, +} diff --git a/rust/src/player.rs b/rust/src/player.rs index e39db1c..35dcc7b 100644 --- a/rust/src/player.rs +++ b/rust/src/player.rs @@ -17,7 +17,7 @@ use crate::{ Package::{Jump, Shoot}, PeerKind, }, - util::NetVector3, + util::{NetVector3, cast_ray}, }, soldier_mesh::SoldierMesh, ui::cli::CommandLinePanel, @@ -221,29 +221,13 @@ impl ICharacterBody3D for LocalPlayer { if event.is_action_pressed("shoot") { let pos = if let Some(camera) = &self.camera { let forward = camera.get_global_basis().col_c().neg(); - let ray = PhysicsRayQueryParameters3D::create( + match cast_ray( camera.get_global_position(), - camera.get_global_position() + forward * 10000., - ); - if let Some(mut ray) = ray { - ray.set_collision_mask(0b110); - ray.set_hit_back_faces(false); - ray.set_hit_from_inside(false); - ray.set_collide_with_bodies(true); - if let Some(world) = self.base().get_world_3d() - && let Some(mut space) = world.get_direct_space_state() - { - let results = space.intersect_ray(&ray); - if let Some(position) = results.get("position") { - Some(Vector3::from_variant(&position)) - } else { - Some(camera.get_global_position() + forward * 100.) - } - } else { - None - } - } else { - None + camera.get_global_position() + forward, + self.base().get_world_3d(), + ) { + Some(res) => Some(res.position), + None => Some(camera.get_global_position() + forward * 100.), } } else { None diff --git a/rust/src/weapon.rs b/rust/src/weapon.rs index 49eb62b..e74adb9 100644 --- a/rust/src/weapon.rs +++ b/rust/src/weapon.rs @@ -3,6 +3,8 @@ use godot::{ prelude::*, }; +use crate::net::util::cast_ray; + pub trait Weapon { fn shoot(&mut self, to: Vector3, deal_damage: bool); } @@ -27,16 +29,23 @@ impl Weapon for Raygun { emitter.play(); } - if let Some(prefab) = &self.bullet_prefab { - let mut bullet = prefab.instantiate_as::(); + if let Some(source) = &self.bullet_source { + let target = cast_ray(source.get_global_position(), to, self.base().get_world_3d()); + + let dir = (to - source.get_global_position()).normalized(); + let beam_end = target + .map(|r| r.position) + .unwrap_or(source.get_global_position() + dir * 100.); + + if let Some(prefab) = &self.bullet_prefab { + let mut bullet = prefab.instantiate_as::(); - if let Some(source) = &self.bullet_source { bullet.bind_mut().source = Some(source.get_global_position()); - } - bullet.bind_mut().target = Some(to); + bullet.bind_mut().target = Some(beam_end); - if let Some(mut parent) = self.base().find_parent("map") { - parent.add_child(&bullet); + if let Some(mut parent) = self.base().find_parent("map") { + parent.add_child(&bullet); + } } } }