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

;; name: squad-control.gc
;; name in dgo: squad-control
;; dgos: HGA, LPATK, RAILA, LFACCAR, CWI, WASALL, LFACTORY, COMBA

(deftype squad-control-stack-type0 (structure)
  ((vec0 vector :inline :offset 0)
   (vec1 vector :inline :offset 16)
   (float0 float :offset 32)
   (byte0 int8 :offset 36)
   (mesh nav-mesh :offset 40)
   (cquery collide-query :inline :offset 64)
   (vec2 vector :inline :offset 272)
   (vec3 vector :inline :offset 288)
   (float1 float :offset 604)
   (float2 float :offset 608)
   (float3 float :offset 612)
   )
  )

;; DECOMP BEGINS

(defmethod init! ((this squad-alert-state))
  (set! (-> this flags) (squad-alert-flag))
  (set! (-> this level) (the-as uint 0))
  (set! (-> this duration) (the-as uint 9000))
  (set! (-> this alarm-sound-id) (new-sound-id))
  (set! (-> this guard-inaccuracy-factor) 1.0)
  (dotimes (v1-2 3)
    (let ((a0-4 (-> this target-status-array v1-2)))
      (set! (-> a0-4 flags) (squad-target-flag))
      (set! (-> a0-4 handle) (the-as handle #f))
      (vector-reset! (-> a0-4 position))
      (vector-reset! (-> a0-4 velocity))
      (set! (-> a0-4 threat-level) 0.0)
      )
    )
  0
  (none)
  )

(defmethod initialize ((this squad-control) (arg0 process))
  0
  (none)
  )

(defmethod squad-control-method-10 ((this squad-control))
  (init! (-> this alert-state))
  (init-alert this)
  0
  (none)
  )

(defmethod stop-alarm-sound ((this squad-control))
  (sound-stop (-> this alert-state alarm-sound-id))
  0
  (none)
  )

(defmethod init-alert ((this squad-control))
  (logclear!
    (-> this alert-state flags)
    (squad-alert-flag guard-multi-focus sticky-guard-settings disable-pursuit-control war)
    )
  (let ((v1-2 (-> this alert-state target-status-array)))
    (logclear! (-> v1-2 0 flags) (squad-target-flag force-visible))
    )
  (set-alert-duration this (seconds 30))
  (set-alert-level this 4)
  0
  (none)
  )

(defmethod set-sync-mask ((this squad-control))
  (+! (-> this sync-clock) 1)
  (let ((v1-2 (-> this sync-clock)))
    (set! (-> this sync-mask-8) (the-as uint (ash 1 (the-as int (logand v1-2 7)))))
    (set! (-> this sync-mask-16) (the-as uint (ash 1 (the-as int (logand v1-2 15)))))
    (set! (-> this sync-mask-32) (the-as uint (ash 1 (the-as int (logand v1-2 31)))))
    )
  0
  (none)
  )

(defmethod update ((this squad-control))
  (set-sync-mask this)
  0
  (none)
  )

;; og:preserve-this duplicate
; (defmethod squad-control-method-17 ((this squad-control) (arg0 vector) (arg1 int) (arg2 squad-target-status))
;   arg2
;   )

(defmethod squad-control-method-18 ((this squad-control) (arg0 int) (arg1 process))
  (if (logtest? (-> this alert-state flags) (squad-alert-flag war))
      (return 0)
      )
  (when (valid-target-handle? this (process->handle arg1))
    (let ((v1-10 (min arg0 (the-as int (-> this alert-state max-level)))))
      (if (< (-> this alert-state level) (the-as uint v1-10))
          (logior! (-> this alert-state flags) (squad-alert-flag update-target-search))
          )
      (set-time! (-> this alert-state start-time))
      (logclear! (-> this alert-state flags) (squad-alert-flag alert-ending))
      (set! (-> this alert-state level) (the-as uint (max (the-as int (-> this alert-state level)) v1-10)))
      )
    )
  0
  )

(defmethod set-alert-level0 ((this squad-control) (arg0 int))
  (if (logtest? (-> this alert-state flags) (squad-alert-flag war))
      (return 0)
      )
  (set! (-> this alert-state level) (the-as uint (min (the-as int (-> this alert-state level)) arg0)))
  0
  )

(defmethod start-alert ((this squad-control) (arg0 int))
  (set! (-> this alert-state level) (the-as uint arg0))
  (set-time! (-> this alert-state start-time))
  (logclear! (-> this alert-state flags) (squad-alert-flag alert-ending))
  0
  (none)
  )

(defmethod set-alert-level ((this squad-control) (arg0 int))
  (set! (-> this alert-state max-level) (the-as uint arg0))
  (set! (-> this alert-state level) (the-as uint (min (the-as int (-> this alert-state level)) arg0)))
  0
  (none)
  )

(defmethod get-alert-level ((this squad-control))
  (if (logtest? (-> this alert-state flags) (squad-alert-flag war))
      (return 0)
      )
  (the-as int (-> this alert-state level))
  )

(defmethod set-alert-duration ((this squad-control) (arg0 time-frame))
  (set! (-> this alert-state duration) (the-as uint arg0))
  0
  (none)
  )

(defmethod probe-backgnd-collision ((this squad-control) (arg0 vector) (arg1 vector))
  (let ((v1-0 (new 'stack-no-clear 'collide-query)))
    (vector-copy! (-> v1-0 start-pos) arg0)
    (vector-! (-> v1-0 move-dist) arg1 arg0)
    (let ((a0-4 v1-0))
      (set! (-> a0-4 radius) 2048.0)
      (set! (-> a0-4 collide-with) (collide-spec backgnd))
      (set! (-> a0-4 ignore-process0) #f)
      (set! (-> a0-4 ignore-process1) #f)
      (set! (-> a0-4 ignore-pat)
            (new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1 :noendlessfall #x1 :board #x1)
            )
      (set! (-> a0-4 action-mask) (collide-action solid))
      )
    (< (fill-and-probe-using-line-sphere *collide-cache* v1-0) 0.0)
    )
  )

(defmethod squad-control-method-16 ((this squad-control) (arg0 vector) (arg1 process-focusable) (arg2 squad-target-status))
  (cond
    ((zero? (get-idx-in-status-arr this (process->handle arg1)))
     (let ((s5-1 (-> this alert-state target-status-array)))
       (let ((s4-0 (new 'stack-no-clear 'inline-array 'primary-target-pos-vel 2)))
         (set-pos-vel this (-> s4-0 0))
         (set! (-> s4-0 1 position quad) (-> s4-0 0 position quad))
         (logior! (-> s5-1 0 flags) (squad-target-flag updated))
         (cond
           ((or (logtest? (-> s5-1 0 flags) (squad-target-flag force-visible))
                (probe-backgnd-collision this arg0 (-> s4-0 1 position))
                )
            (logior! (-> s5-1 0 flags) (squad-target-flag visible-now visible-recently visible-ever))
            (set-time! (-> s5-1 0 last-seen-time))
            (vector-copy! (-> s5-1 0 position) (-> s4-0 1 position))
            (vector-copy! (-> s5-1 0 velocity) (-> s4-0 0 velocity))
            )
           (else
             (logclear! (-> s5-1 0 flags) (squad-target-flag visible-now))
             (if (time-elapsed? (-> s5-1 0 last-seen-time) (seconds 2))
                 (logclear! (-> s5-1 0 flags) (squad-target-flag visible-recently))
                 )
             )
           )
         )
       (mem-copy! (the-as pointer arg2) (the-as pointer s5-1) 68)
       )
     0
     )
    (else
      (logior! (-> arg2 flags) (squad-target-flag visible-now visible-recently visible-ever))
      (set-time! (-> arg2 last-seen-time))
      (vector-copy! (-> arg2 position) (get-trans arg1 3))
      (vector-copy! (-> arg2 velocity) (get-transv arg1))
      )
    )
  0
  (none)
  )

;; WARN: Return type mismatch object vs symbol.
(defmethod valid-target-handle? ((this squad-control) (arg0 handle))
  (the-as symbol (and (handle->process arg0) (= (get-idx-in-status-arr this arg0) 0)))
  )

(defmethod squad-control-method-17 ((this squad-control) (arg0 vector) (arg1 int) (arg2 squad-target-status))
  (logclear! (-> arg2 flags) (squad-target-flag visible-now updated))
  (cond
    ((or (= (-> this sync-mask-16) (ash 1 (logand arg1 15)))
         (or (logtest? (-> this alert-state flags) (squad-alert-flag update-target-search))
             (< (get-idx-in-status-arr this (-> arg2 handle)) 0)
             )
         )
     (logclear! (-> this alert-state flags) (squad-alert-flag update-target-search))
     (logior! (-> arg2 flags) (squad-target-flag updated))
     (let ((a2-1 (handle->process (-> arg2 handle))))
       (if a2-1
           (squad-control-method-16 this arg0 (the-as process-focusable a2-1) arg2)
           )
       )
     )
    (else
      (when (and (handle->process (-> arg2 handle)) (valid-target-handle? this (-> arg2 handle)))
        (let ((s4-1 (-> this alert-state target-status-array)))
          (when (logtest? (-> s4-1 0 flags) (squad-target-flag visible-recently))
            (let ((s3-0 (new 'stack-no-clear 'primary-target-pos-vel)))
              (set-pos-vel this (the-as primary-target-pos-vel (-> s3-0 position)))
              (vector-copy! (-> s4-1 0 position) (-> s3-0 position))
              (vector-copy! (-> s4-1 0 velocity) (-> s3-0 velocity))
              )
            )
          (mem-copy! (the-as pointer arg2) (the-as pointer s4-1) 68)
          )
        )
      (logclear! (-> arg2 flags) (squad-target-flag updated))
      )
    )
  arg2
  )

(defmethod squad-control-method-24 ((this squad-control))
  (if (not (handle->process (-> this alert-state target-status handle)))
      (return 0)
      )
  (let ((s4-0 (as-type (handle->process (-> this alert-state target-status handle)) process-focusable)))
    (when s4-0
      (let ((s5-1 (new 'stack-no-clear 'primary-target-pos-vel)))
        (vector-copy! (-> s5-1 position) (get-trans (the-as process-focusable s4-0) 3))
        (vector-copy! (-> s5-1 velocity) (get-transv (the-as process-focusable s4-0)))
        (set! (-> s5-1 time) (the-as uint (current-time)))
        (if (>= (- (-> s5-1 time) (-> this primary-target-history 1 time)) (the-as uint 30))
            (qmem-copy->!
              (the-as pointer (-> this primary-target-history 1))
              (the-as pointer (-> this primary-target-history))
              480
              )
            )
        (mem-copy! (the-as pointer (-> this primary-target-history)) (the-as pointer (-> s5-1 position)) 32)
        )
      0
      )
    )
  0
  )

;; WARN: Return type mismatch primary-target-pos-vel vs none.
(defmethod squad-control-method-25 ((this squad-control) (arg0 primary-target-pos-vel) (arg1 time-frame))
  (let ((s5-0 (new 'stack-no-clear 'inline-array 'primary-target-pos-vel 2)))
    (set! (-> s5-0 0 time) (the-as uint (- (current-time) arg1)))
    (let ((v1-3 0))
      (let ((a1-1 0))
        (b! #t cfg-7 :delay (nop!))
        (label cfg-1)
        (b!
          (not (and (>= (-> this primary-target-history a1-1 time) (-> s5-0 0 time))
                    (>= (-> s5-0 0 time) (-> this primary-target-history (+ a1-1 1) time))
                    )
               )
          cfg-6
          :delay (empty-form)
          )
        (set! v1-3 a1-1)
        (b! #t cfg-9 :delay (nop!))
        (label cfg-6)
        (+! a1-1 1)
        (label cfg-7)
        (b! (< a1-1 14) cfg-1)
        )
      (set! (-> s5-0 0 time) (-> this primary-target-history 0 time))
      (label cfg-9)
      (let ((s4-0 (-> this primary-target-history v1-3))
            (s3-0 (-> this primary-target-history (+ v1-3 1)))
            )
        (set! (-> s5-0 1 position x)
              (/ (the float (- (-> s5-0 0 time) (-> s4-0 time))) (the float (- (-> s3-0 time) (-> s4-0 time))))
              )
        (vector-lerp! (-> arg0 position) (-> s4-0 position) (-> s3-0 position) (-> s5-0 1 position x))
        (vector-lerp! (-> arg0 velocity) (-> s4-0 velocity) (-> s3-0 velocity) (-> s5-0 1 position x))
        )
      )
    (set! (-> arg0 time) (-> s5-0 0 time))
    )
  (none)
  )

(defmethod set-pos-vel ((this squad-control) (arg0 primary-target-pos-vel))
  (let ((s5-0 (as-type (handle->process (-> this alert-state target-status handle)) process-focusable)))
    (when s5-0
      (vector-copy! (-> arg0 position) (get-trans (the-as process-focusable s5-0) 3))
      (vector-copy! (-> arg0 velocity) (get-transv (the-as process-focusable s5-0)))
      )
    )
  arg0
  )

;; WARN: Return type mismatch float vs none.
(defmethod squad-control-method-27 ((this squad-control) (arg0 process) (arg1 float))
  (let ((a1-4 (process->handle arg0))
        (v1-2 (-> this alert-state target-status-array))
        )
    (when (!= (-> v1-2 0 handle) a1-4)
      (set! (-> v1-2 0 handle) (the-as handle a1-4))
      (set! (-> v1-2 0 flags) (squad-target-flag))
      (vector-reset! (-> v1-2 0 position))
      (vector-reset! (-> v1-2 0 velocity))
      (set! (-> v1-2 0 threat-level) arg1)
      )
    )
  (none)
  )

(defmethod get-idx-in-status-arr ((this squad-control) (arg0 handle))
  (if (not (handle->process arg0))
      (return -1)
      )
  (dotimes (v1-5 3)
    (if (= (-> this alert-state target-status-array v1-5 handle) arg0)
        (return v1-5)
        )
    )
  -1
  )

;; WARN: Return type mismatch process vs process-focusable.
(defmethod get-target-focus ((this squad-control))
  (the-as
    process-focusable
    (as-type (handle->process (-> this alert-state target-status handle)) process-focusable)
    )
  )

;; WARN: Return type mismatch process vs process-focusable.
(defmethod get-focus-in-range ((this squad-control) (arg0 process-focusable))
  (let* ((f0-0 4915200.0)
         (f30-0 (* f0-0 f0-0))
         (s4-0 (the-as process #f))
         )
    (dotimes (s3-0 3)
      (let ((s2-0 (as-type (handle->process (-> this alert-state target-status-array s3-0 handle)) process-focusable)))
        (when s2-0
          (let ((f0-2 (vector-vector-xz-distance-squared (-> arg0 root trans) (get-trans (the-as process-focusable s2-0) 0)))
                )
            (when (< f0-2 f30-0)
              (set! f30-0 f0-2)
              (set! s4-0 s2-0)
              )
            )
          )
        )
      )
    (the-as process-focusable s4-0)
    )
  )

;; WARN: Return type mismatch vector vs none.
(defmethod squad-control-method-31 ((this squad-control) (arg0 vector) (arg1 process-focusable) (arg2 handle) (arg3 float) (arg4 float))
  (local-vars (sv-672 float) (sv-688 vector) (sv-704 int))
  (rlet ((vf0 :class vf)
         (vf4 :class vf)
         (vf5 :class vf)
         (vf6 :class vf)
         )
    (init-vf0-vector)
    (set! sv-672 arg4)
    (let ((s5-0 (get-handle-pos this arg2 (new 'stack-no-clear 'vector))))
      (let ((s3-1 (vector-! (new 'stack-no-clear 'vector) s5-0 (-> arg1 root trans))))
        (set! sv-688 s5-0)
        (set! (-> s3-1 y) 0.0)
        (vector-normalize! s3-1 1.0)
        (let ((s2-0 (new 'stack-no-clear 'squad-control-stack-type0))
              (s1-0 (the-as nav-mesh #f))
              (f30-0 sv-672)
              )
          (if (and (nonzero? (-> arg1 nav)) (-> arg1 nav))
              (set! s1-0 (-> arg1 nav state mesh))
              )
          (if (not s1-0)
              (set! s1-0 (find-nearest-nav-mesh sv-688 (the-as float #x7f800000)))
              )
          (when s1-0
            (nav-mesh-method-10 s1-0 sv-688 sv-688 (the-as nav-poly #f))
            (set! (-> s2-0 float0) 40960.0)
            (set! (-> s2-0 byte0) 2)
            (vector-! (-> s2-0 vec1) sv-688 (the-as vector (-> s1-0 bounds)))
            (nav-mesh-method-46 s1-0 (the-as nav-poly (-> s2-0 vec1)))
            (let ((s0-1 (-> s2-0 mesh)))
              (when s0-1
                (project-point-into-poly-2d s1-0 (the-as nav-poly s0-1) (-> s2-0 vec1) (-> s2-0 vec1))
                (let ((v1-18 (-> s2-0 vec1))
                      (a0-9 (-> s1-0 bounds))
                      )
                  (.mov.vf.w vf6 vf0)
                  (.lvf vf4 (&-> v1-18 quad))
                  (.lvf vf5 (&-> a0-9 quad))
                  )
                (.add.vf.xyz vf6 vf4 vf5)
                (.svf (&-> sv-688 quad) vf6)
                (set! sv-704 0)
                (while (< sv-704 16)
                  (when #t
                    (set! (-> s2-0 float1)
                          (the float (sar (shl (the int (+ f30-0 (* 182.04445 (* 22.5 (the float sv-704))))) 48) 48))
                          )
                    (set! (-> s2-0 float2) arg3)
                    (vector-rotate-around-y! (-> s2-0 vec0) s3-1 (-> s2-0 float1))
                    (vector-float*! (-> s2-0 vec0) (-> s2-0 vec0) (-> s2-0 float2))
                    (clamp-vector-to-mesh-cross-gaps
                      s1-0
                      (-> s2-0 vec1)
                      (the-as nav-poly s0-1)
                      (-> s2-0 vec0)
                      (-> s2-0 float2)
                      #f
                      (the-as clamp-travel-vector-to-mesh-return-info #f)
                      )
                    (vector-copy! (-> s2-0 cquery start-pos) s5-0)
                    (vector-copy! (-> s2-0 cquery move-dist) (-> s2-0 vec0))
                    (let ((v1-34 (-> s2-0 cquery)))
                      (set! (-> v1-34 radius) 2048.0)
                      (set! (-> v1-34 collide-with) (collide-spec backgnd))
                      (set! (-> v1-34 ignore-process0) #f)
                      (set! (-> v1-34 ignore-process1) #f)
                      (set! (-> v1-34 ignore-pat)
                            (new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1 :noendlessfall #x1 :board #x1)
                            )
                      (set! (-> v1-34 action-mask) (collide-action solid))
                      )
                    (set! (-> s2-0 float3) (fill-and-probe-using-line-sphere *collide-cache* (-> s2-0 cquery)))
                    (if (< 0.0 (-> s2-0 float3))
                        (vector-float*! (-> s2-0 vec0) (-> s2-0 vec0) (-> s2-0 float3))
                        )
                    (let ((f0-17 (vector-length-squared (-> s2-0 vec0)))
                          (f1-4 (/ arg3 2))
                          )
                      (when (< (* f1-4 f1-4) f0-17)
                        (vector+! s5-0 s5-0 (-> s2-0 vec0))
                        0
                        (goto cfg-19)
                        )
                      )
                    )
                  (set! sv-704 (+ sv-704 1))
                  )
                )
              )
            )
          )
        )
      (label cfg-19)
      (vector-copy! arg0 s5-0)
      )
    (none)
    )
  )

(defmethod get-handle-pos ((this squad-control) (arg0 handle) (arg1 vector))
  (let ((a0-5 (as-type (handle->process arg0) process-focusable)))
    (new 'stack-no-clear 'vector)
    (if a0-5
        (vector-copy! arg1 (get-trans (the-as process-focusable a0-5) 0))
        )
    )
  arg1
  )
