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

;; name: hvehicle-util.gc
;; name in dgo: hvehicle-util
;; dgos: HGA, CWI, LFACTORY

;; DECOMP BEGINS

(defmethod vehicle-controller-method-18 ((this vehicle-controller) (arg0 vector) (arg1 vector) (arg2 vehicle) (arg3 float))
  (local-vars (a0-95 int) (a0-97 int) (sv-16 vector) (sv-20 float) (sv-24 float))
  (let* ((v1-1 (-> *perf-stats* data 21))
         (a0-1 (-> v1-1 ctrl))
         )
    (+! (-> v1-1 count) 1)
    (b! (zero? a0-1) cfg-2 :delay (nop!))
    (.mtc0 Perf 0)
    (.sync.l)
    (.sync.p)
    (.mtpc pcr0 0)
    (.mtpc pcr1 0)
    (.sync.l)
    (.sync.p)
    (.mtc0 Perf a0-1)
    )
  (.sync.l)
  (.sync.p)
  (label cfg-2)
  0
  (set! sv-16 arg0)
  (set! sv-20 arg3)
  (set! sv-24 (-> arg2 info info inv-mass))
  (let ((gp-0 (new 'stack-no-clear 'vehicle-physics-work)))
    (set! (-> gp-0 dir x) (+ (-> this target-speed) (-> this target-speed-offset)))
    (vector-copy! (-> gp-0 mat uvec) arg1)
    (set! (-> gp-0 mat rvec quad) (-> arg2 root trans quad))
    (vector-z-quaternion! (-> gp-0 mat trans) (-> arg2 root quat))
    (vector-reset! (-> gp-0 mat fvec))
    (cond
      ((logtest? (-> this flags) (vehicle-controller-flag on-straightaway))
       (vector-! (-> gp-0 world-pos) (-> this turn-enter-point) (-> gp-0 mat rvec))
       (let ((f0-5 (vector-dot (-> gp-0 world-pos) (-> this turn-enter-dir))))
         (vector+float*! (-> gp-0 force) (-> this turn-enter-point) (-> this turn-enter-dir) (- f0-5))
         (vector-copy! (-> gp-0 velocity) (-> this turn-enter-dir))
         (if (>= 0.0 f0-5)
             (logclear! (-> this flags) (vehicle-controller-flag on-straightaway))
             )
         (when (not (logtest? (-> this flags) (vehicle-controller-flag no-slowing-for-turns)))
           (let ((f1-4 (* 0.5 (/ 1.0 (-> this turn-accel))))
                 (f2-2 (vector-length-squared arg1))
                 (f3-1 (-> this max-turn-speed))
                 )
             (if (>= (* f1-4 (- f2-2 (* f3-1 f3-1))) f0-5)
                 (set! (-> gp-0 dir x) (fmin (-> gp-0 dir x) (-> this max-turn-speed)))
                 )
             )
           )
         )
       )
      (else
        (if (not (logtest? (-> this flags) (vehicle-controller-flag no-slowing-for-turns)))
            (set! (-> gp-0 dir x) (fmin (-> gp-0 dir x) (-> this max-turn-speed)))
            )
        (vector-! (-> gp-0 world-pos) (-> gp-0 mat rvec) (-> this dest-circle))
        (vector-normalize! (-> gp-0 world-pos) 1.0)
        (set! (-> gp-0 velocity x) (- (-> gp-0 world-pos z)))
        (set! (-> gp-0 velocity y) 0.0)
        (set! (-> gp-0 velocity z) (-> gp-0 world-pos x))
        (if (logtest? (-> this flags) (vehicle-controller-flag left-turn))
            (vector-float*! (-> gp-0 velocity) (-> gp-0 velocity) -1.0)
            )
        (vector-float*! (-> gp-0 world-pos) (-> gp-0 world-pos) (-> this dest-circle w))
        (vector+! (-> gp-0 force) (-> this dest-circle) (-> gp-0 world-pos))
        (when (logtest? (-> this flags) (vehicle-controller-flag attached))
          (vector-! (-> gp-0 steering-axis) (-> this turn-exit-point) (-> gp-0 mat rvec))
          (when (and (< (vector-dot (-> this turn-exit-dir) (-> gp-0 steering-axis)) 0.0)
                     (>= (vector-dot (-> this turn-exit-dir) (-> gp-0 mat trans)) (cos 8192.0))
                     )
            (if (not (vehicle-controller-method-14 this arg2))
                (set! (-> gp-0 dir x) 0.0)
                )
            )
          )
        )
      )
    (set! (-> gp-0 force y) (-> gp-0 mat rvec y))
    (when (and (nonzero? (-> this traffic))
               (not (logtest? (-> this flags) (vehicle-controller-flag ignore-others)))
               (let ((f0-22 (-> arg2 camera-dist2))
                     (f1-9 1228800.0)
                     )
                 (< f0-22 (* f1-9 f1-9))
                 )
               )
      (let ((s3-1 (new 'stack-no-clear 'array 'collide-shape 10))
            (f30-1 (-> arg2 root root-prim prim-core world-sphere w))
            )
        (countdown (s4-1 (fill-actor-list-for-sphere
                           (-> this traffic object-hash)
                           (-> gp-0 mat rvec)
                           (-> gp-0 mat uvec)
                           (* 1.5 f30-1)
                           s3-1
                           10
                           (-> arg2 traffic-hash-id)
                           )
                         )
          (let ((v1-70 (as-type (-> s3-1 s4-1) hvehicle)))
            (when (and v1-70 (not (logtest? (-> v1-70 v-flags) (vehicle-flag dead))) (nonzero? (-> v1-70 flight-level-index)))
              (vector-copy! (-> gp-0 lift-dir) (-> v1-70 root trans))
              (vector-copy! (-> gp-0 normal) (-> v1-70 root transv))
              (vector-! (-> gp-0 tmp) (-> gp-0 mat rvec) (-> gp-0 lift-dir))
              (let ((f1-12 (vector-length-squared (-> gp-0 tmp))))
                (vector-float*! (-> gp-0 axis) (-> gp-0 tmp) (/ 1.0 (sqrtf f1-12)))
                (when #t
                  (let* ((f0-28 (+ f30-1 (-> v1-70 root root-prim prim-core world-sphere w)))
                         (f28-0 (* f0-28 f0-28))
                         )
                    (let ((f0-31 (fmax 0.0 (/ (- f28-0 f1-12) f28-0))))
                      (when (not (logtest? (vehicle-flag player-driving) (-> v1-70 v-flags)))
                        (when (and (< 0.0 sv-20) (< f1-12 f28-0))
                          (vector-! (-> gp-0 p-body) (-> gp-0 mat uvec) (-> gp-0 normal))
                          (let ((f1-14 (vector-dot (-> gp-0 axis) (-> gp-0 p-body))))
                            (when (< f1-14 0.0)
                              (vector-float*!
                                (-> gp-0 world-pos)
                                (-> gp-0 axis)
                                (* -0.5 (/ sv-24 (+ sv-24 (-> v1-70 info info inv-mass))) sv-20 f1-14)
                                )
                              (vector+! (-> gp-0 mat fvec) (-> gp-0 mat fvec) (-> gp-0 world-pos))
                              )
                            )
                          )
                        (vector-float*! (-> gp-0 world-pos) (-> gp-0 axis) (* 163840.0 f0-31))
                        (set! (-> gp-0 world-pos y) 0.0)
                        (vector+! (-> gp-0 mat fvec) (-> gp-0 mat fvec) (-> gp-0 world-pos))
                        )
                      )
                    (when (< (cos 8192.0) (- (vector-dot (-> gp-0 mat trans) (-> gp-0 axis))))
                      (when (< (nearest-dist2-between-moving-points
                                 (-> gp-0 mat rvec)
                                 (-> gp-0 mat uvec)
                                 (-> gp-0 lift-dir)
                                 (-> gp-0 normal)
                                 2.0
                                 )
                               f28-0
                               )
                        (let ((f0-37 (fmax 0.0 (vector-dot (-> gp-0 mat trans) (-> gp-0 normal)))))
                          (set! (-> gp-0 dir x) (fmin (-> gp-0 dir x) f0-37))
                          )
                        )
                      )
                    )
                  )
                )
              )
            )
          )
        )
      )
    (when (not (logtest? (-> this flags) (vehicle-controller-flag ignore-others)))
      (vector-! (-> gp-0 world-pos) (-> gp-0 force) (-> gp-0 mat rvec))
      (let ((f0-39 (vector-length-squared (-> gp-0 world-pos))))
        (logclear! (-> this flags) (vehicle-controller-flag off-path))
        (let ((f1-23 4096.0))
          (when (< (* f1-23 f1-23) f0-39)
            (logior! (-> this flags) (vehicle-controller-flag off-path))
            (let ((t9-8 vector-normalize!)
                  (a0-68 (-> gp-0 world-pos))
                  (f1-26 12288.0)
                  (f2-12 4096.0)
                  )
              (t9-8 a0-68 (fmin f1-26 (- f0-39 (* f2-12 f2-12))))
              )
            (vector+! (-> gp-0 mat fvec) (-> gp-0 mat fvec) (-> gp-0 world-pos))
            )
          )
        )
      (vector+float*!
        (-> gp-0 world-pos)
        (-> gp-0 mat uvec)
        (-> gp-0 velocity)
        (- (vector-dot (-> gp-0 velocity) (-> gp-0 mat uvec)))
        )
      (vector-! (-> gp-0 mat fvec) (-> gp-0 mat fvec) (-> gp-0 world-pos))
      )
    (cond
      ((logtest? (-> this flags) (vehicle-controller-flag direct-mode))
       (vector-! (-> gp-0 world-normal) (-> this turn-exit-point) (-> gp-0 mat rvec))
       (vector-normalize! (-> gp-0 world-normal) (-> gp-0 dir x))
       (vector-! (-> gp-0 world-pos) (-> gp-0 world-normal) (-> gp-0 mat uvec))
       (vector-float*! (-> gp-0 world-pos) (-> gp-0 world-pos) 3.0)
       (let ((f0-48 (vector-dot (-> gp-0 mat trans) (-> gp-0 world-pos))))
         (if (< f0-48 0.0)
             (vector+float*! (-> gp-0 world-pos) (-> gp-0 world-pos) (-> gp-0 mat trans) (* -0.875 f0-48))
             )
         )
       )
      (else
        (vector+float*! (-> gp-0 local-pos) (-> gp-0 mat rvec) (-> gp-0 mat uvec) 0.4)
        (vector-! (-> gp-0 world-pos) (-> gp-0 local-pos) (-> this turn-enter-point))
        (cond
          ((< (vector-dot (-> gp-0 world-pos) (-> this turn-enter-dir)) 0.0)
           (vector-! (-> gp-0 world-normal) (-> this turn-enter-point) (-> gp-0 mat rvec))
           )
          ((begin
             (vector-! (-> gp-0 world-pos) (-> gp-0 local-pos) (-> this turn-exit-point))
             (< (vector-dot (-> gp-0 world-pos) (-> this turn-exit-dir)) 0.0)
             )
           (vector-! (-> gp-0 world-pos) (-> gp-0 local-pos) (-> this dest-circle))
           (set! (-> gp-0 world-normal x) (- (-> gp-0 world-pos z)))
           (set! (-> gp-0 world-normal y) 0.0)
           (set! (-> gp-0 world-normal z) (-> gp-0 world-pos x))
           (if (logtest? (-> this flags) (vehicle-controller-flag left-turn))
               (vector-float*! (-> gp-0 world-normal) (-> gp-0 world-normal) -1.0)
               )
           )
          (else
            (vector-copy! (-> gp-0 world-normal) (-> this turn-exit-dir))
            )
          )
        (let ((f0-60 (vector-length (-> gp-0 world-normal))))
          (if (< 0.1 f0-60)
              (vector-float*! (-> gp-0 world-normal) (-> gp-0 world-normal) (/ (-> gp-0 dir x) f0-60))
              )
          )
        (vector-! (-> gp-0 world-pos) (-> gp-0 world-normal) (-> gp-0 mat uvec))
        (vector-float*! (-> gp-0 world-pos) (-> gp-0 world-pos) 2.0)
        )
      )
    (vector+! (-> gp-0 mat fvec) (-> gp-0 mat fvec) (-> gp-0 world-pos))
    (vector-copy! sv-16 (-> gp-0 mat fvec))
    )
  (let ((v1-144 (-> *perf-stats* data 21)))
    (b! (zero? (-> v1-144 ctrl)) cfg-76 :delay (nop!))
    (.mtc0 Perf 0)
    (.sync.l)
    (.sync.p)
    (.mfpc a0-95 pcr0)
    (+! (-> v1-144 accum0) a0-95)
    (.mfpc a0-97 pcr1)
    (+! (-> v1-144 accum1) a0-97)
    )
  (label cfg-76)
  0
  0
  (none)
  )

(defmethod vehicle-controller-method-12 ((this vehicle-controller)
                                        (arg0 rigid-body-vehicle-constants)
                                        (arg1 vector)
                                        (arg2 float)
                                        (arg3 int)
                                        (arg4 float)
                                        )
  0
  (none)
  )

(defmethod adjust-throttle ((this hvehicle) (arg0 float))
  (let* ((v1-1 (-> this rbody lin-velocity))
         (f0-4 (sqrtf (+ (* (-> v1-1 x) (-> v1-1 x)) (* (-> v1-1 z) (-> v1-1 z)))))
         (f0-6 (/ (- arg0 f0-4) arg0))
         (f1-6 (/ f0-6 200))
         )
    (set! (-> this controls throttle) (fmax 0.0 (fmin 1.0 (+ (-> this controls throttle) f1-6))))
    )
  0
  (none)
  )

(defmethod vehicle-method-133 ((this hvehicle) (arg0 traffic-object-spawn-params))
  (vehicle-rider-spawn this citizen-norm-rider arg0)
  0
  (none)
  )

;; WARN: Found some very strange gotos. Check result carefully, this is not well tested.
(defmethod hvehicle-method-158 ((this hvehicle))
  (logclear! (-> this controller flags) (vehicle-controller-flag ignore-others direct-mode))
  (let ((s5-0 (new 'stack-no-clear 'inline-array 'vector 2)))
    (vector-copy! (-> s5-0 0) (-> this root trans))
    (vector-copy! (-> s5-0 1) (-> this root transv))
    (set! (-> s5-0 0 w) 40960.0)
    (let ((s4-0 0))
      (label cfg-1)
      (let ((v1-7 (find-best-segment (-> this controller traffic) (-> s5-0 0) (-> s5-0 1) 0)))
        (when (and (not v1-7) (< s4-0 3))
          (+! (-> s5-0 0 w) 40960.0)
          (+! s4-0 1)
          (goto cfg-1)
          )
        (if v1-7
            (vehicle-controller-method-13 (-> this controller) (-> v1-7 branch) (-> this root trans))
            (vehicle-method-109 this)
            )
        )
      )
    )
  0
  (none)
  )

(defmethod hvehicle-method-154 ((this hvehicle))
  (when (and (logtest? (-> this info flags) 64) (< (-> this flight-level-index) 1))
    1
    (cond
      ((< (+ 8192.0 (-> this rbody position y)) (-> this flight-level))
       (sound-play "bike-up")
       (transition-flight-level this 1)
       )
      (else
        (set! (-> this flight-level-index) 1)
        )
      )
    )
  0
  (none)
  )

(defmethod hvehicle-method-155 ((this hvehicle))
  (when (and (logtest? (-> this info flags) 64) (> (-> this flight-level-index) 0))
    (sound-play "bike-down")
    (transition-flight-level this 0)
    )
  0
  (none)
  )

(defmethod hvehicle-method-156 ((this hvehicle))
  (logclear! (-> this v-flags) (vehicle-flag flight-level-transition))
  (vehicle-method-87 this)
  (set! (-> this flight-level-index) 0)
  0
  (none)
  )

(defmethod transition-flight-level ((this hvehicle) (arg0 int))
  (set! (-> this flight-level-index-prev) (-> this flight-level-index))
  (set! (-> this flight-level-index) arg0)
  (logior! (-> this v-flags) (vehicle-flag flight-level-transition camera-rapid-tracking-mode))
  (logclear! (-> this v-flags) (vehicle-flag flight-level-transition-ending))
  (set-time! (-> this transition-time))
  (vehicle-method-86 this)
  0
  (none)
  )

(defmethod hvehicle-method-153 ((this hvehicle))
  (logclear! (-> this v-flags) (vehicle-flag flight-level-transition))
  (logior! (-> this v-flags) (vehicle-flag flight-level-transition-ending))
  (set-time! (-> this transition-end-time))
  0
  (none)
  )

(defmethod vehicle-method-139 ((this hvehicle))
  (logior! (-> this nav flags) (nav-control-flag display-marks))
  (logclear! (-> this nav flags) (nav-control-flag output-sphere-hash))
  0
  (none)
  )

(defmethod vehicle-method-82 ((this hvehicle))
  (call-parent-method this)
  (let ((v1-0 (process->ppointer this)))
    (persist-with-delay
      *setting-control*
      'butt-handle
      (seconds 1)
      'butt-handle
      (the-as symbol v1-0)
      32768.0
      (-> v1-0 0 pid)
      )
    )
  (set-setting! 'slave-options 'set 0.0 (cam-slave-options BUTT_CAM))
  0
  (none)
  )
