diff --git a/src/aim/mod.rs b/src/aim/mod.rs index 09cf996..6e22cc0 100644 --- a/src/aim/mod.rs +++ b/src/aim/mod.rs @@ -4,9 +4,11 @@ use crate::{ GameState, billboards::Billboard, loading_assets::UIAssets, + physics_layers::GameLayer, player::{Player, PlayerRig}, tb_entities::EnemySpawn, }; +use avian3d::prelude::*; use bevy::prelude::*; use bevy_sprite3d::{Sprite3dBuilder, Sprite3dParams}; use ops::sin; @@ -93,6 +95,7 @@ fn update( query: Query<(Entity, &Transform), With>, player_pos: Query<&Transform, With>, player_rot: Query<&Transform, With>, + spatial_query: SpatialQuery, ) { let Some(player_pos) = player_pos.iter().next().map(|t| t.translation) else { return; @@ -117,6 +120,10 @@ fn update( let angle = player_forward.angle_between(delta.normalize()); if angle < state.max_angle && distance < target_distance { + if !line_of_sight(&spatial_query, player_pos, delta, distance) { + continue; + } + new_target = Some(e); target_distance = distance; } @@ -139,6 +146,32 @@ fn update( } } +fn line_of_sight( + spatial_query: &SpatialQuery<'_, '_>, + player_pos: Vec3, + delta: Vec3, + distance: f32, +) -> bool { + if let Some(_hit) = spatial_query.cast_shape( + &Collider::sphere(0.1), + player_pos + -delta.normalize(), + Quat::default(), + Dir3::new(-delta).unwrap(), + &ShapeCastConfig { + max_distance: distance * 0.98, + compute_contact_on_penetration: false, + ignore_origin_penetration: true, + ..Default::default() + }, + &SpatialQueryFilter::default().with_mask(LayerMask(GameLayer::Level.to_bits())), + ) { + // info!("no line of sight"); + return false; + }; + + true +} + fn move_marker(mut query: Query<&mut Transform, With>, time: Res