Compare commits

..

No commits in common. "8eb050d10ad0e3f732cb0b95b7f03632e420113e" and "f19beaa73aa0c24c30aae3644192097835ba4c3d" have entirely different histories.

5 changed files with 191 additions and 235 deletions

View File

@ -20,7 +20,7 @@ bevy_synthizer = "0.7"
bevy_tts = { version = "0.9", default-features = false, features = ["tolk"] } bevy_tts = { version = "0.9", default-features = false, features = ["tolk"] }
coord_2d = "0.3" coord_2d = "0.3"
here_be_dragons = { version = "0.3", features = ["serde"] } here_be_dragons = { version = "0.3", features = ["serde"] }
leafwing-input-manager = "0.15" leafwing-input-manager = "0.14"
maze_generator = "2" maze_generator = "2"
once_cell = "1" once_cell = "1"
pathfinding = "4" pathfinding = "4"

View File

@ -9,7 +9,6 @@ use crate::{
core::{Player, PointLike}, core::{Player, PointLike},
error::error_handler, error::error_handler,
map::Map, map::Map,
navigation::NavigationAction,
pathfinding::Destination, pathfinding::Destination,
visibility::{RevealedTiles, Viewshed, Visible, VisibleEntities}, visibility::{RevealedTiles, Viewshed, Visible, VisibleEntities},
}; };
@ -355,25 +354,6 @@ where
Ok(()) Ok(())
} }
fn cancel_on_navigate(
mut commands: Commands,
explorers: Query<
Entity,
(
With<ActionState<ExplorationAction>>,
Changed<ActionState<NavigationAction>>,
),
>,
focused: Query<Entity, With<ExplorationFocused>>,
) {
if !explorers.is_empty() {
for entity in &focused {
println!("Clearing focus");
commands.entity(entity).remove::<ExplorationFocused>();
}
}
}
fn cleanup( fn cleanup(
mut commands: Commands, mut commands: Commands,
explorers: Query<Entity, With<Exploring>>, explorers: Query<Entity, With<Exploring>>,
@ -418,7 +398,7 @@ where
.register_type::<Explorable>() .register_type::<Explorable>()
.add_plugins(InputManagerPlugin::<ExplorationAction>::default()) .add_plugins(InputManagerPlugin::<ExplorationAction>::default())
.add_systems( .add_systems(
FixedUpdate, Update,
( (
exploration_type_change::<ExplorationType>.pipe(error_handler), exploration_type_change::<ExplorationType>.pipe(error_handler),
exploration_type_changed_announcement::<ExplorationType>.pipe(error_handler), exploration_type_changed_announcement::<ExplorationType>.pipe(error_handler),
@ -427,7 +407,7 @@ where
.in_set(Exploration), .in_set(Exploration),
) )
.add_systems( .add_systems(
FixedUpdate, Update,
( (
exploration_focus::<MapData>, exploration_focus::<MapData>,
exploration_type_focus::<ExplorationType>.pipe(error_handler), exploration_type_focus::<ExplorationType>.pipe(error_handler),
@ -437,14 +417,11 @@ where
.chain() .chain()
.in_set(Exploration), .in_set(Exploration),
) )
.add_systems( .add_systems(Update, navigate_to_explored::<MapData>.in_set(Exploration));
FixedUpdate,
(navigate_to_explored::<MapData>, cancel_on_navigate).in_set(Exploration),
);
if !config.states.is_empty() { if !config.states.is_empty() {
let states = config.states; let states = config.states;
for state in states { for state in states {
app.configure_sets(FixedUpdate, Exploration.run_if(in_state(state.clone()))) app.configure_sets(Update, Exploration.run_if(in_state(state.clone())))
.add_systems(OnExit(state), cleanup); .add_systems(OnExit(state), cleanup);
} }
} }

View File

@ -3,16 +3,17 @@ use std::{collections::HashMap, error::Error, f32::consts::PI, fmt::Debug, hash:
use bevy::prelude::*; use bevy::prelude::*;
use bevy_rapier2d::prelude::*; use bevy_rapier2d::prelude::*;
use bevy_tts::Tts; use bevy_tts::Tts;
use leafwing_input_manager::prelude::*; use leafwing_input_manager::{axislike::DualAxisData, prelude::*};
use crate::{ use crate::{
core::{Angle, Area, CardinalDirection, GlobalTransformExt, Player, TransformExt}, core::{Angle, Area, CardinalDirection, GlobalTransformExt, Player, TransformExt},
error::error_handler, error::error_handler,
exploration::{ExplorationFocused, Exploring},
log::Log, log::Log,
utils::target_and_other, utils::target_and_other,
}; };
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)] #[derive(Actionlike, PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)]
pub enum NavigationAction { pub enum NavigationAction {
Move, Move,
Translate, Translate,
@ -25,23 +26,6 @@ pub enum NavigationAction {
SnapReverse, SnapReverse,
} }
impl Actionlike for NavigationAction {
fn input_control_kind(&self) -> InputControlKind {
match &self {
NavigationAction::Move
| NavigationAction::Translate
| NavigationAction::SetLinearVelocity => InputControlKind::DualAxis,
NavigationAction::Rotate | NavigationAction::SetAngularVelocity => {
InputControlKind::Axis
}
NavigationAction::SnapLeft
| NavigationAction::SnapRight
| NavigationAction::SnapCardinal
| NavigationAction::SnapReverse => InputControlKind::Button,
}
}
}
#[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)] #[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)]
#[reflect(Component)] #[reflect(Component)]
pub struct BackwardMovementFactor(pub f32); pub struct BackwardMovementFactor(pub f32);
@ -151,6 +135,7 @@ fn tick_snap_timers(time: Res<Time>, mut snap_timers: ResMut<SnapTimers>) {
} }
fn controls( fn controls(
mut commands: Commands,
rapier_context: Res<RapierContext>, rapier_context: Res<RapierContext>,
time: Res<Time>, time: Res<Time>,
snap_timers: Res<SnapTimers>, snap_timers: Res<SnapTimers>,
@ -166,6 +151,7 @@ fn controls(
&mut Transform, &mut Transform,
&Collider, &Collider,
)>, )>,
exploration_focused: Query<Entity, With<ExplorationFocused>>,
) { ) {
for ( for (
entity, entity,
@ -180,76 +166,131 @@ fn controls(
collider, collider,
) in &mut query ) in &mut query
{ {
if !actions.action_disabled(&NavigationAction::Move) { let mut cleanup = false;
let mut direction = actions.clamped_axis_pair(&NavigationAction::Move); if actions.pressed(&NavigationAction::Move) {
let forward_movement_factor = if let Some(pair) = actions.clamped_axis_pair(&NavigationAction::Move) {
forward_movement_factor.map(|v| v.0).unwrap_or_else(|| 1.); cleanup = true;
let backward_movement_factor = let mut direction = pair.xy();
backward_movement_factor.map(|v| v.0).unwrap_or_else(|| 1.); let forward_movement_factor =
let strafe_movement_factor = strafe_movement_factor.map(|v| v.0).unwrap_or_else(|| 1.); forward_movement_factor.map(|v| v.0).unwrap_or_else(|| 1.);
let forward_backward_movement_factor = if direction.x > 0. { let backward_movement_factor =
forward_movement_factor backward_movement_factor.map(|v| v.0).unwrap_or_else(|| 1.);
} else if direction.x < 0. { let strafe_movement_factor =
backward_movement_factor strafe_movement_factor.map(|v| v.0).unwrap_or_else(|| 1.);
} else { let forward_backward_movement_factor = if direction.x > 0. {
1. forward_movement_factor
}; } else if direction.x < 0. {
let movement_factor = if direction.x != 0. && direction.y != 0. { backward_movement_factor
strafe_movement_factor.min(forward_backward_movement_factor) } else {
} else if direction.y != 0. { 1.
strafe_movement_factor };
} else { let movement_factor = if direction.x != 0. && direction.y != 0. {
forward_backward_movement_factor strafe_movement_factor.min(forward_backward_movement_factor)
}; } else if direction.y != 0. {
trace!("{entity:?}: move: {direction:?}"); strafe_movement_factor
direction = transform } else {
.compute_matrix() forward_backward_movement_factor
.transform_vector3(direction.extend(0.)) };
.truncate(); trace!("{entity:?}: move: {direction:?}");
let mut speed = **speed; direction = transform
speed *= movement_factor; .compute_matrix()
let move_velocity = direction * speed; .transform_vector3(direction.extend(0.))
// println!("{entity:?}: SetLinearVelocity: {velocity:?}"); .truncate();
actions.set_axis_pair(&NavigationAction::SetLinearVelocity, move_velocity); let mut speed = **speed;
} speed *= movement_factor;
if velocity.linvel != actions.axis_pair(&NavigationAction::SetLinearVelocity) { let velocity = direction * speed;
velocity.linvel = actions.axis_pair(&NavigationAction::SetLinearVelocity); // println!("{entity:?}: SetLinearVelocity: {velocity:?}");
} actions.press(&NavigationAction::SetLinearVelocity);
if actions.axis_pair(&NavigationAction::Translate) != Vec2::ZERO { actions
let pair = actions.axis_pair(&NavigationAction::Translate); .action_data_mut_or_default(&NavigationAction::SetLinearVelocity)
if rapier_context .axis_pair = Some(DualAxisData::from_xy(velocity));
.cast_shape(
transform.translation.truncate(),
transform.yaw().radians(),
pair,
collider,
ShapeCastOptions {
max_time_of_impact: 1.,
..default()
},
QueryFilter::new()
.exclude_sensors()
.exclude_collider(entity),
)
.is_none()
{
transform.translation += pair.extend(0.);
} }
actions.set_axis_pair(&NavigationAction::Translate, Vec2::ZERO); } else if actions.just_released(&NavigationAction::Move) {
trace!("{entity:?}: Stopped moving");
actions.release(&NavigationAction::SetLinearVelocity);
actions.release(&NavigationAction::Translate);
actions
.action_data_mut_or_default(&NavigationAction::Move)
.axis_pair = Some(DualAxisData::from_xy(Vec2::ZERO));
}
if actions.pressed(&NavigationAction::SetLinearVelocity) {
if let Some(pair) = actions.axis_pair(&NavigationAction::SetLinearVelocity) {
// println!("{entity:?}: SetLinearVelocity: {pair:?}");
velocity.linvel = pair.into();
} else {
// println!("{entity:?}: SetLinearVelocity: 0");
velocity.linvel = Vec2::ZERO;
}
} else if actions.just_released(&NavigationAction::SetLinearVelocity) {
// println!("{entity:?}: Released velocity");
velocity.linvel = Vec2::ZERO;
actions
.action_data_mut_or_default(&NavigationAction::SetLinearVelocity)
.axis_pair = None;
}
if actions.pressed(&NavigationAction::Translate) {
if let Some(pair) = actions.axis_pair(&NavigationAction::Translate) {
let vel = pair.xy();
if rapier_context
.cast_shape(
transform.translation.truncate(),
transform.yaw().radians(),
vel,
collider,
ShapeCastOptions {
max_time_of_impact: 1.,
..default()
},
QueryFilter::new()
.exclude_sensors()
.exclude_collider(entity),
)
.is_none()
{
transform.translation += vel.extend(0.);
}
}
} else if actions.just_released(&NavigationAction::Translate) {
actions
.action_data_mut_or_default(&NavigationAction::Translate)
.axis_pair = None;
} }
if !snap_timers.contains_key(&entity) { if !snap_timers.contains_key(&entity) {
if let Some(rotation_speed) = rotation_speed { if let Some(rotation_speed) = rotation_speed {
let delta = if actions.pressed(&NavigationAction::Rotate) {
-rotation_speed.radians() * actions.clamped_value(&NavigationAction::Rotate); cleanup = true;
actions.set_value(&NavigationAction::SetAngularVelocity, delta); let delta = -rotation_speed.radians()
* actions.clamped_value(&NavigationAction::Rotate);
actions.press(&NavigationAction::SetAngularVelocity);
actions
.action_data_mut_or_default(&NavigationAction::SetAngularVelocity)
.value = delta;
}
} }
} }
if actions.value(&NavigationAction::SetAngularVelocity) != 0. { if actions.just_released(&NavigationAction::Rotate) {
actions.release(&NavigationAction::SetAngularVelocity);
actions
.action_data_mut_or_default(&NavigationAction::Rotate)
.value = 0.;
}
if actions.pressed(&NavigationAction::SetAngularVelocity) {
// velocity.angvel = // velocity.angvel =
// actions.value(&NavigationAction::SetAngularVelocity); // actions.value(&NavigationAction::SetAngularVelocity);
transform.rotation *= Quat::from_rotation_z( transform.rotation *= Quat::from_rotation_z(
actions.value(&NavigationAction::SetAngularVelocity) * time.delta_seconds(), actions.value(&NavigationAction::SetAngularVelocity) * time.delta_seconds(),
); );
} else if actions.just_released(&NavigationAction::SetAngularVelocity) {
actions
.action_data_mut_or_default(&NavigationAction::SetAngularVelocity)
.value = 0.;
velocity.angvel = 0.;
}
if cleanup {
commands.entity(entity).remove::<Exploring>();
for entity in &exploration_focused {
commands.entity(entity).remove::<ExplorationFocused>();
}
} }
} }
} }
@ -395,17 +436,12 @@ where
.in_set(Movement), .in_set(Movement),
) )
.add_systems( .add_systems(
FixedUpdate, Update,
(tick_snap_timers, speak_direction.pipe(error_handler)), (tick_snap_timers, speak_direction.pipe(error_handler)),
) )
.add_systems( .add_systems(
PostUpdate, PostUpdate,
(remove_direction, log_area_descriptions::<State>), (remove_direction, log_area_descriptions::<State>),
); );
if !self.states.is_empty() {
for state in &self.states {
app.configure_sets(Update, Movement.run_if(in_state(state.clone())));
}
}
} }
} }

View File

@ -1,4 +1,5 @@
use bevy::{ use bevy::{
ecs::entity::Entities,
prelude::*, prelude::*,
tasks::{futures_lite::future, prelude::*, Task}, tasks::{futures_lite::future, prelude::*, Task},
utils::HashMap, utils::HashMap,
@ -8,7 +9,7 @@ use bevy_rapier2d::{
prelude::*, prelude::*,
rapier::prelude::{ColliderHandle, ColliderSet, QueryPipeline, RigidBodySet}, rapier::prelude::{ColliderHandle, ColliderSet, QueryPipeline, RigidBodySet},
}; };
use leafwing_input_manager::{plugin::InputManagerSystem, prelude::*}; use leafwing_input_manager::{axislike::DualAxisData, plugin::InputManagerSystem, prelude::*};
use pathfinding::prelude::*; use pathfinding::prelude::*;
use crate::{ use crate::{
@ -20,11 +21,7 @@ use crate::{
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)] #[derive(PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)]
pub struct NegotiatePathAction; pub struct NegotiatePathAction;
impl Actionlike for NegotiatePathAction { impl Actionlike for NegotiatePathAction {}
fn input_control_kind(&self) -> InputControlKind {
InputControlKind::DualAxis
}
}
#[derive(Component, Debug, Deref, DerefMut)] #[derive(Component, Debug, Deref, DerefMut)]
struct Calculating(Task<Option<Path>>); struct Calculating(Task<Option<Path>>);
@ -48,17 +45,6 @@ pub struct Path(pub Vec<(i32, i32)>);
#[reflect(Component)] #[reflect(Component)]
pub struct CostMap(pub HashMap<(i32, i32), f32>); pub struct CostMap(pub HashMap<(i32, i32), f32>);
#[derive(Bundle, Deref, DerefMut)]
pub struct PathfindingControlsBundle(pub ActionState<NegotiatePathAction>);
impl Default for PathfindingControlsBundle {
fn default() -> Self {
let mut input: ActionState<NegotiatePathAction> = Default::default();
input.disable();
Self(input)
}
}
pub fn find_path<D: 'static + Clone + Default + Send + Sync>( pub fn find_path<D: 'static + Clone + Default + Send + Sync>(
start: &dyn PointLike, start: &dyn PointLike,
destination: &dyn PointLike, destination: &dyn PointLike,
@ -175,11 +161,7 @@ fn calculate_path(
>, >,
) { ) {
for (entity, handle, destination, coordinates, shape, cost_map) in &query { for (entity, handle, destination, coordinates, shape, cost_map) in &query {
trace
!("{entity}: destination: {destination:?}");
if coordinates.i32() == **destination { if coordinates.i32() == **destination {
trace
!("{entity}: remove1");
commands commands
.entity(entity) .entity(entity)
.remove::<Path>() .remove::<Path>()
@ -229,8 +211,6 @@ fn calculate_path(
shape_clone, shape_clone,
) )
}); });
trace
!("{entity}: remove2");
commands commands
.entity(entity) .entity(entity)
.insert(Calculating(task)) .insert(Calculating(task))
@ -241,45 +221,34 @@ fn calculate_path(
fn poll_tasks( fn poll_tasks(
mut commands: Commands, mut commands: Commands,
mut query: Query<( mut query: Query<(Entity, &mut Calculating, &Transform, &Destination)>,
Entity,
&mut Calculating,
&Transform,
&Destination,
Option<&mut ActionState<NegotiatePathAction>>,
)>,
) { ) {
for (entity, mut calculating, transform, destination, actions) in &mut query { for (entity, mut calculating, transform, destination) in &mut query {
if let Some(result) = future::block_on(future::poll_once(&mut **calculating)) { if let Some(result) = future::block_on(future::poll_once(&mut **calculating)) {
if let Some(path) = result { if let Some(path) = result {
trace!("{entity:?}: Path: {path:?}"); trace!("{entity:?}: Path: {path:?}");
commands.entity(entity).insert(path); commands.entity(entity).insert(path);
} else { } else {
trace trace!(
!(
"{entity:?}: path: no path from {:?} to {:?}", "{entity:?}: path: no path from {:?} to {:?}",
transform.translation.truncate().i32(), transform.translation.truncate().i32(),
**destination **destination
); );
commands.entity(entity).insert(NoPath); commands.entity(entity).insert(NoPath);
if let Some(mut actions) = actions {
trace!("{entity:?}: Disabling and resetting because no path");
actions.disable();
actions.reset_all();
}
} }
commands.entity(entity).remove::<Calculating>(); commands.entity(entity).remove::<Calculating>();
} }
} }
} }
fn remove_destination(mut commands: Commands, mut removed: RemovedComponents<Destination>) { fn remove_destination(
mut commands: Commands,
entities: &Entities,
mut removed: RemovedComponents<Destination>,
) {
for entity in removed.read() { for entity in removed.read() {
if let Some(mut commands) = commands.get_entity(entity) { if entities.contains(entity) {
commands commands.entity(entity).remove::<Calculating>();
.remove::<Calculating>()
.remove::<Path>()
.remove::<NoPath>();
} }
} }
} }
@ -290,7 +259,6 @@ fn negotiate_path(
physics_config: Res<RapierConfiguration>, physics_config: Res<RapierConfiguration>,
mut query: Query<( mut query: Query<(
Entity, Entity,
Option<&mut ActionState<NegotiatePathAction>>,
&mut ActionState<NavigationAction>, &mut ActionState<NavigationAction>,
&mut Path, &mut Path,
&mut Transform, &mut Transform,
@ -303,18 +271,9 @@ fn negotiate_path(
if !physics_config.physics_pipeline_active || !physics_config.query_pipeline_active { if !physics_config.physics_pipeline_active || !physics_config.query_pipeline_active {
return; return;
} }
for ( for (entity, mut actions, mut path, mut transform, collider, speed, rotation_speed) in
entity, &mut query
actions,
mut navigation_actions,
mut path,
mut transform,
collider,
speed,
rotation_speed,
) in &mut query
{ {
trace!("{entity:?}: negotiating path");
let start_i32 = transform.translation.truncate().i32(); let start_i32 = transform.translation.truncate().i32();
trace!( trace!(
"{entity:?}: start pathfinding from {start_i32:?} to {:?}: at {:?}", "{entity:?}: start pathfinding from {start_i32:?} to {:?}: at {:?}",
@ -326,6 +285,7 @@ fn negotiate_path(
path.remove(0); path.remove(0);
} }
if let Some(next) = path.first() { if let Some(next) = path.first() {
trace!("{entity:?}: path: moving from {start_i32:?} to {next:?}");
let start = transform.translation.truncate(); let start = transform.translation.truncate();
let mut next = Vec2::new(next.0 as f32, next.1 as f32); let mut next = Vec2::new(next.0 as f32, next.1 as f32);
if next.x >= 0. { if next.x >= 0. {
@ -362,27 +322,22 @@ fn negotiate_path(
) )
.is_some() .is_some()
{ {
trace // trace!("{entity:?} is stuck, hit: {hit:?}, TOI: {toi:?}");
!("{entity:?} is stuck");
// TODO: Remove when we have an actual character controller. // TODO: Remove when we have an actual character controller.
next.x = next.x.trunc();
next.y = next.y.trunc();
transform.translation = next.extend(0.); transform.translation = next.extend(0.);
} else { continue;
navigation_actions.set_axis_pair(&NavigationAction::Translate, direction);
} }
trace!("{entity:?}: path: direction: {direction:?}");
actions.press(&NavigationAction::Translate);
actions
.action_data_mut_or_default(&NavigationAction::Translate)
.axis_pair = Some(DualAxisData::from_xy(direction));
if rotation_speed.is_some() { if rotation_speed.is_some() {
let angle = direction.y.atan2(direction.x); let angle = direction.y.atan2(direction.x);
transform.rotation = Quat::from_rotation_z(angle); transform.rotation = Quat::from_rotation_z(angle);
} }
} else { } else {
trace trace!("{entity:?}: empty path, cleaning");
!("{entity:?}: empty path, cleaning");
if let Some(mut actions) = actions {
trace!("{entity:?}: Disabling pathfind because at destination");
actions.reset_all();
actions.disable();
}
commands commands
.entity(entity) .entity(entity)
.remove::<Path>() .remove::<Path>()
@ -397,35 +352,46 @@ fn actions(
mut commands: Commands, mut commands: Commands,
mut query: Query<( mut query: Query<(
Entity, Entity,
&ActionState<NegotiatePathAction>, &mut ActionState<NegotiatePathAction>,
&mut ActionState<NavigationAction>, &mut ActionState<NavigationAction>,
Option<&mut Destination>, Option<&mut Destination>,
)>, )>,
) { ) {
for (entity, actions, mut navigation_action, destination) in &mut query { for (entity, mut actions, mut navigation_action, destination) in &mut query {
if actions.action_disabled(&NegotiatePathAction) { if actions.pressed(&NegotiatePathAction) {
if destination.is_some() { if let Some(pair) = actions.axis_pair(&NegotiatePathAction) {
commands.entity(entity).remove::<Destination>(); trace!("{entity:?}: Negotiating path to {pair:?}");
} let dest = Destination(pair.xy().i32());
} else { if let Some(mut current_dest) = destination {
let pair = actions.axis_pair(&NegotiatePathAction); trace!("Got a destination");
trace!("{entity:?}: Negotiating path to {pair:?}"); if *current_dest != dest {
let dest = Destination(pair.xy().i32()); trace!("{entity:?}: New destination {dest:?} differs from {current_dest:?}, zeroing velocity");
if let Some(mut current_dest) = destination { navigation_action.press(&NavigationAction::SetLinearVelocity);
trace!("Got a destination"); navigation_action
if *current_dest != dest { .action_data_mut_or_default(&NavigationAction::SetLinearVelocity)
trace .axis_pair = Some(DualAxisData::from_xy(Vec2::ZERO));
!("{entity:?}: New destination {dest:?} differs from {current_dest:?}, zeroing velocity"); *current_dest = dest;
}
} else {
trace!("{entity:?}: Adding destination, zeroing velocity");
navigation_action.press(&NavigationAction::SetLinearVelocity);
navigation_action navigation_action
.set_axis_pair(&NavigationAction::SetLinearVelocity, Vec2::ZERO); .action_data_mut_or_default(&NavigationAction::SetLinearVelocity)
*current_dest = dest; .axis_pair = Some(DualAxisData::from_xy(Vec2::ZERO));
commands.entity(entity).insert(dest);
} }
} else { } else if destination.is_some() {
trace trace!("No value, resetting");
!("{entity:?}: Adding destination, zeroing velocity"); commands
navigation_action.set_axis_pair(&NavigationAction::SetLinearVelocity, Vec2::ZERO); .entity(entity)
commands.entity(entity).insert(dest); .remove::<Destination>()
.remove::<Path>()
.remove::<NoPath>();
} }
actions.release(&NegotiatePathAction);
actions
.action_data_mut_or_default(&NegotiatePathAction)
.axis_pair = None;
} }
} }
} }
@ -439,13 +405,16 @@ impl Plugin for PathfindingPlugin {
.register_type::<NoPath>() .register_type::<NoPath>()
.register_type::<Path>() .register_type::<Path>()
.register_type::<CostMap>() .register_type::<CostMap>()
.add_systems(PreUpdate, (poll_tasks, negotiate_path).chain()) .add_systems(
FixedPreUpdate,
(poll_tasks, apply_deferred, negotiate_path).chain(),
)
.add_systems( .add_systems(
PreUpdate, PreUpdate,
(actions, calculate_path) (actions, apply_deferred, calculate_path)
.chain() .chain()
.after(InputManagerSystem::Tick), .after(InputManagerSystem::Tick),
) )
.add_systems(PostUpdate, remove_destination); .add_systems(FixedPostUpdate, remove_destination);
} }
} }

View File

@ -146,30 +146,7 @@ impl Viewshed {
}; };
if let Some((opacity, coord_entities)) = result { if let Some((opacity, coord_entities)) = result {
for e in &coord_entities { for e in &coord_entities {
let mut should_insert = true; new_visible_entities.insert(*e);
if coord_entities.len() > 1 {
let start = start.translation().truncate();
let dest = Vec2::new(coord.x as f32, coord.y as f32);
let dir = dest - start;
rapier_context.intersections_with_ray(
start,
dir,
1.,
true,
QueryFilter::new()
.exclude_sensors()
.exclude_collider(*viewer_entity)
.exclude_collider(*e)
.predicate(&|e| visible_query.contains(e)),
|_, _| {
should_insert = false;
false
},
);
}
if should_insert {
new_visible_entities.insert(*e);
}
} }
opacity opacity
} else { } else {
@ -210,7 +187,7 @@ impl Viewshed {
} }
} }
#[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Eq, PartialEq, Reflect)] #[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)]
#[reflect(Component)] #[reflect(Component)]
pub struct Visible(pub u8); pub struct Visible(pub u8);
@ -460,9 +437,6 @@ impl<MapData: 'static + Clone + Default + Send + Sync> Plugin for VisibilityPlug
update_revealed_tiles::<MapData>, update_revealed_tiles::<MapData>,
), ),
) )
.add_systems( .add_systems(FixedPostUpdate, (log_visible, viewshed_removed, remove_visible));
FixedPostUpdate,
(log_visible, viewshed_removed, remove_visible),
);
} }
} }