From 0ce3d03e1f12f1b490b64be0b4fdeec76ebbc397 Mon Sep 17 00:00:00 2001
From: yuni <hut@hut.pm>
Date: Sat, 30 Nov 2024 03:23:25 +0100
Subject: [PATCH] rewrite handle_wants_acceleration() using MatchVelocityTarget

---
 src/actor.rs | 95 +++++++++++-----------------------------------------
 1 file changed, 19 insertions(+), 76 deletions(-)

diff --git a/src/actor.rs b/src/actor.rs
index 685eafb..a6c1692 100644
--- a/src/actor.rs
+++ b/src/actor.rs
@@ -791,17 +791,15 @@ fn handle_wants_rotation_change(mut q_actor: Query<(&mut Rotation, &mut WantsRot
 fn handle_wants_acceleration(
     time: Res<Time>,
     settings: Res<var::Settings>,
-    jupiter_pos: Res<game::JupiterPos>,
     q_audiosinks: Query<(&audio::Sfx, &AudioSink)>,
     mut q_actor: Query<
         (
-            Entity,
             &Transform,
             &Position,
             &mut LinearVelocity,
+            &MatchingVelocityTarget,
             Option<&mut Engine>,
             Option<&WantsAcceleration>,
-            Option<&hud::IsTargeted>,
             Option<&PlayerCamera>,
         ),
         (Without<visual::IsEffect>, Without<HiddenInsideVehicle>),
@@ -809,78 +807,25 @@ fn handle_wants_acceleration(
     mut ew_effect: EventWriter<visual::SpawnEffectEvent>,
 ) {
     let dt = time.delta_seconds();
-
-    // Vector elements: (Entity, is_player, pos)
-    let mut request_closest: Vec<(Entity, bool, DVec3)> = vec![];
-    let mut closest_map: HashMap<Entity, DVec3> = HashMap::new();
-
-    // First, determine whether any actor wants to brake (=match velocity)
-    for (entity, _, pos, _, _, accel, _, is_player) in &mut q_actor {
-        if accel.is_some() && accel.unwrap().brake {
-            request_closest.push((entity, is_player.is_some(), pos.0.clone()));
-        }
-    }
-
-    // If an actor is braking, find out relative to what it wants to brake
-    for (entity, is_player, pos) in &request_closest {
-        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 {
-            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 - 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 - 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);
-        }
-    }
-
-    // Finally, apply the requested acceleration to the actor's velocity
     let mut play_thruster_sound = false;
     let mut players_engine: Option<Engine> = None;
-    for (entity, trans, pos, mut v, engine, accel, _, is_player) in &mut q_actor {
-        let mut thruster_on = false;
+
+    for (trans, pos, mut v, matching, engine, accel, is_player) in &mut q_actor {
+        // Apply the requested acceleration to the actor's velocity
         if let (Some(mut engine), Some(accel)) = (engine, accel) {
+            let mut thruster_on = false;
             let mut delta_v = DVec3::ZERO;
             let mut allow_fullstop = false;
             let boost = engine.current_boost_factor;
             engine.currently_matching_velocity = false;
 
             if accel.brake {
-                if let Some(target_v) = closest_map.get(&entity) {
-                    let stop_direction = (*target_v - v.0).as_vec3();
-                    if stop_direction.length_squared() > 0.003 {
-                        delta_v =
-                            (trans.rotation.inverse() * stop_direction.normalize()).as_dvec3();
-                        engine.currently_matching_velocity = true;
-                        thruster_on = true; // is this redundant?
-                    }
+                let stop_direction = (matching.v - v.0).as_vec3();
+                if stop_direction.length_squared() > 0.003 {
+                    delta_v =
+                        (trans.rotation.inverse() * stop_direction.normalize()).as_dvec3();
+                    engine.currently_matching_velocity = true;
+                    thruster_on = true; // is this redundant?
                 }
             }
 
@@ -922,16 +867,14 @@ fn handle_wants_acceleration(
 
                 // Apply acceleration to velocity
                 if allow_fullstop {
-                    if let Some(target_v) = closest_map.get(&entity) {
-                        // Prevent overshooting when matching velocity, which
-                        // would result in oscillating acceleration back and forth
-                        for axis in 0..3 {
-                            let original = v[axis];
-                            let target = target_v[axis];
-                            v[axis] += final_accel[axis];
-                            if (original - target).signum() != (v[axis] - target).signum() {
-                                v[axis] = target;
-                            }
+                    // Prevent overshooting when matching velocity, which
+                    // would result in oscillating acceleration back and forth
+                    for axis in 0..3 {
+                        let original = v[axis];
+                        let target = matching.v[axis];
+                        v[axis] += final_accel[axis];
+                        if (original - target).signum() != (v[axis] - target).signum() {
+                            v[axis] = target;
                         }
                     }
                 } else {