From 3e3542cb10010488d07d3deeec6fb8aabb738665 Mon Sep 17 00:00:00 2001 From: Matt Dallmeyer Date: Thu, 16 Apr 2026 05:52:51 -0700 Subject: [PATCH] [jak3] Prevent NaN-induced infinite loop in ff-squad-control bubble sort (#4225) This bit of ff-squad-control code is trying to sort guards based on their distance from some shared target. In some cases the `vector-vector-distance` returns NaN. In the bubble sort below this change, the < operation always returns #t when NaN is involved, so the NaN guard gets swapped back and forth endlessly, causing an infinite loop. --- goal_src/jak3/engine/math/math.gc | 3 +++ goal_src/jak3/levels/city/common/ff-squad-control.gc | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/goal_src/jak3/engine/math/math.gc b/goal_src/jak3/engine/math/math.gc index 5dc2bbe684..af929bc3ca 100644 --- a/goal_src/jak3/engine/math/math.gc +++ b/goal_src/jak3/engine/math/math.gc @@ -10,6 +10,9 @@ `(.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) ) +(defmacro is-nan? (flt) + `(and (< 0.0 ,flt) (< ,flt 0.0))) + ;; DECOMP BEGINS (defun truncate ((arg0 float)) diff --git a/goal_src/jak3/levels/city/common/ff-squad-control.gc b/goal_src/jak3/levels/city/common/ff-squad-control.gc index a9e17a8094..4f17faa3b1 100644 --- a/goal_src/jak3/levels/city/common/ff-squad-control.gc +++ b/goal_src/jak3/levels/city/common/ff-squad-control.gc @@ -186,8 +186,12 @@ (when (and s2-0 (not (focus-test? s2-0 dead inactive)) (= (-> s2-0 target-status handle) (-> arg2 handle))) (set! (-> sv-176 sv-184) s2-0) (set! (-> sv-180 sv-184) (vector-vector-distance (-> s2-0 root trans) (-> arg2 position))) - (set! sv-184 (+ sv-184 1)) - (set! (-> s2-0 move-index) -1) + ;; og:preserve-this only add guard to the list if their distance isn't NaN + ;; any < operation involving NaN will return #t, causing infinite loop in bubble sort below + (when (not (is-nan? (-> sv-180 sv-184))) + (set! sv-184 (+ sv-184 1)) + (set! (-> s2-0 move-index) -1) + ) ) ) )