Implement footstepbox checking with raycasts

This commit is contained in:
Sofia 2026-08-07 22:22:39 +03:00
parent c530cfedba
commit 7fc2da4800
4 changed files with 21 additions and 13 deletions

View File

@ -901,6 +901,7 @@ impl LocalPlayer {
camera.get_global_position() + forward, camera.get_global_position() + forward,
&self.base().get_world_3d(), &self.base().get_world_3d(),
&Array::from_iter(vec![self.base().get_rid()]), &Array::from_iter(vec![self.base().get_rid()]),
None,
) { ) {
Some(res) => Some(res.position), Some(res) => Some(res.position),
None => Some(camera.get_global_position() + forward * 100.), None => Some(camera.get_global_position() + forward * 100.),

View File

@ -18,7 +18,7 @@ use crate::{
telegrenade::Telegrenade, telegrenade::Telegrenade,
weapon::{BallWeapon, Weapon, WeaponType}, weapon::{BallWeapon, Weapon, WeaponType},
}, },
util::shotgun_ray, util::{cast_ray, shotgun_ray},
}; };
pub mod ball; pub mod ball;
@ -110,16 +110,18 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
self.base_mut().set_velocity(speed); self.base_mut().set_velocity(speed);
self.base_mut().move_and_slide(); self.base_mut().move_and_slide();
if let Some(collision) = self.base().get_last_slide_collision() if self.base().is_on_floor() {
&& let Some(collider) = collision.get_collider() if let Some(result) = cast_ray(
{ self.base().get_global_position() + Vector3::UP,
// Detect if it's floor we're contacting with self.base().get_global_position() + Vector3::DOWN,
if collision.get_normal().dot(self.base().get_floor_normal()) > 0.95 { &self.base().get_world_3d(),
if let Ok(footstep_box) = collider.try_cast::<FootstepBox>() { &Array::new(),
self.set_walk_kind(footstep_box.bind().kind); Some(0b100),
} else { ) && let Ok(footstep_box) = result.collider.try_cast::<FootstepBox>()
self.set_walk_kind(FootstepKind::default()); {
} self.set_walk_kind(footstep_box.bind().kind);
} else {
self.set_walk_kind(FootstepKind::default());
} }
} }
} }
@ -262,6 +264,7 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
10, 10,
PI / 2., PI / 2.,
2., 2.,
None,
); );
let mut colliders = HashSet::new(); let mut colliders = HashSet::new();

View File

@ -92,6 +92,7 @@ impl Weapon for Raygun {
to, to,
&self.base().get_world_3d(), &self.base().get_world_3d(),
&Array::from_iter(vec![player]), &Array::from_iter(vec![player]),
None,
); );
if play_fx { if play_fx {
@ -231,6 +232,7 @@ impl Weapon for Shotgun {
10, 10,
PI / 2., PI / 2.,
10., 10.,
None,
); );
if play_fx { if play_fx {
let mut bullet_decal_results = Vec::new(); let mut bullet_decal_results = Vec::new();

View File

@ -8,10 +8,11 @@ pub fn cast_ray(
to: Vector3, to: Vector3,
world: &Option<Gd<World3D>>, world: &Option<Gd<World3D>>,
exclude: &Array<Rid>, exclude: &Array<Rid>,
mask: Option<u32>,
) -> Option<RaycastResult> { ) -> Option<RaycastResult> {
let ray = PhysicsRayQueryParameters3D::create(from, to); let ray = PhysicsRayQueryParameters3D::create(from, to);
if let Some(mut ray) = ray { if let Some(mut ray) = ray {
ray.set_collision_mask(0b1111); ray.set_collision_mask(mask.unwrap_or(0b1111));
ray.set_hit_back_faces(false); ray.set_hit_back_faces(false);
ray.set_hit_from_inside(false); ray.set_hit_from_inside(false);
ray.set_collide_with_bodies(true); ray.set_collide_with_bodies(true);
@ -49,6 +50,7 @@ pub fn shotgun_ray(
density: u8, density: u8,
angle: f32, angle: f32,
distance: f32, distance: f32,
mask: Option<u32>,
) -> Vec<RaycastResult> { ) -> Vec<RaycastResult> {
let mut results = Vec::new(); let mut results = Vec::new();
@ -64,7 +66,7 @@ pub fn shotgun_ray(
let x_rot = -(angle / 2.) + step * x as f32; let x_rot = -(angle / 2.) + step * x as f32;
let dir = original_dir.rotated(up, x_rot).rotated(right, y_rot); let dir = original_dir.rotated(up, x_rot).rotated(right, y_rot);
let to = from + dir * distance; let to = from + dir * distance;
if let Some(res) = cast_ray(from, to, world, exclude) { if let Some(res) = cast_ray(from, to, world, exclude, mask) {
results.push(res); results.push(res);
} }
} }