;;-*-Lisp-*-
(in-package goal)

;; name: joint-mod.gc
;; name in dgo: joint-mod
;; dgos: GAME

(define-extern joint-mod-look-at-handler (function cspace transformq none :behavior process))
(define-extern joint-mod-world-look-at-handler (function cspace transformq none :behavior process))
(define-extern joint-mod-rotate-handler (function cspace transformq none :behavior process))
(define-extern joint-mod-joint-set-handler (function cspace transformq none :behavior process))
(define-extern joint-mod-joint-set-world-handler (function cspace transformq none :behavior process))
(define-extern joint-mod-joint-set*-handler (function cspace transformq none :behavior process))
(define-extern joint-mod-joint-set*-world-handler (function cspace transformq none :behavior process))
(define-extern joint-mod-polar-look-at-callback (function cspace transformq none :behavior process))

;; DECOMP BEGINS

;; WARN: Return type mismatch matrix vs none.
;; WARN: Function joint-mod-ik-callback has a return type of none, but the expression builder found a return statement.
(defbehavior joint-mod-ik-callback process ((arg0 cspace) (arg1 transformq))
  "Inverse kinematics joint mod callback.
   Despite the arm-related names, can be used on legs too."
  (local-vars
    (sv-352 vector)
    (sv-356 vector)
    (sv-360 vector)
    (sv-364 vector)
    (sv-368 quaternion)
    (sv-372 quaternion)
    (sv-768 matrix)
    (sv-784 vector)
    )
  (rlet ((vf0 :class vf)
         (vf4 :class vf)
         (vf5 :class vf)
         (vf6 :class vf)
         )
    (init-vf0-vector)
    (let ((gp-0 (the-as joint-mod-ik (-> arg0 param1))))
      (-> arg0 param2)
      (cspace<-parented-transformq-joint! arg0 arg1)
      (cond
        ((logtest? (-> gp-0 flags) (joint-mod-ik-flags enable))
         (+! (-> gp-0 blend) (* 4.0 (seconds-per-frame)))
         (if (< 1.0 (-> gp-0 blend))
             (set! (-> gp-0 blend) 1.0)
             )
         )
        (else
          (set! (-> gp-0 blend) (- (-> gp-0 blend) (* 4.0 (seconds-per-frame))))
          (if (< (-> gp-0 blend) 0.0)
              (set! (-> gp-0 blend) 0.0)
              )
          )
        )
      (if (= (-> gp-0 blend) 0.0)
          (return #f)
          )
      (let ((s5-0 (-> arg0 parent bone transform))
            (s4-1 (-> arg0 bone transform))
            )
        (new 'stack-no-clear 'matrix)
        (new 'stack-no-clear 'matrix)
        (let ((s3-0 (new 'stack-no-clear 'vector)))
          (matrix->trans s5-0 s3-0)
          (vector-copy! (-> s5-0 trans) s3-0)
          (matrix->trans s4-1 s3-0)
          (vector-copy! (-> s4-1 trans) s3-0)
          )
        (matrix-copy! (-> gp-0 shoulder-matrix-no-ik) s5-0)
        (matrix-copy! (-> gp-0 elbow-matrix-no-ik) s4-1)
        (let ((s2-0 (new 'stack-no-clear 'vector)))
          (set! sv-784 (new 'stack-no-clear 'vector))
          (let ((s0-0 (new 'stack-no-clear 'vector))
                (s1-0 (new 'stack-no-clear 'vector))
                (s3-1 (new 'stack-no-clear 'vector))
                )
            0.0
            0.0
            (vector-copy! s2-0 (-> s5-0 trans))
            (vector-copy! sv-784 (-> s4-1 trans))
            (vector+*! s0-0 sv-784 (-> s4-1 uvec) (-> gp-0 hand-dist))
            (if (-> gp-0 callback)
                ((-> gp-0 callback) gp-0 s5-0 s4-1 s0-0)
                )
            (vector-copy! s1-0 (-> gp-0 handle-pos))
            (let ((f30-0 (vector-vector-distance s2-0 sv-784))
                  (f0-12 (vector-vector-distance sv-784 s0-0))
                  )
              (set! sv-768 (new 'stack-no-clear 'matrix))
              (let ((v1-32 s1-0)
                    (a0-19 s2-0)
                    )
                (.lvf vf4 (&-> v1-32 quad))
                (.lvf vf5 (&-> a0-19 quad))
                )
              (.mov.vf.w vf6 vf0)
              (.sub.vf.xyz vf6 vf4 vf5)
              (.svf (&-> sv-768 rvec quad) vf6)
              (vector-length (-> sv-768 rvec))
              (+ -4.096 f0-12 f30-0)
              (let ((f0-15 (+ 4.096 (fabs (- f30-0 f0-12)))))
                (cond
                  ((< f0-15 f0-15)
                   (vector-normalize! (-> sv-768 rvec) f0-15)
                   (let ((v1-39 s1-0))
                     (let ((a0-21 s2-0))
                       (.mov.vf.w vf6 vf0)
                       (.lvf vf4 (&-> a0-21 quad))
                       )
                     (.lvf vf5 (&-> sv-768 rvec quad))
                     (.add.vf.xyz vf6 vf4 vf5)
                     (.svf (&-> v1-39 quad) vf6)
                     )
                   )
                  ((< f0-15 f0-15)
                   (vector-normalize! (-> sv-768 rvec) f0-15)
                   (vector+! s1-0 s2-0 (-> sv-768 rvec))
                   )
                  )
                )
              )
            (set! sv-352 (vector-! (new 'stack-no-clear 'vector) sv-784 s2-0))
            (let ((v1-44 (new 'stack-no-clear 'vector)))
              (.lvf vf4 (&-> s0-0 quad))
              (.lvf vf5 (&-> sv-784 quad))
              (.mov.vf.w vf6 vf0)
              (.sub.vf.xyz vf6 vf4 vf5)
              (.svf (&-> v1-44 quad) vf6)
              (set! sv-356 v1-44)
              )
            (set! sv-360 (vector-! (new 'stack-no-clear 'vector) s0-0 s2-0))
            (set! sv-364 (vector-! (new 'stack-no-clear 'vector) s1-0 s2-0))
            (set! sv-368 (new 'stack-no-clear 'quaternion))
            (set! sv-372 (new 'stack-no-clear 'quaternion))
            (let ((f26-0 (vector-length sv-352))
                  (f24-0 (vector-length sv-356))
                  (f30-1 (vector-length sv-364))
                  )
              (let* ((s2-1 (new 'stack-no-clear 'vector))
                     (f28-0 (vector-vector-angle-safe sv-352 sv-356))
                     (f0-17 (fmax -1.0 (fmin 1.0 (/ (- (- (* f30-1 f30-1) (* f26-0 f26-0)) (* f24-0 f24-0)) (* 2.0 f24-0 f26-0)))))
                     (f26-1 (acos f0-17))
                     )
                (cond
                  ((= f28-0 0.0)
                   (set! (-> s2-1 quad) (-> (&-> s4-1 quad (-> gp-0 elbow-rotation-axis)) 0))
                   (when (logtest? (-> gp-0 flags) (joint-mod-ik-flags elbow-rot-neg))
                     (vector-negate! s2-1 s2-1)
                     (set! f26-1 (- f26-1))
                     )
                   (set! (-> s3-1 quad) (-> (&-> s4-1 quad (-> gp-0 elbow-pole-vector-axis)) 0))
                   (if (logtest? (-> gp-0 flags) (joint-mod-ik-flags elbow-trans-neg))
                       (vector-negate! s3-1 s3-1)
                       )
                   )
                  (else
                    (vector-cross! s2-1 sv-352 sv-356)
                    (vector-!
                      s3-1
                      sv-352
                      (vector-float*!
                        (new 'stack-no-clear 'vector)
                        sv-360
                        (/ (vector-dot sv-360 sv-352) (vector-dot sv-360 sv-360))
                        )
                      )
                    )
                  )
                (vector-normalize! s3-1 1.0)
                (vector-normalize! s2-1 1.0)
                (quaternion-vector-angle! sv-368 s2-1 (- f26-1 f28-0))
                )
              (vector-orient-by-quat! sv-356 sv-356 sv-368)
              (vector+! sv-360 sv-352 sv-356)
              (quaternion-from-two-vectors!
                sv-372
                (vector-normalize-copy! (new 'stack-no-clear 'vector) sv-360 1.0)
                (vector-normalize-copy! (new 'stack-no-clear 'vector) sv-364 1.0)
                )
              (vector-orient-by-quat! sv-352 sv-352 sv-372)
              (let ((f0-25 (fabs (vector-dot
                                   (vector-normalize-copy! (new 'stack-no-clear 'vector) sv-352 1.0)
                                   (vector-normalize-copy! (new 'stack-no-clear 'vector) sv-364 1.0)
                                   )
                                 )
                           )
                    )
                (if (< 0.98 f0-25)
                    (vector-orient-by-quat! sv-352 s3-1 sv-372)
                    )
                )
              (let ((s2-4 (new 'stack-no-clear 'vector))
                    (s1-2 (new 'stack-no-clear 'quaternion))
                    )
                (new 'stack-no-clear 'matrix)
                (* f30-1 f30-1)
                (let ((s0-2 (new 'stack-no-clear 'quaternion)))
                  (vector-flatten! s2-4 sv-352 sv-364)
                  (vector-flatten! (-> s1-2 vec) s3-1 sv-364)
                  (vector-normalize! s2-4 1.0)
                  (vector-normalize! (-> s1-2 vec) 1.0)
                  (quaternion-from-two-vectors! s0-2 s2-4 (-> s1-2 vec))
                  (quaternion*! sv-372 s0-2 sv-372)
                  )
                )
              )
            )
          )
        (quaternion-pseudo-slerp! sv-368 *unity-quaternion* sv-368 (-> gp-0 blend))
        (quaternion-pseudo-slerp! sv-372 *unity-quaternion* sv-372 (-> gp-0 blend))
        (let ((a2-19 (quaternion->matrix (new 'stack-no-clear 'matrix) sv-368))
              (gp-1 (new 'stack-no-clear 'matrix))
              )
          (set! (-> gp-1 rvec quad) (-> s4-1 trans quad))
          (matrix*! s4-1 s4-1 a2-19)
          (vector-copy! (-> s4-1 trans) (-> gp-1 rvec))
          )
        (let ((s3-2 (quaternion->matrix (new 'stack-no-clear 'matrix) sv-372))
              (a2-20 (matrix-4x4-inverse! (new 'stack-no-clear 'matrix) s5-0))
              (gp-2 (new 'stack-no-clear 'matrix))
              )
          (set! (-> gp-2 rvec quad) (-> s5-0 trans quad))
          (matrix*! s4-1 s4-1 a2-20)
          (matrix*! s5-0 s5-0 s3-2)
          (vector-copy! (-> s5-0 trans) (-> gp-2 rvec))
          )
        (matrix*! s4-1 s4-1 s5-0)
        )
      )
    (none)
    )
  )

(defmethod new joint-mod-ik ((allocation symbol) (type-to-make type) (proc process-drawable) (joint-id int) (hand-dist float))
  (let ((v0-0 (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
    (set! (-> v0-0 process) proc)
    (set! (-> v0-0 hand-dist) hand-dist)
    (set! (-> v0-0 elbow-pole-vector-axis) (the-as uint 0))
    (logclear! (-> v0-0 flags) (joint-mod-ik-flags elbow-trans-neg))
    (set! (-> v0-0 elbow-rotation-axis) (the-as uint 2))
    (logclear! (-> v0-0 flags) (joint-mod-ik-flags elbow-rot-neg))
    (set! (-> v0-0 callback) #f)
    (set! (-> v0-0 blend) 0.0)
    (logclear! (-> v0-0 flags) (joint-mod-ik-flags enable))
    (let ((a0-5 (-> proc node-list data joint-id)))
      (set! (-> a0-5 param0) joint-mod-ik-callback)
      (set! (-> a0-5 param1) v0-0)
      (set! (-> a0-5 param2) (the-as basic joint-id))
      )
    v0-0
    )
  )

(defmethod set-ik-target! ((this joint-mod-ik) (pos vector))
  (vector-copy! (-> this handle-pos) pos)
  0
  (none)
  )

(defmethod enable-set! ((this joint-mod-ik) (enable symbol))
  (if enable
      (logior! (-> this flags) (joint-mod-ik-flags enable))
      (logclear! (-> this flags) (joint-mod-ik-flags enable))
      )
  0
  (none)
  )

(defbehavior real-joint-mod-gun-look-at-handler process ((arg0 cspace) (arg1 transformq))
  "Joint mod callback for pointing the gun (implementation)."
  (local-vars
    (sv-16 joint-mod)
    (sv-64 vector)
    (sv-96 quaternion)
    (sv-160 vector)
    (sv-164 vector)
    (sv-168 vector)
    (sv-172 symbol)
    )
  (set! sv-16 (the-as joint-mod (-> arg0 param1)))
  (vector*! (-> arg1 scale) (-> arg1 scale) (-> sv-16 scale))
  (cspace<-parented-transformq-joint! arg0 arg1)
  (let ((s5-0 (-> arg0 bone transform)))
    (let ((s4-0 (matrix->quat s5-0 (new 'stack-no-clear 'quaternion))))
      (set! sv-64 (matrix->trans s5-0 (new 'stack-no-clear 'vector)))
      (quaternion-rotate-y! s4-0 s4-0 (-> sv-16 twist z))
      (set! sv-96 (quaternion-copy! (new 'stack-no-clear 'quaternion) s4-0))
      (when (!= (-> sv-16 flex-blend) 0.0)
        (set! sv-160 (vector-y-quaternion! (new 'stack-no-clear 'vector) sv-96))
        (set! sv-164 (vector-z-quaternion! (new 'stack-no-clear 'vector) sv-96))
        (set! sv-168 (vector-normalize! (vector-! (new 'stack-no-clear 'vector) (-> sv-16 target) sv-64) 1.0))
        (set! sv-172 (the-as symbol #f))
        (let* ((f30-0 (vector-y-angle sv-164))
               (a0-14 (vector-flatten! (new 'stack-no-clear 'vector) sv-168 sv-160))
               (f0-2 (vector-y-angle a0-14))
               (f0-3 (deg-diff f30-0 f0-2))
               (f30-1 (* f0-3 (-> sv-16 blend)))
               )
          (let ((f28-0 (fmax (fmin f30-1 (-> sv-16 twist-max y)) (- (-> sv-16 twist-max y)))))
            (if (or (!= f30-1 f28-0) (= (-> sv-16 blend) 0.0))
                (logclear! (-> sv-16 track-mode) (track-mode lock-on))
                )
            (cond
              ((or (< (-> sv-16 ignore-angle) (fabs f0-3))
                   (< (-> sv-16 twist-max w) (vector-vector-distance (-> sv-16 target) sv-64))
                   )
               (set! f30-1 0.0)
               (set! f28-0 0.0)
               (set! sv-172 #t)
               )
              ((< 5461.3335 (fabs (deg-diff f30-1 f28-0)))
               (set! (-> sv-16 blend) 0.0001)
               )
              ((< 182.04445 (fabs (deg-diff f30-1 f28-0)))
               (logclear! (-> sv-16 track-mode) (track-mode track-x))
               )
              )
            (if (or (and (logtest? (-> sv-16 track-mode) (track-mode track-y)) (= f30-1 f28-0))
                    (< (-> sv-16 twist-max y) (fabs (-> sv-16 twist y)))
                    )
                (set! (-> sv-16 twist y)
                      (deg-seek (-> sv-16 twist y) f28-0 (* (fabs (deg-diff f28-0 (-> sv-16 twist y)))
                                                            (if (logtest? (-> sv-16 track-mode) (track-mode lock-on))
                                                                1.0
                                                                (-> sv-16 twist-speed-y)
                                                                )
                                                            (-> self clock time-adjust-ratio)
                                                            )
                                )
                      )
                )
            )
          (if (and (< (fabs (deg-diff f30-1 (-> sv-16 twist y))) 728.1778) (and (not sv-172) (!= (-> sv-16 blend) 0.0)))
              (logior! (-> sv-16 track-mode) (track-mode lock-on))
              )
          )
        (quaternion-rotate-local-y! sv-96 sv-96 (-> sv-16 twist y))
        (let* ((s3-1 (vector-x-quaternion! (new 'stack-no-clear 'vector) sv-96))
               (f30-2 (vector-x-angle sv-164))
               (s3-2 (vector-flatten! (new 'stack-no-clear 'vector) sv-168 s3-1))
               (f0-24 (vector-x-angle s3-2))
               (f30-3 (fmax
                        (fmin (* (- (deg-diff f30-2 f0-24)) (-> sv-16 blend)) (-> sv-16 twist-max x))
                        (- (-> sv-16 twist-max x))
                        )
                      )
               )
          (if (or (< (vector-dot s3-2 sv-164) 0.1)
                  (< (-> sv-16 twist-max z) (vector-vector-distance (-> sv-16 target) sv-64))
                  )
              (set! f30-3 0.0)
              )
          (if (or (logtest? (-> sv-16 track-mode) (track-mode track-x))
                  (< (-> sv-16 twist-max x) (fabs (-> sv-16 twist x)))
                  )
              (set! (-> sv-16 twist x)
                    (deg-seek (-> sv-16 twist x) f30-3 (* (fabs (deg-diff f30-3 (-> sv-16 twist x)))
                                                          (if (logtest? (-> sv-16 track-mode) (track-mode lock-on))
                                                              1.0
                                                              (-> sv-16 twist-speed-x)
                                                              )
                                                          (-> self clock time-adjust-ratio)
                                                          )
                              )
                    )
              )
          )
        (quaternion-rotate-x! sv-96 sv-96 (-> sv-16 twist x))
        (quaternion-normalize! (quaternion*! sv-96 sv-96 (-> sv-16 quat)))
        )
      (let ((a1-27 (quaternion-slerp! (new 'stack-no-clear 'quaternion) s4-0 sv-96 (-> sv-16 flex-blend))))
        (matrix<-quat s5-0 a1-27)
        )
      )
    (let ((f30-4 (-> sv-16 trans x))
          (s4-1 (-> s5-0 uvec))
          (v1-97 (vector<-matrix! (new 'stack-no-clear 'vector) s5-0))
          )
      (let ((f0-43 (- f30-4 (-> v1-97 y))))
        (if (< 614.4 (fabs f0-43))
            (+! (-> sv-16 trans z) (* 8.0 f0-43))
            )
        )
      (+! (-> sv-16 trans z) (* -260.0 (seconds-per-frame) (-> sv-16 trans y)))
      (let ((f0-48 (-> sv-16 trans y)))
        (+! (-> sv-16 trans y) (* (-> sv-16 trans z) (seconds-per-frame)))
        (set! (-> sv-16 trans y) (* 0.95 (-> sv-16 trans y)))
        (when (< (* f0-48 (-> sv-16 trans y)) 0.0)
          (set! (-> sv-16 trans y) 0.0)
          (set! (-> sv-16 trans z) 0.0)
          )
        )
      (cond
        ((< 409.6 (-> sv-16 trans y))
         (set! (-> sv-16 trans y) 409.6)
         (set! (-> sv-16 trans z) 0.0)
         )
        ((< (-> sv-16 trans y) -409.6)
         (set! (-> sv-16 trans y) -409.6)
         (set! (-> sv-16 trans z) 0.0)
         )
        )
      (set! (-> sv-16 trans x) (-> v1-97 y))
      (let ((f0-60 (* (-> sv-16 trans y) (-> sv-16 flex-blend))))
        (if (!= f0-60 0.0)
            (vector+float*! (-> s5-0 trans) v1-97 s4-1 f0-60)
            )
        )
      )
    )
  (if (-> sv-16 parented-scale?)
      (set-vector! (-> arg0 bone scale) 1.0 1.0 1.0 1.0)
      )
  0
  (none)
  )

(defbehavior joint-mod-gun-look-at-handler process ((arg0 cspace) (arg1 transformq))
  "Joint mod callback for pointing the gun (wrapper)."
  (real-joint-mod-gun-look-at-handler arg0 arg1)
  (none)
  )

(defbehavior joint-mod-foot-rot-handler process ((arg0 cspace) (arg1 transformq))
  "Joint mod callback to pitch the foot to match the ground."
  (let ((s5-0 (the-as joint-mod (-> arg0 param1)))
        (gp-0 (-> arg0 bone transform))
        )
    (cspace<-parented-transformq-joint! arg0 arg1)
    (let ((s3-0 (-> s5-0 target))
          (s4-0 (-> s5-0 twist-max))
          )
      1.0
      (when (< 8192.0 (vector-vector-angle-safe s3-0 s4-0))
        (let* ((a1-4 (vector-normalize! (vector-cross! (new 'stack-no-clear 'vector) s3-0 s4-0) 1.0))
               (a2-1 (quaternion-vector-angle! (new 'stack-no-clear 'quaternion) a1-4 8192.0))
               )
          (vector-orient-by-quat! s4-0 s3-0 a2-1)
          )
        )
      (let* ((f0-4
               (/ (vector-dot s3-0 (-> s5-0 joint bone transform uvec)) (vector-length (-> s5-0 joint bone transform uvec)))
               )
             (f30-1 (lerp-scale 0.0 1.0 f0-4 0.85 1.0))
             )
        (vector-deg-slerp (-> s5-0 twist) (-> s5-0 twist) s4-0 0.3)
        (vector-copy! s4-0 (-> s5-0 twist))
        (seek! (-> s5-0 blend) (-> s5-0 flex-blend) (* 4.0 (seconds-per-frame)))
        (let ((s3-1 (matrix->scale gp-0 (new 'stack-no-clear 'vector))))
          (let ((s2-0 (matrix->quat gp-0 (new 'stack-no-clear 'quaternion)))
                (s0-0 (matrix->trans gp-0 (new 'stack-no-clear 'vector)))
                )
            (vector-copy! (-> gp-0 uvec) (-> s5-0 twist-max))
            (vector-cross! (-> gp-0 fvec) (-> gp-0 rvec) (-> gp-0 uvec))
            (vector-cross! (-> gp-0 rvec) (-> gp-0 uvec) (-> gp-0 fvec))
            (set! (-> gp-0 rvec w) 0.0)
            (set! (-> gp-0 uvec w) 0.0)
            (set! (-> gp-0 fvec w) 0.0)
            (let ((s1-0 (matrix->quat gp-0 (new 'stack-no-clear 'quaternion))))
              (let* ((f0-14 (vector-dot s4-0 (vector-! (new 'stack-no-clear 'vector) s0-0 (-> s5-0 trans))))
                     (f0-15 (lerp-scale 1.0 0.0 f0-14 819.2 2048.0))
                     )
                (seek! (-> s5-0 old-blend) (* (-> s5-0 blend) f0-15 f30-1) (* 15.0 (seconds-per-frame)))
                )
              (quaternion-slerp! s1-0 s2-0 s1-0 (-> s5-0 old-blend))
              (matrix<-quat gp-0 s1-0)
              )
            )
          (matrix<-scale gp-0 s3-1)
          )
        )
      )
    )
  0
  (none)
  )

(defmethod new joint-mod ((allocation symbol) (type-to-make type) (mode joint-mod-mode) (proc process-drawable) (base-joint-id int))
  (let ((gp-0 (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
    (set! (-> gp-0 process) proc)
    (set! (-> gp-0 joint) (-> proc node-list data base-joint-id))
    (mode-set! gp-0 mode)
    (set-vector! (-> gp-0 twist-max) 8192.0 11832.889 0.0 1.0)
    (set! (-> gp-0 twist-speed-x) 0.1)
    (set! (-> gp-0 twist-speed-y) 0.1)
    (set! (-> gp-0 up) (the-as uint 1))
    (set! (-> gp-0 nose) (the-as uint 2))
    (set! (-> gp-0 ear) (the-as uint 0))
    (set! (-> gp-0 base-joint) (the-as uint base-joint-id))
    (set! (-> gp-0 base-nose) (the-as uint 2))
    (set! (-> gp-0 max-dist) 122880.0)
    (set! (-> gp-0 ignore-angle) 65536.0)
    (set! (-> gp-0 flex-blend) 1.0)
    (set! (-> gp-0 shutting-down?) #f)
    (set-vector! (-> gp-0 scale) 1.0 1.0 1.0 1.0)
    (set! (-> gp-0 parented-scale?) #f)
    (quaternion-identity! (-> gp-0 quat))
    gp-0
    )
  )

;; WARN: Return type mismatch joint-mod vs none.
(defmethod mode-set! ((this joint-mod) (mode joint-mod-mode))
  "Set the type of joint-mod and install the right callback."
  (set! (-> this mode) mode)
  (let ((v1-0 (-> this joint)))
    (case mode
      (((joint-mod-mode flex-blend))
       (set! (-> v1-0 param0) #f)
       (set! (-> this blend) 0.0)
       (set! (-> this flex-blend) 1.0)
       )
      (((joint-mod-mode reset))
       (set! (-> v1-0 param0) #f)
       (set! (-> this blend) 0.0)
       (set! (-> this shutting-down?) #f)
       )
      (((joint-mod-mode look-at))
       (let ((a0-4 v1-0))
         (set! (-> a0-4 param0) joint-mod-look-at-handler)
         (set! (-> a0-4 param1) this)
         )
       )
      (((joint-mod-mode joint-set*-world))
       (let ((a0-5 v1-0))
         (set! (-> a0-5 param0) joint-mod-gun-look-at-handler)
         (set! (-> a0-5 param1) this)
         )
       )
      (((joint-mod-mode gun-look-at))
       (set-vector! (-> this twist) 0.0 1.0 0.0 1.0)
       (let ((a0-7 v1-0))
         (set! (-> a0-7 param0)
               (lambda ((arg0 cspace) (arg1 transformq)) (joint-mod-foot-rot-handler arg0 arg1) (none))
               )
         (set! (-> a0-7 param1) this)
         )
       )
      (((joint-mod-mode world-look-at))
       (let ((a0-8 v1-0))
         (set! (-> a0-8 param0) joint-mod-world-look-at-handler)
         (set! (-> a0-8 param1) this)
         )
       )
      (((joint-mod-mode rotate))
       (let ((a0-9 v1-0))
         (set! (-> a0-9 param0) joint-mod-rotate-handler)
         (set! (-> a0-9 param1) this)
         )
       (set! (-> this blend) 1.0)
       )
      (((joint-mod-mode rotate2))
       (let ((a0-11 v1-0))
         (set! (-> a0-11 param0) joint-mod-rotate-handler)
         (set! (-> a0-11 param1) this)
         )
       (set! (-> this blend) 1.0)
       )
      (((joint-mod-mode joint-set))
       (let ((a0-13 v1-0))
         (set! (-> a0-13 param0) joint-mod-joint-set-handler)
         (set! (-> a0-13 param1) this)
         )
       (vector-reset! (-> this trans))
       (quaternion-identity! (-> this quat))
       (set-vector! (-> this scale) 1.0 1.0 1.0 1.0)
       )
      (((joint-mod-mode foot-rot))
       (let ((a0-16 v1-0))
         (set! (-> a0-16 param0) joint-mod-joint-set-world-handler)
         (set! (-> a0-16 param1) this)
         )
       (vector-reset! (-> this trans))
       (quaternion-identity! (-> this quat))
       (set-vector! (-> this scale) 1.0 1.0 1.0 1.0)
       (set! (-> this flex-blend) 1.0)
       )
      (((joint-mod-mode joint-set*))
       (let ((a0-23 v1-0))
         (set! (-> a0-23 param0) joint-mod-joint-set*-handler)
         (set! (-> a0-23 param1) this)
         )
       (vector-reset! (-> this trans))
       (quaternion-identity! (-> this quat))
       (set-vector! (-> this scale) 1.0 1.0 1.0 1.0)
       )
      (((joint-mod-mode polar-look-at))
       (let ((a0-27 v1-0))
         (set! (-> a0-27 param0) joint-mod-joint-set*-world-handler)
         (set! (-> a0-27 param1) this)
         )
       (vector-reset! (-> this trans))
       (quaternion-identity! (-> this quat))
       (set-vector! (-> this scale) 1.0 1.0 1.0 1.0)
       )
      )
    )
  (none)
  )

;; WARN: Return type mismatch joint-mod vs none.
(defmethod shut-down ((this joint-mod))
  "Disable the joint mod, possibly blending out depending on the type"
  (set! (-> this shutting-down?) #t)
  (set! (-> this blend) 0.0)
  (none)
  )

(defmethod twist-set! ((this joint-mod) (x float) (y float) (z float))
  "Set twist x,y,z. A value of #f will skip the set."
  (if x
      (set! (-> this twist x) x)
      )
  (if y
      (set! (-> this twist y) y)
      )
  (if z
      (set! (-> this twist z) z)
      )
  (-> this twist)
  )

(defmethod trs-set! ((this joint-mod) (trans vector) (quat quaternion) (scale vector))
  "Set translation, quaternion, scale. A value of #f will skip the set."
  (if trans
      (vector-copy! (-> this trans) trans)
      )
  (if quat
      (quaternion-copy! (-> this quat) quat)
      )
  (if scale
      (vector-copy! (-> this scale) scale)
      )
  0
  (none)
  )

(defmethod target-set! ((this joint-mod) (pos vector))
  "Set the target position for look-at mode."
  (if (= (-> this mode) (joint-mod-mode reset))
      (mode-set! this (joint-mod-mode look-at))
      )
  (let ((f0-0 (vector-vector-distance (-> this process root trans) pos)))
    (set! (-> this shutting-down?) #f)
    (vector-copy! (-> this target) pos)
    (if (< f0-0 (-> this max-dist))
        (set! (-> this blend) 1.0)
        (set! (-> this blend) 0.0)
        )
    )
  0
  (none)
  )

(define last-try-to-look-at-data (new 'global 'try-to-look-at-info))

(defmethod look-at! ((this joint-mod) (target vector) (mode symbol) (proc process))
  "Activate joint mod to look at the process."
  (when (= mode 'attacking)
    (let ((s1-0 (as-type proc process-drawable)))
      (when s1-0
        (let ((s2-1 (as-type (-> s1-0 fact) fact-info-enemy)))
          (when s2-1
            (when (< (vector-vector-distance (-> this process root trans) (-> s1-0 root trans)) (-> s2-1 cam-notice-dist))
              (set-time! (-> this notice-time))
              (set! (-> last-try-to-look-at-data who) (process->handle proc))
              (if (< (-> last-try-to-look-at-data vert) (-> s2-1 cam-vert))
                  (set! (-> last-try-to-look-at-data vert) (-> s2-1 cam-vert))
                  )
              (if (< (-> last-try-to-look-at-data horz) (-> s2-1 cam-horz))
                  (set! (-> last-try-to-look-at-data horz) (-> s2-1 cam-horz))
                  )
              )
            )
          )
        )
      )
    )
  (let ((f30-0 (vector-vector-distance (-> this process root trans) target)))
    (if (logtest? (process-mask enemy) (-> proc mask))
        (+! (-> this look-at-count) (the int (lerp-scale 256.0 0.0 f30-0 20480.0 204800.0)))
        )
    (when (and (or (= (-> this blend) 0.0)
                   (or (< f30-0 (vector-vector-distance (-> this process root trans) (-> this target))) (= mode 'force))
                   )
               (< f30-0 (-> this max-dist))
               )
      (if (= (-> this mode) (joint-mod-mode reset))
          (mode-set! this (joint-mod-mode look-at))
          )
      (vector-copy! (-> this target) target)
      (set! (-> this blend) 1.0)
      (set! (-> this shutting-down?) #f)
      )
    )
  0
  (none)
  )

(defbehavior joint-mod-look-at-handler process ((arg0 cspace) (arg1 transformq))
  "Callback for look-at joint mod."
  (local-vars
    (sv-144 matrix)
    (sv-148 quaternion)
    (sv-152 vector)
    (sv-156 vector)
    (sv-160 (pointer uint128))
    (sv-164 symbol)
    )
  (let ((gp-0 (the-as joint-mod (-> arg0 param1))))
    (cspace<-parented-transformq-joint! arg0 arg1)
    (let ((s3-0 (-> arg0 bone transform)))
      (set! sv-144 (new 'stack-no-clear 'matrix))
      (set! sv-148 (new 'stack-no-clear 'quaternion))
      (set! sv-152 (new 'stack-no-clear 'vector))
      (set! sv-156 (new 'stack-no-clear 'vector))
      (set! sv-160 (&-> gp-0 process node-list data (-> gp-0 base-joint) bone transform quad (-> gp-0 base-nose)))
      (set! sv-164
            (< (vector-dot (-> s3-0 rvec) (vector-cross! (new 'stack-no-clear 'vector) (-> s3-0 uvec) (-> s3-0 fvec)))
               0.0
               )
            )
      (vector-normalize-copy! (-> sv-144 rvec) (the-as vector (&-> s3-0 quad (-> gp-0 ear))) (if sv-164
                                                                                                 -1.0
                                                                                                 1.0
                                                                                                 )
                              )
      (vector-normalize-copy! (-> sv-144 uvec) (the-as vector (&-> s3-0 quad (-> gp-0 up))) 1.0)
      (vector-normalize-copy! (-> sv-144 fvec) (the-as vector (&-> s3-0 quad (-> gp-0 nose))) 1.0)
      )
    (vector-reset! (-> sv-144 trans))
    (matrix->quaternion sv-148 sv-144)
    (vector-normalize! (vector-! sv-152 (-> gp-0 target) (-> arg0 bone transform trans)) 1.0)
    (vector-inv-orient-by-quat! sv-156 sv-152 sv-148)
    (let ((f30-0 (vector-y-angle sv-156))
          (f0-2 (if (= (-> gp-0 base-joint) (+ (-> arg0 joint number) 1))
                    0.0
                    (deg-diff (vector-y-angle (-> sv-144 fvec)) (vector-y-angle (the-as vector sv-160)))
                    )
                )
          )
      (if (< (-> gp-0 ignore-angle) (fabs f30-0))
          (set! f30-0 0.0)
          )
      (let ((f30-1
              (fmax
                (fmin (* f30-0 (-> gp-0 blend) (-> gp-0 flex-blend)) (+ (-> gp-0 twist-max y) (* f0-2 (-> gp-0 flex-blend))))
                (+ (- (-> gp-0 twist-max y)) (* f0-2 (-> gp-0 flex-blend)))
                )
              )
            )
        (when (and (-> gp-0 shutting-down?) (< (fabs (- (-> gp-0 twist y) f30-1)) 18.204445))
          (if (and (= (-> gp-0 scale x) 1.0) (= (-> gp-0 scale y) 1.0) (= (-> gp-0 scale z) 1.0))
              (mode-set! gp-0 (joint-mod-mode reset))
              (mode-set! gp-0 (joint-mod-mode rotate2))
              )
          )
        (set! (-> gp-0 twist y)
              (deg-seek
                (-> gp-0 twist y)
                f30-1
                (* (fabs (deg-diff f30-1 (-> gp-0 twist y))) (-> gp-0 twist-speed-y) (-> self clock time-adjust-ratio))
                )
              )
        )
      )
    (let ((f0-21 (if sv-164
                     (- (-> gp-0 twist y))
                     (-> gp-0 twist y)
                     )
                 )
          (a1-18 (new-stack-vector0))
          )
      (set! (-> a1-18 data (-> gp-0 up)) 1.0)
      (let ((a2-7 (quaternion-vector-angle! (new-stack-quaternion0) a1-18 f0-21)))
        (quaternion-normalize! (quaternion*! (-> arg1 quat) (-> arg1 quat) a2-7))
        )
      )
    (let ((f0-27
            (fmax
              (fmin (* (- (vector-x-angle sv-156)) (-> gp-0 blend) (-> gp-0 flex-blend)) (-> gp-0 twist-max x))
              (- (-> gp-0 twist-max x))
              )
            )
          )
      (if (< (vector-dot sv-156 *z-vector*) 0.1)
          (set! f0-27 0.0)
          )
      (set! (-> gp-0 twist x)
            (deg-seek
              (-> gp-0 twist x)
              f0-27
              (* (fabs (deg-diff f0-27 (-> gp-0 twist x))) (-> gp-0 twist-speed-x) (-> self clock time-adjust-ratio))
              )
            )
      )
    (let ((a1-22 (new-stack-vector0)))
      (set! (-> a1-22 data (-> gp-0 ear)) 1.0)
      (let ((a2-10 (quaternion-vector-angle! (new-stack-quaternion0) a1-22 (-> gp-0 twist x))))
        (quaternion-normalize! (quaternion*! (-> arg1 quat) (-> arg1 quat) a2-10))
        )
      )
    (vector+! (-> arg1 trans) (-> arg1 trans) (-> gp-0 trans))
    (quaternion-normalize! (quaternion*! (-> arg1 quat) (-> arg1 quat) (-> gp-0 quat)))
    (vector*! (-> arg1 scale) (-> arg1 scale) (-> gp-0 scale))
    (cspace<-parented-transformq-joint! arg0 arg1)
    (if (-> gp-0 parented-scale?)
        (set-vector! (-> arg0 bone scale) 1.0 1.0 1.0 1.0)
        )
    (if (and (= (-> gp-0 process type) target) (!= (-> gp-0 blend) 0.0))
        (add-debug-text-sphere
          *display-target-marks*
          (bucket-id debug-no-zbuf1)
          (-> gp-0 target)
          (meters 0.2)
          "look"
          (new 'static 'rgba :r #xff :g #xff :a #x80)
          )
        )
    )
  0
  (none)
  )

(defbehavior joint-mod-world-look-at-handler process ((arg0 cspace) (arg1 transformq))
  (local-vars (sv-48 vector) (sv-52 vector) (sv-56 vector))
  (let ((gp-0 (the-as joint-mod (-> arg0 param1))))
    (let ((s5-0 (-> arg0 bone transform)))
      (cspace<-parented-transformq-joint! arg0 arg1)
      (set! sv-48 (vector-normalize-copy!
                    (new 'stack-no-clear 'vector)
                    (-> gp-0 process node-list data 0 bone transform uvec)
                    1.0
                    )
            )
      (set! sv-52 (vector-normalize! (the-as vector (&-> s5-0 quad (-> gp-0 nose))) 1.0))
      (set! sv-56 (vector-normalize! (vector-! (new 'stack-no-clear 'vector) (-> gp-0 target) (-> s5-0 trans)) 1.0))
      (let* ((f30-0 (vector-y-angle sv-52))
             (a0-7 (vector-flatten! (new-stack-vector0) sv-56 sv-48))
             (f0-0 (vector-y-angle a0-7))
             (f0-1 (deg-diff f30-0 f0-0))
             )
        (if (< (-> gp-0 ignore-angle) (fabs f0-1))
            (set! f0-1 0.0)
            )
        (let ((f0-5
                (fmax (fmin (* f0-1 (-> gp-0 blend) (-> gp-0 flex-blend)) (-> gp-0 twist-max y)) (- (-> gp-0 twist-max y)))
                )
              )
          (set! (-> gp-0 twist y) (deg-seek
                                    (-> gp-0 twist y)
                                    f0-5
                                    (* (fmax 1.0 (* (fabs (deg-diff f0-5 (-> gp-0 twist y))) (-> gp-0 twist-speed-y)))
                                       (-> self clock time-adjust-ratio)
                                       )
                                    )
                )
          )
        )
      (when (!= (-> gp-0 twist y) 0.0)
        (let ((a2-3 (matrix-rotate-y! (new 'stack-no-clear 'matrix) (-> gp-0 twist y)))
              (s4-2 (-> s5-0 trans quad))
              )
          (matrix*! s5-0 s5-0 a2-3)
          (set! (-> s5-0 trans quad) s4-2)
          )
        )
      (let* ((s4-3 (vector-normalize-copy!
                     (new 'stack-no-clear 'vector)
                     (-> gp-0 process node-list data 0 bone transform rvec)
                     1.0
                     )
                   )
             (f30-2 (vector-x-angle sv-52))
             (s4-4 (vector-flatten! (new-stack-vector0) sv-56 s4-3))
             (f0-15 (vector-x-angle s4-4))
             (f0-21 (fmax
                      (fmin (* (- (deg-diff f30-2 f0-15)) (-> gp-0 blend) (-> gp-0 flex-blend)) (-> gp-0 twist-max x))
                      (- (-> gp-0 twist-max x))
                      )
                    )
             )
        (if (< (vector-dot s4-4 sv-52) 0.1)
            (set! f0-21 0.0)
            )
        (set! (-> gp-0 twist x) (deg-seek
                                  (-> gp-0 twist x)
                                  f0-21
                                  (* (fmax 1.0 (* (fabs (deg-diff f0-21 (-> gp-0 twist x))) (-> gp-0 twist-speed-x)))
                                     (-> self clock time-adjust-ratio)
                                     )
                                  )
              )
        )
      (when (!= (-> gp-0 twist x) 0.0)
        (let* ((v1-25 (-> gp-0 ear))
               (a1-17 ((cond
                         ((zero? v1-25)
                          matrix-rotate-x!
                          )
                         ((= v1-25 1)
                          matrix-rotate-y!
                          )
                         (else
                           matrix-rotate-z!
                           )
                         )
                       (new 'stack-no-clear 'matrix)
                       (-> gp-0 twist x)
                       )
                      )
               )
          (matrix*! s5-0 a1-17 s5-0)
          )
        )
      )
    (if (and (= (-> gp-0 process type) target) (!= (-> gp-0 blend) 0.0))
        (add-debug-text-sphere
          *display-target-marks*
          (bucket-id debug-no-zbuf1)
          (-> gp-0 target)
          (meters 0.2)
          "look"
          (new 'static 'rgba :r #xff :g #xff :a #x80)
          )
        )
    )
  0
  (none)
  )

(defbehavior joint-mod-rotate-handler process ((arg0 cspace) (arg1 transformq))
  "Callback for rotate joint mod."
  (let ((s5-0 (the-as joint-mod (-> arg0 param1))))
    (let ((s3-0 (new 'static 'inline-array vector 3
                  (new 'static 'vector :x 1.0 :w 1.0)
                  (new 'static 'vector :y 1.0 :w 1.0)
                  (new 'static 'vector :z 1.0 :w 1.0)
                  )
                )
          )
      (if (not (logtest? (-> s5-0 track-mode) (track-mode no-trans)))
          (vector+! (-> arg1 trans) (-> arg1 trans) (-> s5-0 trans))
          )
      (when (not (logtest? (-> s5-0 track-mode) (track-mode no-rotate)))
        (let* ((v1-9 (-> s3-0 (-> s5-0 ear)))
               (a1-4 (quaternion-axis-angle!
                       (new 'stack-no-clear 'quaternion)
                       (-> v1-9 x)
                       (-> v1-9 y)
                       (-> v1-9 z)
                       (* (-> s5-0 twist x) (-> s5-0 blend) (-> s5-0 flex-blend))
                       )
                     )
               )
          (quaternion-normalize! (quaternion*! (-> arg1 quat) a1-4 (-> arg1 quat)))
          )
        (let* ((v1-13 (-> s3-0 (-> s5-0 up)))
               (a1-6 (quaternion-axis-angle!
                       (new 'stack-no-clear 'quaternion)
                       (-> v1-13 x)
                       (-> v1-13 y)
                       (-> v1-13 z)
                       (* (-> s5-0 twist y) (-> s5-0 blend) (-> s5-0 flex-blend))
                       )
                     )
               )
          (quaternion-normalize! (quaternion*! (-> arg1 quat) a1-6 (-> arg1 quat)))
          )
        (let* ((v1-17 (-> s3-0 (-> s5-0 nose)))
               (a1-8 (quaternion-axis-angle!
                       (new 'stack-no-clear 'quaternion)
                       (-> v1-17 x)
                       (-> v1-17 y)
                       (-> v1-17 z)
                       (* (-> s5-0 twist z) (-> s5-0 blend) (-> s5-0 flex-blend))
                       )
                     )
               )
          (quaternion-normalize! (quaternion*! (-> arg1 quat) a1-8 (-> arg1 quat)))
          )
        )
      )
    (if (not (logtest? (-> s5-0 track-mode) (track-mode no-scale)))
        (vector*! (-> arg1 scale) (-> arg1 scale) (-> s5-0 scale))
        )
    (cspace<-parented-transformq-joint! arg0 arg1)
    (if (-> s5-0 parented-scale?)
        (set-vector! (-> arg0 bone scale) 1.0 1.0 1.0 1.0)
        )
    )
  0
  (none)
  )

(defbehavior joint-mod-scale-handler process ((arg0 cspace) (arg1 transformq))
  "Callback for scale joint mod."
  (let ((s5-0 (the-as joint-mod (-> arg0 param1))))
    (vector*! (-> arg1 scale) (-> arg1 scale) (-> s5-0 scale))
    (cspace<-parented-transformq-joint! arg0 arg1)
    (if (-> s5-0 parented-scale?)
        (set-vector! (-> arg0 bone scale) 1.0 1.0 1.0 1.0)
        )
    )
  0
  (none)
  )

(defbehavior joint-mod-joint-set-handler process ((arg0 cspace) (arg1 transformq))
  "Callback for set joint mod."
  (let ((s4-0 (the-as joint-mod (-> arg0 param1))))
    (if (not (logtest? (-> s4-0 track-mode) (track-mode no-trans)))
        (vector-copy! (-> arg1 trans) (-> s4-0 trans))
        )
    (if (not (logtest? (-> s4-0 track-mode) (track-mode no-rotate)))
        (quaternion-copy! (-> arg1 quat) (-> s4-0 quat))
        )
    (if (not (logtest? (-> s4-0 track-mode) (track-mode no-scale)))
        (vector-copy! (-> arg1 scale) (-> s4-0 scale))
        )
    )
  (cspace<-parented-transformq-joint! arg0 arg1)
  0
  (none)
  )

;; WARN: Function joint-mod-joint-set-world-handler has a return type of none, but the expression builder found a return statement.
(defbehavior joint-mod-joint-set-world-handler process ((arg0 cspace) (arg1 transformq))
  (cspace<-parented-transformq-joint! arg0 arg1)
  (let ((s5-0 (the-as joint-mod (-> arg0 param1)))
        (s4-0 (matrix->trans (-> arg0 bone transform) (new 'stack-no-clear 'vector)))
        )
    (let ((s3-0 (new 'stack-no-clear 'vector)))
      (if (>= 0.0 (-> s5-0 flex-blend))
          (return #f)
          )
      (cond
        ((logtest? (-> s5-0 track-mode) (track-mode no-scale))
         (vector-copy! s3-0 (-> arg1 scale))
         )
        ((>= (-> s5-0 flex-blend) 1.0)
         (vector-copy! s3-0 (-> s5-0 scale))
         )
        (else
          (vector-lerp! s3-0 (-> arg1 scale) (-> s5-0 scale) (-> s5-0 flex-blend))
          )
        )
      (cond
        ((logtest? (-> s5-0 track-mode) (track-mode no-rotate))
         )
        ((>= (-> s5-0 flex-blend) 1.0)
         (quaternion->matrix (-> arg0 bone transform) (-> s5-0 quat))
         )
        (else
          (let ((v1-15 (new 'stack-no-clear 'vector)))
            (vector-copy! v1-15 (-> arg1 scale))
            (set! (-> v1-15 x) (/ 1.0 (-> v1-15 x)))
            (set! (-> v1-15 y) (/ 1.0 (-> v1-15 y)))
            (set! (-> v1-15 z) (/ 1.0 (-> v1-15 z)))
            (vector-float*! (-> arg0 bone transform rvec) (-> arg0 bone transform rvec) (-> v1-15 x))
            (vector-float*! (-> arg0 bone transform uvec) (-> arg0 bone transform uvec) (-> v1-15 y))
            (vector-float*! (-> arg0 bone transform fvec) (-> arg0 bone transform fvec) (-> v1-15 z))
            )
          (let ((a1-12 (matrix->quaternion (new 'stack-no-clear 'quaternion) (-> arg0 bone transform))))
            (quaternion->matrix
              (-> arg0 bone transform)
              (quaternion-slerp! (new 'stack-no-clear 'quaternion) a1-12 (-> s5-0 quat) (-> s5-0 flex-blend))
              )
            )
          )
        )
      (cond
        ((logtest? (-> s5-0 track-mode) (track-mode no-rotate))
         (vector-normalize! (-> arg0 bone transform rvec) (-> s3-0 x))
         (vector-normalize! (-> arg0 bone transform uvec) (-> s3-0 y))
         (vector-normalize! (-> arg0 bone transform fvec) (-> s3-0 z))
         )
        (else
          (vector-float*! (-> arg0 bone transform rvec) (-> arg0 bone transform rvec) (-> s3-0 x))
          (vector-float*! (-> arg0 bone transform uvec) (-> arg0 bone transform uvec) (-> s3-0 y))
          (vector-float*! (-> arg0 bone transform fvec) (-> arg0 bone transform fvec) (-> s3-0 z))
          )
        )
      )
    (set! (-> arg0 bone transform rvec w) 0.0)
    (set! (-> arg0 bone transform uvec w) 0.0)
    (set! (-> arg0 bone transform fvec w) 0.0)
    (cond
      ((logtest? (-> s5-0 track-mode) (track-mode no-trans))
       (vector-copy! (-> arg0 bone transform trans) s4-0)
       )
      ((>= (-> s5-0 flex-blend) 1.0)
       (vector-copy! (-> arg0 bone transform trans) (-> s5-0 trans))
       (set! (-> arg0 bone transform trans w) 1.0)
       )
      (else
        (vector-lerp! (-> arg0 bone transform trans) s4-0 (-> s5-0 trans) (-> s5-0 flex-blend))
        (set! (-> arg0 bone transform trans w) 1.0)
        )
      )
    )
  0
  (none)
  )

(defbehavior joint-mod-joint-set*-handler process ((arg0 cspace) (arg1 transformq))
  (let ((s5-0 (the-as joint-mod (-> arg0 param1))))
    (if (not (logtest? (-> s5-0 track-mode) (track-mode no-trans)))
        (vector+! (-> arg1 trans) (-> arg1 trans) (-> s5-0 trans))
        )
    (if (not (logtest? (-> s5-0 track-mode) (track-mode no-rotate)))
        (quaternion-normalize! (quaternion*! (-> arg1 quat) (-> arg1 quat) (-> s5-0 quat)))
        )
    (if (not (logtest? (-> s5-0 track-mode) (track-mode no-scale)))
        (vector*! (-> arg1 scale) (-> arg1 scale) (-> s5-0 scale))
        )
    (cspace<-parented-transformq-joint! arg0 arg1)
    (if (-> s5-0 parented-scale?)
        (set-vector! (-> arg0 bone scale) 1.0 1.0 1.0 1.0)
        )
    )
  0
  (none)
  )

(defbehavior joint-mod-joint-set*-world-handler process ((arg0 cspace) (arg1 transformq))
  (cspace<-parented-transformq-joint! arg0 arg1)
  (let ((s5-0 (the-as joint-mod (-> arg0 param1))))
    (let ((s3-0 (quaternion->matrix (new 'stack-no-clear 'matrix) (-> s5-0 quat)))
          (s4-0 (matrix->trans (-> arg0 bone transform) (new 'stack-no-clear 'vector)))
          )
      (vector-reset! (-> arg0 bone transform trans))
      (set! (-> arg0 bone transform trans w) 1.0)
      (vector-float*! (-> s3-0 rvec) (-> s3-0 rvec) (-> s5-0 scale x))
      (vector-float*! (-> s3-0 uvec) (-> s3-0 uvec) (-> s5-0 scale y))
      (vector-float*! (-> s3-0 fvec) (-> s3-0 fvec) (-> s5-0 scale z))
      (set! (-> s3-0 rvec w) 0.0)
      (set! (-> s3-0 uvec w) 0.0)
      (set! (-> s3-0 fvec w) 0.0)
      (matrix*! (-> arg0 bone transform) (-> arg0 bone transform) s3-0)
      (vector+! (-> arg0 bone transform trans) s4-0 (-> s5-0 trans))
      )
    (if (-> s5-0 parented-scale?)
        (set-vector! (-> arg0 bone scale) 1.0 1.0 1.0 1.0)
        )
    )
  0
  (none)
  )

;; WARN: Return type mismatch float vs none.
(defmethod initialize ((this joint-mod-polar-look-at) (proc process-drawable) (joint-id int))
  "Attach joint-mod to process and set defaults."
  (let ((a1-2 (-> proc node-list data joint-id)))
    (set! (-> a1-2 param0) joint-mod-polar-look-at-callback)
    (set! (-> a1-2 param1) this)
    )
  (set! (-> this flags) (joint-mod-polar-flags blending-to-zero))
  (set! (-> this up) 1)
  (set! (-> this nose) 2)
  (set! (-> this ear) 0)
  (set! (-> this polar-internal-tilt-max) 32768.0)
  (set! (-> this polar-internal-radius) 32768.0)
  (set! (-> this polar-external-tilt-max) 32768.0)
  (set! (-> this polar-external-radius) 32768.0)
  (set! (-> this upward-tilt) 16384.0)
  (set! (-> this downward-tilt) 16384.0)
  (set! (-> this forward-twist) 16384.0)
  (set! (-> this backward-twist) 16384.0)
  (set! (-> this blend-duration) 0)
  (set! (-> this blend-start-value) 0.0)
  (set! (-> this blend-max) 1.0)
  (none)
  )

;; WARN: Return type mismatch float vs none.
(defmethod set-both-targets! ((this joint-mod-polar-look-at) (other joint-mod-polar-look-at) (pos vector))
  "Update the target position of this mod, and a second one."
  (when (nonzero? this)
    (set-target! this pos)
    (when (nonzero? other)
      (set! (-> this polar-external-tilt-max) (-> other polar-internal-tilt-max))
      (set! (-> this polar-external-radius) (-> other polar-internal-radius))
      )
    )
  (when (nonzero? other)
    (set-target! other pos)
    (when (nonzero? this)
      (set! (-> other polar-external-tilt-max) (-> this polar-internal-tilt-max))
      (set! (-> other polar-external-radius) (-> this polar-internal-radius))
      )
    )
  (none)
  )

(defmethod set-target! ((this joint-mod-polar-look-at) (pos vector))
  "Update the target position."
  (vector-copy! (-> this target) pos)
  0
  (none)
  )

(defmethod blend-on! ((this joint-mod-polar-look-at) (duration time-frame) (final-val float) (restart-if-in-progress symbol))
  "Start blending this joint mod on."
  (cond
    ((and (not restart-if-in-progress) (not (logtest? (-> this flags) (joint-mod-polar-flags blending-to-zero))))
     )
    ((zero? duration)
     (set! (-> this blend-start-value) final-val)
     (set! (-> this blend-max) final-val)
     (set! (-> this blend-duration) duration)
     (logclear! (-> this flags) (joint-mod-polar-flags blending-to-zero))
     )
    (else
      (set-time! (-> this blend-start-time))
      (set! (-> this blend-start-value) (get-start-blend! this))
      (set! (-> this blend-max) final-val)
      (set! (-> this blend-duration) duration)
      (logclear! (-> this flags) (joint-mod-polar-flags blending-to-zero))
      )
    )
  0
  (none)
  )

(defmethod blend-to-off! ((this joint-mod-polar-look-at) (duration time-frame) (restart-if-in-progress symbol))
  "Start blending to disable this joint mod."
  (cond
    ((and (not restart-if-in-progress) (logtest? (-> this flags) (joint-mod-polar-flags blending-to-zero)))
     )
    ((zero? duration)
     (set! (-> this blend-start-value) 0.0)
     (set! (-> this blend-duration) duration)
     (logior! (-> this flags) (joint-mod-polar-flags blending-to-zero))
     )
    (else
      (set-time! (-> this blend-start-time))
      (set! (-> this blend-start-value) (get-start-blend! this))
      (set! (-> this blend-duration) duration)
      (logior! (-> this flags) (joint-mod-polar-flags blending-to-zero))
      )
    )
  0
  (none)
  )

(defmethod get-start-blend! ((this joint-mod-polar-look-at))
  "Determine what blend to use when starting a new one."
  (local-vars (f0-2 float))
  (cond
    ((zero? (-> this blend-duration))
     (-> this blend-start-value)
     )
    ((begin
       (set! f0-2 (the float (- (current-time) (-> this blend-start-time))))
       (logtest? (-> this flags) (joint-mod-polar-flags blending-to-zero))
       )
     (let ((f0-5 (lerp-scale (-> this blend-start-value) 0.0 f0-2 0.0 (the float (-> this blend-duration)))))
       (when (= f0-5 0.0)
         (set! (-> this blend-start-value) f0-5)
         (set! (-> this blend-duration) 0)
         0
         )
       f0-5
       )
     )
    (else
      (let ((f0-8
              (lerp-scale (-> this blend-start-value) (-> this blend-max) f0-2 0.0 (the float (-> this blend-duration)))
              )
            )
        (when (>= f0-8 (-> this blend-max))
          (set! (-> this blend-start-value) f0-8)
          (set! (-> this blend-duration) 0)
          0
          )
        f0-8
        )
      )
    )
  )

(defbehavior joint-mod-polar-look-at-callback process ((arg0 cspace) (arg1 transformq))
  (let* ((s5-0 (the-as joint-mod-polar-look-at (-> arg0 param1)))
         (f30-0 (get-start-blend! s5-0))
         )
    (cspace<-parented-transformq-joint! arg0 arg1)
    (when (< 0.0 f30-0)
      (let* ((t9-2 vector-normalize-copy!)
             (a0-3 (new 'stack-no-clear 'vector))
             (v1-3 (abs (-> s5-0 nose)))
             (s3-0 (t9-2 a0-3 (the-as vector (&-> arg0 bone transform quad v1-3)) 1.0))
             (s1-0 (vector-normalize!
                     (vector-! (new 'stack-no-clear 'vector) (-> s5-0 target) (-> arg0 bone transform trans))
                     1.0
                     )
                   )
             (s4-1 (new 'stack-no-clear 'matrix))
             )
        (let ((s2-0 (new 'stack-no-clear 'vector)))
          (if (logtest? (-> s5-0 flags) (joint-mod-polar-flags negate-nose))
              (vector-negate! s3-0 s3-0)
              )
          (let ((t9-5 vector-normalize-copy!)
                (a0-7 (-> s4-1 rvec))
                (v1-11 (abs (-> s5-0 ear)))
                )
            (t9-5 a0-7 (the-as vector (&-> arg0 bone transform quad v1-11)) 1.0)
            )
          (if (logtest? (-> s5-0 flags) (joint-mod-polar-flags negate-ear))
              (vector-negate! (-> s4-1 rvec) (-> s4-1 rvec))
              )
          (let ((t9-7 vector-normalize-copy!)
                (a0-9 (-> s4-1 uvec))
                (v1-18 (abs (-> s5-0 up)))
                )
            (t9-7 a0-9 (the-as vector (&-> arg0 bone transform quad v1-18)) 1.0)
            )
          (if (logtest? (-> s5-0 flags) (joint-mod-polar-flags negate-up))
              (vector-negate! (-> s4-1 uvec) (-> s4-1 uvec))
              )
          (vector-copy! (-> s4-1 fvec) s3-0)
          (set-vector! (-> s4-1 trans) 0.0 0.0 0.0 1.0)
          (matrix-transpose! s4-1 s4-1)
          (set-vector! (-> s4-1 trans) 0.0 0.0 0.0 1.0)
          (vector-matrix*! s2-0 s1-0 s4-1)
          (let* ((t9-11 asin)
                 (f0-9 (-> s2-0 x))
                 (f0-11 (* f0-9 f0-9))
                 (f1-0 (-> s2-0 y))
                 (f26-0 (t9-11 (sqrtf (+ f0-11 (* f1-0 f1-0)))))
                 (f28-0 (atan (-> s2-0 y) (-> s2-0 x)))
                 )
            (if (< (-> s2-0 z) 0.0)
                (set! f26-0 (- 32768.0 f26-0))
                )
            (set! (-> s5-0 polar-internal-radius) f26-0)
            (cond
              ((< 16384.0 f28-0)
               (set! (-> s5-0 polar-internal-tilt-max) (- 32768.0 f28-0))
               (if (and (< (-> s5-0 polar-external-radius) f26-0) (< 0.0 (-> s5-0 polar-external-tilt-max)))
                   (set! f28-0 (fmax f28-0 (- 32768.0 (-> s5-0 polar-external-tilt-max))))
                   )
               )
              ((< f28-0 -16384.0)
               (set! (-> s5-0 polar-internal-tilt-max) (- -32768.0 f28-0))
               (if (and (< (-> s5-0 polar-external-radius) f26-0) (< (-> s5-0 polar-external-tilt-max) 0.0))
                   (set! f28-0 (fmin f28-0 (- -32768.0 (-> s5-0 polar-external-tilt-max))))
                   )
               )
              ((< 0.0 f28-0)
               (set! (-> s5-0 polar-internal-tilt-max) f28-0)
               (if (and (< (-> s5-0 polar-external-radius) f26-0) (< 0.0 (-> s5-0 polar-external-tilt-max)))
                   (set! f28-0 (fmin f28-0 (-> s5-0 polar-external-tilt-max)))
                   )
               )
              (else
                (set! (-> s5-0 polar-internal-tilt-max) f28-0)
                (if (and (< (-> s5-0 polar-external-radius) f26-0) (< (-> s5-0 polar-external-tilt-max) 0.0))
                    (set! f28-0 (fmax f28-0 (-> s5-0 polar-external-tilt-max)))
                    )
                )
              )
            (let* ((f0-39 (sin f28-0))
                   (f24-0 (* f0-39 f0-39))
                   (f0-41 (cos f28-0))
                   (f0-43 (* f0-41 f0-41))
                   )
              32768.0
              (let ((f0-45 (cond
                             ((< 16384.0 f28-0)
                              (+ (* f24-0 (-> s5-0 upward-tilt)) (* f0-43 (-> s5-0 backward-twist)))
                              )
                             ((< f28-0 -16384.0)
                              (+ (* f24-0 (-> s5-0 downward-tilt)) (* f0-43 (-> s5-0 backward-twist)))
                              )
                             ((< 0.0 f28-0)
                              (+ (* f24-0 (-> s5-0 upward-tilt)) (* f0-43 (-> s5-0 forward-twist)))
                              )
                             (else
                               (+ (* f24-0 (-> s5-0 downward-tilt)) (* f0-43 (-> s5-0 forward-twist)))
                               )
                             )
                           )
                    )
                (if (< f0-45 f26-0)
                    (set! f26-0 f0-45)
                    )
                )
              )
            (let ((f26-1 (cos f26-0)))
              (set-vector! s2-0 (cos f28-0) (sin f28-0) 0.0 1.0)
              (let ((t9-18 vector-normalize!)
                    (a0-24 s2-0)
                    (f0-53 1.0)
                    (f1-22 f26-1)
                    )
                (t9-18 a0-24 (sqrtf (- f0-53 (* f1-22 f1-22))))
                )
              (set! (-> s2-0 z) f26-1)
              )
            )
          (matrix-transpose! s4-1 s4-1)
          (vector-matrix*! s2-0 s2-0 s4-1)
          (if (< f30-0 1.0)
              (matrix-from-two-vectors-partial-linear! s4-1 s3-0 s2-0 f30-0)
              (matrix-from-two-vectors! s4-1 s3-0 s2-0)
              )
          )
        (let ((s3-1 (matrix->trans (-> arg0 bone transform) (new 'stack-no-clear 'vector))))
          (set-vector! (-> arg0 bone transform trans) 0.0 0.0 0.0 1.0)
          (matrix*! (-> arg0 bone transform) (-> arg0 bone transform) s4-1)
          (when (logtest? (-> s5-0 flags) (joint-mod-polar-flags no-z-rot))
            (let ((a1-25 (vector-normalize-copy! (new 'stack-no-clear 'vector) (-> arg0 bone transform uvec) -1.0)))
              (matrix-remove-z-rot (-> arg0 bone transform) a1-25)
              )
            )
          (vector-copy! (-> arg0 bone transform trans) s3-1)
          )
        )
      )
    )
  0
  (none)
  )
