From 67703072d7b27a0a8286e8508119b1c5d970e840 Mon Sep 17 00:00:00 2001 From: yuni <hut@hut.pm> Date: Sat, 30 Nov 2024 02:49:12 +0100 Subject: [PATCH] implement update_matching_velocity_target() --- src/actor.rs | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/cmd.rs | 2 +- src/hud.rs | 8 +++-- src/main.rs | 2 +- 4 files changed, 92 insertions(+), 6 deletions(-) diff --git a/src/actor.rs b/src/actor.rs index 477e802..685eafb 100644 --- a/src/actor.rs +++ b/src/actor.rs @@ -79,6 +79,7 @@ impl Plugin for ActorPlugin { handle_input.run_if(in_control).run_if(game_running), handle_collisions.run_if(game_running), handle_damage.run_if(game_running), + update_matching_velocity_target.run_if(game_running), ), ); app.add_systems( @@ -86,6 +87,10 @@ impl Plugin for ActorPlugin { (handle_vehicle_enter_exit.run_if(game_running),), ); app.add_event::<VehicleEnterExitEvent>(); + app.insert_resource(MatchingVelocityTargetUpdateTimer(Timer::from_seconds( + 0.25, + TimerMode::Repeating, + ))); } } @@ -173,11 +178,13 @@ impl Default for ExperiencesGForce { } #[derive(Component, Default)] -pub struct MatchingVelocity { +pub struct MatchingVelocityTarget { pub entity: Option<Entity>, pub pos: Option<DVec3>, pub v: DVec3, } +#[derive(Resource)] +pub struct MatchingVelocityTargetUpdateTimer(Timer); #[derive(Component, Default)] pub struct WantsAcceleration { @@ -1221,3 +1228,80 @@ fn handle_atmosphere( settings.atmo_drag = None; } } + +pub fn update_matching_velocity_target( + time: Res<Time>, + mut timer: ResMut<MatchingVelocityTargetUpdateTimer>, + jupiter_pos: Res<game::JupiterPos>, + mut q_actor: Query< + ( + Entity, + &Transform, + &Position, + &mut LinearVelocity, + Option<&mut MatchingVelocityTarget>, + Option<&WantsAcceleration>, + Option<&hud::IsTargeted>, + Option<&PlayerCamera>, + ), + (Without<visual::IsEffect>, Without<HiddenInsideVehicle>), + >, +) { + if timer.0.tick(time.delta()).just_finished() { + return; + } + + let mut closest_map: HashMap<Entity, DVec3> = HashMap::new(); + + for (entity, _, pos, _, matching, _, _, is_player) in &q_actor { + // We only care about entities that ever need to match their velocity + if matching.is_none() { + continue; + } + + let mut target_v: Option<DVec3> = None; + + // First, if this is the player, check whether they targeted anything + // so we can match velocity to the target. + if is_player.is_some() { + for (_, _, _, v, _, _, is_target, _) in &q_actor { + if is_target.is_some() { + target_v = Some(v.0); + break; + } + } + } + + // If not, simply look for the closest object and match velocity to that. + if target_v.is_none() { + let mut closest_distance = camera::MAX_DIST_FOR_MATCH_VELOCITY; + for (testentity, _, testpos, v, _, _, _, _) in &q_actor { + if entity != testentity { + let distance = (pos.0 - testpos.0).length(); + if distance < closest_distance { + target_v = Some(v.0); + closest_distance = distance; + } + } + } + } + + // Last resort: Match velocity to the orbital velocity around Jupiter + if target_v.is_none() { + let relative_pos = pos.0 - jupiter_pos.0; + target_v = Some(nature::orbital_velocity(relative_pos, nature::JUPITER_MASS)); + } + + if let Some(target_v) = target_v { + closest_map.insert(entity, target_v); + } + } + + for (entity, _, _, _, matching, _, _, _) in &mut q_actor { + if let Some(mut matching) = matching { + if let Some(target_v) = closest_map.get(&entity) { + matching.v = *target_v; + } + } + } +} diff --git a/src/cmd.rs b/src/cmd.rs index 151b8b8..ca433fa 100644 --- a/src/cmd.rs +++ b/src/cmd.rs @@ -1513,7 +1513,7 @@ fn spawn_entities( actor.insert(actor::ExperiencesAtmosphere); } if state.is_player || state.is_vehicle { - actor.insert(MatchingVelocity::default()); + actor.insert(MatchingVelocityTarget::default()); // previously used to apply mouse movement to actor rotation, but currently unused actor.insert(ExternalTorque::ZERO.with_persistence(false)); } diff --git a/src/hud.rs b/src/hud.rs index 40e3d05..3f7e586 100644 --- a/src/hud.rs +++ b/src/hud.rs @@ -1338,7 +1338,10 @@ fn update_target_selectagon( fn update_motion_marker( settings: Res<Settings>, - q_player: Query<(&Transform, &LinearVelocity, &MatchingVelocity), With<actor::PlayerCamera>>, + q_player: Query< + (&Transform, &LinearVelocity, &MatchingVelocityTarget), + With<actor::PlayerCamera>, + >, mut q_retrograde: Query< (&mut Transform, &mut Visibility), (With<MarkerMotionRetrograde>, Without<actor::PlayerCamera>), @@ -1350,8 +1353,7 @@ fn update_motion_marker( let dv = player_v.0 - player_mv.v; if dv.length() > 1.0 { *vis = Visibility::Inherited; - trans.translation = - player_trans.translation - (dv.as_vec3().normalize() * 2.0); + trans.translation = player_trans.translation - (dv.as_vec3().normalize() * 2.0); trans.look_at(player_trans.translation, player_trans.up()); } else { *vis = Visibility::Hidden; diff --git a/src/main.rs b/src/main.rs index f024094..b43204e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,7 +34,7 @@ pub mod prelude { pub use crate::{ actor, audio, camera, chat, cmd, common, game, hud, load, menu, nature, var, visual, world, }; - pub use actor::MatchingVelocity; + pub use actor::MatchingVelocityTarget; pub use game::Cycle::Next; pub use game::Turn::Toggle; pub use game::{GameEvent, Turn};