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

;; name: fac-robotank-turret.gc
;; name in dgo: fac-robotank-turret
;; dgos: LFACTORY

;; +++fac-robotank-turret-flag
(defenum fac-robotank-turret-flag
  :type uint16
  :bitfield #t
  (frt0 0)
  (frt1 1)
  (frt2 2)
  (frt3 3)
  (frt4 4)
  (frt5 5)
  (frt6 6)
  (frt7 7)
  (frt8 8)
  (frt9 9)
  (frt10 10)
  )
;; ---fac-robotank-turret-flag


;; DECOMP BEGINS

(deftype fac-robotank-turret (process-focusable)
  ((los                  los-control  :inline)
   (tank-quat            quaternion   :inline)
   (tank-quat-vibe-only  quaternion   :inline)
   (rotate-quat          quaternion   :inline)
   (rotate-rate          float)
   (rotate-mult          float)
   (shot-range           float)
   (fov-mult             float)
   (offset               vector       :inline)
   (sight-pos            vector       :inline)
   (firing-sight-pos     vector       :inline)
   (aim-pos              vector       3 :inline)
   (gun-timer            time-frame)
   (gun-elev-jmod        joint-mod)
   (gun-elev             float)
   (gun-elev-cam         float)
   (gun-joint-l          int32        2)
   (gun-joint-r          int32        2)
   (gun-spread           float)
   (gun-index            int32)
   (flags                fac-robotank-turret-flag)
   (turn-sound-id        sound-id)
   )
  (:state-methods
    ready
    fire
    die
    )
  (:methods
    (fac-robotank-turret-method-31 (_type_ vector vector) object)
    (fac-robotank-turret-method-32 (_type_ (inline-array vector)) (pointer ftank-shot))
    (fac-robotank-turret-method-33 (_type_) none)
    (fac-robotank-turret-method-34 (_type_ vector float) symbol)
    )
  )


(deftype fac-robotank-reticle (process-drawable)
  ((shadow-jmod   joint-mod-set-local)
   (sight-jmod    joint-mod-set-local)
   (ring-jmod     joint-mod  3)
   (ring-timer    time-frame)
   (sight-scale   vector     :inline)
   (collide-dist  float)
   )
  (:state-methods
    unlock
    lock
    )
  )


(defpartgroup group-robotank-steamescape
  :id 782
  :bounds (static-bspherem 0 0 0 6)
  :parts ((sp-item 2924 :fade-after (meters 100) :falloff-to (meters 100) :flags (sp7)))
  )

(defpart 2924
  :init-specs ((:texture (bigpuff level-default-sprite))
    (:num 0.5 1.0)
    (:x (meters -3) (meters 5))
    (:y (meters -0.1) (meters 0.3))
    (:z (meters 0.2) (meters 0.2))
    (:scale-x (meters 0.5) (meters 0.25))
    (:rot-z (degrees 0) (degrees 360))
    (:scale-y :copy scale-x)
    (:r 64.0 128.0)
    (:g :copy r)
    (:b :copy g)
    (:a 0.0)
    (:vel-z (meters 0.005) (meters 0.0025))
    (:scalevel-x (meters 0.0016666667) (meters 0.0033333334))
    (:rotvel-z (degrees -1.2) (degrees 2.4))
    (:scalevel-y :copy scalevel-x)
    (:fade-a 0.64)
    (:accel-y (meters 0.00016666666) (meters 0.00016666666))
    (:friction 0.99)
    (:timer (seconds 2))
    (:flags (sp-cpuinfo-flag-2 sp-cpuinfo-flag-13))
    (:next-time (seconds 0.085) (seconds 0.08))
    (:next-launcher 2925)
    (:launchrot-x (degrees -5) (degrees 10))
    (:launchrot-y (degrees -5) (degrees 10))
    (:rotate-y (degrees 0))
    )
  )

(defpart 2925
  :init-specs ((:fade-a -0.064 -0.064))
  )

(defbehavior fac-robotank-reticle-post fac-robotank-reticle ()
  (let ((s5-0 (vector-z-quaternion! (new 'stack-no-clear 'vector) (-> self root quat)))
        (s1-0 (new 'stack-no-clear 'vector))
        (s3-0 (camera-pos))
        (s4-0 (-> self draw shadow-ctrl settings shadow-dir))
        (gp-0 (-> self draw shadow-ctrl settings bot-plane))
        (s2-0 (-> self draw shadow-ctrl settings top-plane))
        )
    (-> self draw shadow-ctrl settings)
    (vector-normalize! s5-0 1.0)
    (vector-negate! s1-0 s5-0)
    (set! (-> s4-0 x) (-> s5-0 x))
    (set! (-> s4-0 y) (-> s5-0 y))
    (set! (-> s4-0 z) (-> s5-0 z))
    (set! (-> s4-0 w) -16384.0)
    (set! (-> s2-0 quad) (-> s5-0 quad))
    (set! (-> gp-0 quad) (-> s5-0 quad))
    (let ((s4-1 (new 'stack-no-clear 'vector)))
      (vector+float*! s4-1 (-> self root trans) s5-0 -4096.0)
      (set! (-> s2-0 w) (- (vector-dot s4-1 s5-0)))
      (vector+float*! s4-1 (-> self root trans) s5-0 (-> self collide-dist))
      (let* ((a1-6 (vector-! (new 'stack-no-clear 'vector) s3-0 s4-1))
             (f1-0 (vector-length a1-6))
             (a2-2
               (vector-normalize-copy! (new 'stack-no-clear 'vector) a1-6 (fmax -20480.0 (fmin 20480.0 (* 0.75 f1-0))))
               )
             (v1-26 (vector-float*! (new 'stack-no-clear 'vector) s5-0 (- (vector-dot a2-2 s5-0))))
             )
        (vector+! s4-1 s4-1 v1-26)
        )
      (set! (-> gp-0 w) (- (vector-dot s4-1 s5-0)))
      )
    )
  0
  (vector-seek! (-> self sight-jmod transform scale) (-> self sight-scale) (* 6.0 (seconds-per-frame)))
  (ja-post)
  (none)
  )

(defbehavior fac-robotank-reticle-handler fac-robotank-reticle ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  (local-vars (v0-0 object))
  (case arg2
    (('update-trans-only)
     (set! v0-0 (-> self root trans))
     (set! (-> (the-as vector v0-0) quad) (-> (the-as vector (-> arg3 param 0)) quad))
     v0-0
     )
    (('update)
     (let ((s5-0 (the-as vector (-> arg3 param 0)))
           (gp-0 (the-as vector (-> arg3 param 1)))
           )
       (let ((a1-3
               (vector-normalize-copy! (new 'stack-no-clear 'vector) (vector-! (new 'stack-no-clear 'vector) gp-0 s5-0) 1.0)
               )
             )
         (vector-copy! (-> self root trans) s5-0)
         (forward-up->quaternion (-> self root quat) a1-3 *up-vector*)
         )
       (let ((f0-0 (vector-length (vector-! (new 'stack-no-clear 'vector) gp-0 s5-0)))
             (gp-1 (-> self sight-scale))
             )
         (set! (-> gp-1 z) (/ f0-0 (meters 10)))
         (let ((f0-1 (lerp-scale 0.1 6.0 f0-0 61440.0 163840.0)))
           (set! (-> gp-1 x) f0-1)
           (set! (-> gp-1 y) f0-1)
           f0-1
           )
         )
       )
     )
    (('collide-dist)
     (set! (-> self collide-dist) (the-as float (-> arg3 param 0)))
     )
    (('on)
     (let ((v1-14 (-> self draw shadow-ctrl)))
       (logclear! (-> v1-14 settings flags) (shadow-flags disable-draw))
       )
     0
     (set! v0-0 (logclear (-> self draw status) (draw-control-status no-draw)))
     (set! (-> self draw status) (the-as draw-control-status v0-0))
     v0-0
     )
    (('off)
     (let ((v1-19 (-> self draw shadow-ctrl)))
       (logior! (-> v1-19 settings flags) (shadow-flags disable-draw))
       )
     0
     (set! v0-0 (logior (-> self draw status) (draw-control-status no-draw)))
     (set! (-> self draw status) (the-as draw-control-status v0-0))
     v0-0
     )
    (('spotlight-on)
     (let ((v1-25 (-> self draw shadow-ctrl)))
       (logclear! (-> v1-25 settings flags) (shadow-flags disable-draw))
       )
     0
     )
    (('spotlight-off)
     (let ((v1-27 (-> self draw shadow-ctrl)))
       (logior! (-> v1-27 settings flags) (shadow-flags disable-draw))
       )
     0
     )
    (('lock)
     (go-virtual lock)
     )
    (('unlock)
     (go-virtual unlock)
     )
    (('die)
     (go empty-state)
     )
    )
  )

(defskelgroup skel-fac-robotank-turret fac-robotank-top fac-robotank-top-lod0-jg fac-robotank-top-idle-ja
              ((fac-robotank-top-lod0-mg (meters 20)) (fac-robotank-top-lod1-mg (meters 999999)))
              :bounds (static-spherem 0 0 0 4)
              :origin-joint-index 3
              )

(defpart 2926
  :init-specs ((:texture (glow-hotdot level-default-sprite))
    (:num 1.0)
    (:scale-x (meters 1.5) (meters 0.1))
    (:rot-x (degrees 1.125))
    (:scale-y :copy scale-x)
    (:r 128.0 64.0)
    (:g 0.0)
    (:b :copy g)
    (:a 96.0 64.0)
    (:rotvel-z (degrees 0.3))
    (:fade-g -1.0666667)
    (:fade-b -1.0666667)
    (:fade-a -8.533334)
    (:timer (seconds 0.017))
    (:flags (sp-cpuinfo-flag-2 sp-cpuinfo-flag-14 glow))
    (:userdata 1.0)
    )
  )

;; WARN: Return type mismatch (pointer process) vs (pointer ftank-shot).
(defmethod fac-robotank-turret-method-32 ((this fac-robotank-turret) (arg0 (inline-array vector)))
  (let ((s4-0 (new 'stack-no-clear 'projectile-init-by-other-params)))
    (let ((s5-0 (-> arg0 0))
          (gp-0 (-> arg0 1))
          )
      (set! (-> s4-0 ent) (-> this entity))
      (set! (-> s4-0 charge) 1.0)
      (set! (-> s4-0 options) (projectile-options))
      (logclear! (-> s4-0 options) (projectile-options po14 po15 po16))
      (vector-copy! (-> s4-0 pos) s5-0)
      (set! (-> s4-0 notify-handle) (process->handle this))
      (set! (-> s4-0 owner-handle) (the-as handle #f))
      (set! (-> s4-0 target-handle) (the-as handle #f))
      (set! (-> s4-0 target-pos quad) (the-as uint128 0))
      (set! (-> s4-0 ignore-handle) (process->handle this))
      (let* ((v1-12 *game-info*)
             (a0-13 (+ (-> v1-12 attack-id) 1))
             )
        (set! (-> v1-12 attack-id) a0-13)
        (set! (-> s4-0 attack-id) a0-13)
        )
      (set! (-> s4-0 timeout) (seconds 4))
      (let ((s2-0 (new 'stack-no-clear 'vector)))
        (rand-vu-sphere-point-uniform! s2-0 (* 40960.0 (rand-vu)))
        (vector+! gp-0 gp-0 s2-0)
        )
      (vector-! (-> s4-0 vel) gp-0 s5-0)
      )
    (vector-normalize! (-> s4-0 vel) 512000.0)
    (the-as (pointer ftank-shot) (spawn-projectile ftank-shot s4-0 this *default-dead-pool*))
    )
  )

;; WARN: Return type mismatch (pointer ftank-shot) vs none.
(defmethod fac-robotank-turret-method-33 ((this fac-robotank-turret))
  (local-vars (sv-144 vector) (sv-160 vector))
  (let ((s3-0 (new 'stack-no-clear 'inline-array 'vector 2))
        (s5-0 (new 'stack-no-clear 'inline-array 'vector 2))
        )
    (-> this node-list data 11)
    (let ((s4-0 (new 'stack-no-clear 'vector))
          (s1-0 (-> this sight-pos))
          (s2-0 (-> this gun-index))
          )
      0.0
      0.0
      (vector<-cspace! (-> s3-0 0) (-> this node-list data (-> this gun-joint-l s2-0)))
      (vector<-cspace! (-> s3-0 1) (-> this node-list data (-> this gun-joint-r s2-0)))
      (let ((f30-0 (* 0.5 (vector-length (vector-! (new 'stack-no-clear 'vector) (-> s3-0 1) (-> s3-0 0))))))
        (let ((f28-0 (fmax 81920.0 (+ 12288.0 (vector-length (vector-! (new 'stack-no-clear 'vector) s1-0 (-> s3-0 0)))))))
          (vector-normalize-copy! s4-0 (-> this node-list data (-> this gun-joint-l s2-0) bone transform fvec) 1.0)
          (let ((s0-0 vector-rotate-y!))
            (set! sv-144 s4-0)
            (set! sv-160 s4-0)
            (let ((a2-1 (- 16384.0 (acos (/ f30-0 f28-0)))))
              (s0-0 sv-144 sv-160 a2-1)
              )
            )
          (vector-copy! (-> s5-0 0) (-> s3-0 0))
          (vector+float*! (-> s5-0 1) (-> s5-0 0) s4-0 512000.0)
          (set! (-> this shot-range) (fmin 204800.0 f28-0))
          )
        (fac-robotank-turret-method-32 this s5-0)
        (let ((f28-1 (fmax 81920.0 (+ 12288.0 (vector-length (vector-! (new 'stack-no-clear 'vector) s1-0 (-> s3-0 1)))))))
          (vector-normalize-copy! s4-0 (-> this node-list data (-> this gun-joint-r s2-0) bone transform fvec) 1.0)
          (vector-rotate-y! s4-0 s4-0 (- (- 16384.0 (acos (/ f30-0 f28-1)))))
          (vector-copy! (-> s5-0 0) (-> s3-0 1))
          (vector+float*! (-> s5-0 1) (-> s5-0 0) s4-0 512000.0)
          (set! (-> this shot-range) (fmin 204800.0 f28-1))
          )
        )
      )
    (fac-robotank-turret-method-32 this s5-0)
    )
  (none)
  )

(defmethod fac-robotank-turret-method-31 ((this fac-robotank-turret) (arg0 vector) (arg1 vector))
  (let ((s5-0 (new 'stack-no-clear 'collide-query))
        (f30-0 307200.0)
        )
    (vector-copy! (-> s5-0 start-pos) arg0)
    (vector-float*! (-> s5-0 move-dist) arg1 f30-0)
    (let ((v1-4 s5-0))
      (set! (-> v1-4 radius) 4096.0)
      (set! (-> v1-4 collide-with) (collide-spec backgnd jak bot enemy obstacle hit-by-others-list player-list))
      (set! (-> v1-4 ignore-process0) (ppointer->process (-> this parent)))
      (set! (-> v1-4 ignore-process1) this)
      (set! (-> v1-4 ignore-pat)
            (new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1 :noendlessfall #x1 :board #x1)
            )
      (set! (-> v1-4 action-mask) (collide-action solid semi-solid))
      )
    (let ((f28-0 (fill-and-probe-using-line-sphere *collide-cache* s5-0))
          (s4-1 (-> this sight-pos))
          )
      (cond
        ((>= f28-0 0.0)
         (let ((f0-3 (vector-length (-> s5-0 move-dist))))
           (if (>= 20480.0 (* f0-3 f28-0))
               (set! f28-0 (/ 20480.0 f0-3))
               )
           )
         (vector+float*! s4-1 (-> s5-0 start-pos) (-> s5-0 move-dist) f28-0)
         (let ((s3-0 (as-type (-> s5-0 best-other-tri collide-ptr) collide-shape-prim))
               (s5-2 (new 'stack-no-clear 'vector))
               )
           (vector-copy! s5-2 s4-1)
           (vector+float*! s5-2 s5-2 (-> (math-camera-matrix) fvec) -2048.0)
           (if (and s3-0
                    (logtest? (process-mask target enemy) (-> (the-as collide-shape-prim s3-0) cshape process mask))
                    (>= 307200.0 (vector-vector-distance s5-2 arg0))
                    )
               #f
               (+ 12288.0 (* f30-0 f28-0))
               )
           )
         )
        (else
          (vector+! s4-1 (-> s5-0 start-pos) (-> s5-0 move-dist))
          )
        )
      )
    )
  )

;; WARN: Return type mismatch collide-prim-core vs vector.
(defmethod get-trans ((this fac-robotank-turret) (arg0 int))
  "Get the `trans` for this process."
  (the-as vector (-> this root root-prim prim-core))
  )

(defbehavior turret-post fac-robotank-turret ()
  (let ((gp-0 (the-as target (as-type *target* process-focusable))))
    (cond
      ((and (logtest? (-> self flags) (fac-robotank-turret-flag frt0)) gp-0)
       (if (logtest? (-> self flags) (fac-robotank-turret-flag frt9))
           (format 0 "Fix Los control update~%")
           )
       (if *target*
           (look-at! (-> *target* neck) (-> self root root-prim prim-core world-sphere) 'attacking self)
           )
       (set! (-> self aim-pos 0 quad) (-> self aim-pos 1 quad))
       (vector-copy! (-> self aim-pos 1) (get-trans gp-0 0))
       (let ((s5-2 (-> self aim-pos 2))
             (s4-0 (vector<-cspace! (new 'stack-no-clear 'vector) (-> self node-list data (-> self gun-joint-l 0))))
             )
         (let ((v1-24 (vector<-cspace! (new 'stack-no-clear 'vector) (-> self node-list data (-> self gun-joint-r 0)))))
           (vector-! s5-2 (-> self aim-pos 1) (-> self aim-pos 0))
           (vector-float*! s5-2 s5-2 (* 0.8 (-> self clock frames-per-second)))
           (set! (-> s5-2 y) 0.0)
           (vector+! s5-2 (-> self aim-pos 1) s5-2)
           (+! (-> s5-2 y) 8192.0)
           (vector+! s4-0 s4-0 v1-24)
           )
         (vector-float*! s4-0 s4-0 0.5)
         (let ((gp-2 (vector-! (new 'stack-no-clear 'vector) s5-2 s4-0))
               (s3-1 (vector-! (new 'stack-no-clear 'vector) (-> self firing-sight-pos) s4-0))
               (s5-3 (new 'stack-no-clear 'vector))
               )
           (let ((f30-0 (vector-length gp-2)))
             (vector-normalize! gp-2 1.0)
             (vector-normalize! s3-1 1.0)
             (if (logtest? (-> self flags) (fac-robotank-turret-flag frt3))
                 (vector-copy! s5-3 s3-1)
                 (vector-copy! s5-3 gp-2)
                 )
             (when (logtest? (-> self flags) (fac-robotank-turret-flag frt7))
               (let ((f0-6 (lerp-scale 1.0 0.2 f30-0 8192.0 327680.0)))
                 (seek! (-> self fov-mult) f0-6 (* 2.0 (seconds-per-frame)))
                 )
               (set-setting! 'fov 'rel (-> self fov-mult) 0)
               )
             )
           (let* ((f30-1 (vector-y-angle s5-3))
                  (f0-11 (quaternion-y-angle (-> self rotate-quat)))
                  (f0-12 (deg-diff f0-11 f30-1))
                  )
             (* (-> self rotate-mult) f0-12)
             (let ((f1-6 25486.223))
               (set! (-> self rotate-rate) (fmax (fmin (* 4.0 f0-12) f1-6) (- f1-6)))
               )
             )
           (let ((f30-3 (fmax -16384.0 (fmin 16384.0 (- 16384.0 (acos (- (vector-dot s5-3 *y-vector*))))))))
             (let* ((f0-28 (fmax -16384.0 (fmin 16384.0 (- 16384.0 (acos (- (vector-dot gp-2 *y-vector*)))))))
                    (f2-1 (- (-> self gun-elev-cam) f0-28))
                    (f1-12 (if (< f2-1 0.0)
                               (fmin 3640.889 (* (fabs (/ f2-1 10)) (-> self clock frames-per-second)))
                               910.2222
                               )
                           )
                    )
               (seek! (-> self gun-elev-cam) f0-28 (* f1-12 (seconds-per-frame)))
               )
             (let* ((f28-2 (quaternion-y-angle (-> self rotate-quat)))
                    (f0-32 (quaternion-y-angle (-> self tank-quat)))
                    (f0-34 (* 2.0 (deg-diff f0-32 f28-2)))
                    (f0-35 (cos f0-34))
                    )
               0.0
               (if (< 0.0 f0-35)
                   (* 182.04445 (lerp 4.0 90.0 f0-35))
                   (* 182.04445 (lerp 4.0 18.0 (- f0-35)))
                   )
               )
             (seek! (-> self gun-elev) f30-3 (* 16384.0 (seconds-per-frame)))
             )
           )
         )
       (quaternion-axis-angle! (-> self gun-elev-jmod quat) 1.0 0.0 0.0 (-> self gun-elev))
       )
      (else
        )
      )
    )
  (when (and (logtest? (-> self flags) (fac-robotank-turret-flag frt0))
             (not (logtest? (-> self flags) (fac-robotank-turret-flag frt3)))
             )
    (let* ((a1-26 (-> self node-list data (-> self gun-joint-l 0)))
           (s4-1 (-> self node-list data (-> self gun-joint-r 0)))
           (gp-4
             (vector+!
               (new 'stack-no-clear 'vector)
               (vector<-cspace! (new 'stack-no-clear 'vector) a1-26)
               (vector<-cspace! (new 'stack-no-clear 'vector) s4-1)
               )
             )
           (a2-16
             (vector-normalize-copy! (new 'stack-no-clear 'vector) (-> self node-list data 11 bone transform fvec) 1.0)
             )
           )
      (vector-float*! gp-4 gp-4 0.5)
      (fac-robotank-turret-method-31 self gp-4 a2-16)
      )
    )
  (cond
    ((logtest? (-> self flags) (fac-robotank-turret-flag frt6))
     (sound-play "robotank-turret" :id (-> self turn-sound-id) :position (-> self root trans))
     (when (< (fabs (-> self rotate-rate)) 728.1778)
       (logclear! (-> self flags) (fac-robotank-turret-flag frt6))
       (sound-stop (-> self turn-sound-id))
       (sound-play "robo-turret-end")
       )
     )
    (else
      (if (< 2184.5334 (fabs (-> self rotate-rate)))
          (logior! (-> self flags) (fac-robotank-turret-flag frt6))
          )
      )
    )
  (quaternion-rotate-y!
    (-> self rotate-quat)
    (-> self rotate-quat)
    (* (-> self rotate-rate) (seconds-per-frame))
    )
  (quaternion*! (-> self root quat) (-> self rotate-quat) (-> self tank-quat-vibe-only))
  (quaternion-normalize! (-> self root quat))
  (transform-post)
  (none)
  )

(defbehavior robotank-turret-handler fac-robotank-turret ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  (local-vars (v0-0 object))
  (case arg2
    (('fire-suppress)
     (cond
       ((-> arg3 param 0)
        (set! v0-0 (logior (-> self flags) (fac-robotank-turret-flag frt4)))
        (set! (-> self flags) (the-as fac-robotank-turret-flag v0-0))
        )
       (else
         (set! v0-0 (logclear (-> self flags) (fac-robotank-turret-flag frt4)))
         (set! (-> self flags) (the-as fac-robotank-turret-flag v0-0))
         )
       )
     v0-0
     )
    (('set-spread)
     (set! (-> self gun-spread) (the-as float (-> arg3 param 0)))
     )
    (('use-los)
     (cond
       ((-> arg3 param 0)
        (set! v0-0 (logior (-> self flags) (fac-robotank-turret-flag frt9)))
        (set! (-> self flags) (the-as fac-robotank-turret-flag v0-0))
        )
       (else
         (set! v0-0 (logclear (-> self flags) (fac-robotank-turret-flag frt9)))
         (set! (-> self flags) (the-as fac-robotank-turret-flag v0-0))
         )
       )
     v0-0
     )
    (('limit-reticle-elev)
     (cond
       ((-> arg3 param 0)
        (set! v0-0 (logior (-> self flags) (fac-robotank-turret-flag frt10)))
        (set! (-> self flags) (the-as fac-robotank-turret-flag v0-0))
        )
       (else
         (set! v0-0 (logclear (-> self flags) (fac-robotank-turret-flag frt10)))
         (set! (-> self flags) (the-as fac-robotank-turret-flag v0-0))
         )
       )
     v0-0
     )
    (('pov-cam-on)
     (let ((v1-14 (-> (the-as collide-shape-prim-group (-> self root root-prim)) child 3)))
       (set! (-> v1-14 prim-core collide-as) (collide-spec obstacle pusher))
       (set! (-> v1-14 prim-core collide-with) (collide-spec jak player-list))
       )
     (set! v0-0 (logior (-> self flags) (fac-robotank-turret-flag frt7)))
     (set! (-> self flags) (the-as fac-robotank-turret-flag v0-0))
     v0-0
     )
    (('pov-cam-off)
     (let ((v1-19 (-> (the-as collide-shape-prim-group (-> self root root-prim)) child 3)))
       (set! (-> v1-19 prim-core collide-as) (collide-spec))
       (set! (-> v1-19 prim-core collide-with) (collide-spec))
       )
     0
     (logclear! (-> self flags) (fac-robotank-turret-flag frt7))
     (remove-setting! 'fov)
     )
    (('get-rotate-quat)
     (-> self rotate-quat)
     )
    (('get-gun-elevation-cam)
     (-> self gun-elev-cam)
     )
    (('update)
     (-> arg3 param 1)
     (new 'stack-no-clear 'vector)
     (let ((s5-0 (new 'stack-no-clear 'quaternion)))
       (let ((s4-0 (the-as cspace (-> arg3 param 2))))
         (vector<-cspace+vector! (-> self root trans) s4-0 (-> self offset))
         (matrix->quaternion s5-0 (-> s4-0 bone transform))
         )
       (quaternion-copy! (-> self tank-quat) s5-0)
       )
     (quaternion-copy! (-> self tank-quat-vibe-only) (the-as quaternion (-> arg3 param 3)))
     )
    (('die)
     (go-virtual die)
     )
    )
  )

(defmethod fac-robotank-turret-method-34 ((this fac-robotank-turret) (arg0 vector) (arg1 float))
  (let ((s4-1 (vector-! (new 'stack-no-clear 'vector) arg0 (-> this root trans)))
        (s3-0 (vector-z-quaternion! (new 'stack-no-clear 'vector) (-> this root quat)))
        (s5-0 (new 'stack-no-clear 'vector))
        )
    (vector-copy! s5-0 s4-1)
    (set! (-> s3-0 y) 0.0)
    (vector-normalize! s3-0 1.0)
    (set! (-> s5-0 y) 0.0)
    (vector-normalize! s5-0 1.0)
    (>= (vector-dot s3-0 s5-0) (cos arg1))
    )
  )

(defstate ready (fac-robotank-turret)
  :virtual #t
  :event robotank-turret-handler
  :enter (behavior ()
    (logior! (-> self flags) (fac-robotank-turret-flag frt0))
    (set-time! (-> self gun-timer))
    )
  :trans (behavior ()
    (if (logtest? (-> self flags) (fac-robotank-turret-flag frt4))
        (set-time! (-> self gun-timer))
        )
    (if (and (the-as target (as-type *target* process-focusable))
             (or (not (logtest? (-> self flags) (fac-robotank-turret-flag frt9))) (should-check-los? (-> self los) 0))
             (time-elapsed? (-> self gun-timer) (seconds 1))
             )
        (go-virtual fire)
        )
    )
  :code (behavior ()
    (until #f
      (ja-no-eval :group! fac-robotank-idle-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!))
        )
      )
    #f
    )
  :post turret-post
  )

(defstate fire (fac-robotank-turret)
  :virtual #t
  :event robotank-turret-handler
  :enter (behavior ()
    (logior! (-> self flags) (fac-robotank-turret-flag frt8))
    (let ((a0-1 (the-as target (as-type *target* process-focusable))))
      (when a0-1
        (set! (-> self aim-pos 0 quad) (-> (get-trans a0-1 0) quad))
        (vector-copy! (-> self aim-pos 1) (-> self aim-pos 0))
        (vector-copy! (-> self aim-pos 2) (-> self aim-pos 0))
        )
      )
    )
  :trans (behavior ()
    (when (or (not (the-as target (as-type *target* process-focusable)))
              (and (logtest? (-> self flags) (fac-robotank-turret-flag frt9))
                   (not (logtest? (-> self flags) (fac-robotank-turret-flag frt3)))
                   (los-control-method-11 (-> self los) 0)
                   )
              (logtest? (-> self flags) (fac-robotank-turret-flag frt4))
              )
      (logclear! (-> self flags) (fac-robotank-turret-flag frt8))
      (go-virtual ready)
      )
    )
  :code (behavior ()
    (local-vars (v1-2 symbol))
    (until #f
      (until v1-2
        (suspend)
        (set! v1-2 (and (fac-robotank-turret-method-34 self (-> self aim-pos 2) 2730.6667)
                        (logtest? (-> self draw status) (draw-control-status on-screen))
                        )
              )
        )
      (logior! (-> self flags) (fac-robotank-turret-flag frt3))
      (vector-copy! (-> self firing-sight-pos) (-> self sight-pos))
      (suspend-for (seconds 0.5)
        )
      (let ((gp-2 (max 2 (min 3 (rand-vu-int-range 0 3)))))
        0
        (dotimes (s5-2 gp-2)
          (let ((s4-1 (max 2 (min 4 (rand-vu-int-range 1 8)))))
            (dotimes (s3-2 s4-1)
              (ja-no-eval :group! fac-robotank-fire-start-ja :num! (seek!) :frame-num 0.0)
              (until (ja-done? 0)
                (suspend)
                (ja :num! (seek!))
                )
              (fac-robotank-turret-method-33 self)
              (ja-no-eval :group! fac-robotank-fire-end-ja :num! (seek!) :frame-num 0.0)
              (until (ja-done? 0)
                (suspend)
                (ja :num! (seek!))
                )
              (set! (-> self gun-index) (- 1 (-> self gun-index)))
              (suspend)
              (if (< (vector-length (vector-! (new 'stack-no-clear 'vector) (-> self firing-sight-pos) (-> self root trans)))
                     73728.0
                     )
                  (goto cfg-22)
                  )
              )
            )
          (let ((f30-0 (rand-vu-float-range 0.05 0.43)))
            (suspend-for (the int (* 300.0 f30-0))
              )
            )
          )
        )
      (label cfg-22)
      (logclear! (-> self flags) (fac-robotank-turret-flag frt3))
      (until (fac-robotank-turret-method-34 self (-> self aim-pos 2) 2730.6667)
        (suspend)
        )
      (let ((f30-1 (rand-vu-float-range
                     (if (< 2730.6667 (-> self rotate-rate))
                         1.2
                         0.32
                         )
                     2.11
                     )
                   )
            )
        (suspend-for (the int (* 300.0 f30-1))
          )
        )
      )
    #f
    )
  :post turret-post
  )

(defstate die (fac-robotank-turret)
  :virtual #t
  :code (behavior ()
    (let ((v1-1 (-> self root root-prim)))
      (set! (-> v1-1 prim-core collide-as) (collide-spec))
      (set! (-> v1-1 prim-core collide-with) (collide-spec))
      )
    0
    (logior! (-> self draw status) (draw-control-status no-draw))
    (suspend-for (seconds 1)
      )
    (while (-> self child)
      (suspend)
      )
    )
  )

(defmethod deactivate ((this fac-robotank-turret))
  "Make a process dead, clean it up, remove it from the active pool, and return to dead pool."
  (logclear! (-> this flags) (fac-robotank-turret-flag frt6))
  (sound-stop (-> this turn-sound-id))
  ((method-of-type process-focusable deactivate) this)
  (none)
  )

;; WARN: Return type mismatch process-focusable vs fac-robotank-turret.
(defmethod relocate ((this fac-robotank-turret) (offset int))
  (if (nonzero? (-> this gun-elev-jmod))
      (&+! (-> this gun-elev-jmod) offset)
      )
  (the-as fac-robotank-turret ((method-of-type process-focusable relocate) this offset))
  )

(defbehavior fac-robotank-turret-init-by-other fac-robotank-turret ((arg0 vector) (arg1 quaternion) (arg2 vector) (arg3 float))
  (let ((s2-0 (new 'process 'collide-shape-moving self (collide-list-enum usually-hit-by-player))))
    (set! (-> s2-0 dynam) (copy *standard-dynamics* 'process))
    (set! (-> s2-0 reaction) cshape-reaction-default)
    (set! (-> s2-0 no-reaction)
          (the-as (function collide-shape-moving collide-query vector vector object) nothing)
          )
    (let ((s1-0 (new 'process 'collide-shape-prim-group s2-0 (the-as uint 4) 0)))
      (set! (-> s2-0 total-prims) (the-as uint 5))
      (set! (-> s1-0 prim-core collide-as) (collide-spec obstacle camera-blocker pusher))
      (set! (-> s1-0 prim-core collide-with) (collide-spec jak bot player-list))
      (set! (-> s1-0 prim-core action) (collide-action solid))
      (set-vector! (-> s1-0 local-sphere) 0.0 0.0 0.0 36864.0)
      (set! (-> s2-0 root-prim) s1-0)
      )
    (pusher-init s2-0)
    (let ((v1-14 (new 'process 'collide-shape-prim-mesh s2-0 (the-as uint 2) (the-as uint 0))))
      (set! (-> v1-14 prim-core collide-as) (collide-spec obstacle pusher))
      (set! (-> v1-14 prim-core collide-with) (collide-spec jak bot player-list))
      (set! (-> v1-14 prim-core action) (collide-action solid))
      (set! (-> v1-14 transform-index) 3)
      (set-vector! (-> v1-14 local-sphere) 0.0 0.0 0.0 16384.0)
      )
    (let ((v1-16 (new 'process 'collide-shape-prim-mesh s2-0 (the-as uint 1) (the-as uint 0))))
      (set! (-> v1-16 prim-core collide-as) (collide-spec obstacle pusher))
      (set! (-> v1-16 prim-core collide-with) (collide-spec jak bot player-list))
      (set! (-> v1-16 prim-core action) (collide-action solid))
      (set! (-> v1-16 transform-index) 8)
      (set-vector! (-> v1-16 local-sphere) 0.0 0.0 4096.0 6553.6)
      )
    (let ((v1-18 (new 'process 'collide-shape-prim-mesh s2-0 (the-as uint 0) (the-as uint 0))))
      (set! (-> v1-18 prim-core collide-as) (collide-spec obstacle pusher))
      (set! (-> v1-18 prim-core collide-with) (collide-spec jak bot player-list))
      (set! (-> v1-18 prim-core action) (collide-action solid))
      (set! (-> v1-18 transform-index) 5)
      (set-vector! (-> v1-18 local-sphere) 0.0 0.0 4096.0 6553.6)
      )
    (let ((v1-20 (new 'process 'collide-shape-prim-mesh s2-0 (the-as uint 3) (the-as uint 0))))
      (set! (-> v1-20 prim-core action) (collide-action solid))
      (set! (-> v1-20 transform-index) 3)
      (set-vector! (-> v1-20 local-sphere) 0.0 20480.0 4096.0 31129.6)
      )
    (set! (-> s2-0 nav-radius) (* 0.75 (-> s2-0 root-prim local-sphere w)))
    (let ((v1-23 (-> s2-0 root-prim)))
      (set! (-> s2-0 backup-collide-as) (-> v1-23 prim-core collide-as))
      (set! (-> s2-0 backup-collide-with) (-> v1-23 prim-core collide-with))
      )
    (set! (-> self root) s2-0)
    )
  (vector-copy! (-> self root trans) arg0)
  (quaternion-copy! (-> self root quat) arg1)
  (vector-copy! (-> self offset) arg2)
  (initialize-skeleton
    self
    (the-as skeleton-group (art-group-get-by-name *level* "skel-fac-robotank-turret" (the-as (pointer level) #f)))
    (the-as pair 0)
    )
  (logclear! (-> self mask) (process-mask actor-pause))
  (set! (-> self draw light-index) (the-as uint 10))
  (init-los! (-> self los) self (seconds 0.1) 327680.0 (collide-spec backgnd))
  (set! (-> self gun-elev-jmod) (new 'process 'joint-mod (joint-mod-mode joint-set*) self 4))
  (set! (-> self gun-elev) 0.0)
  (set! (-> self gun-elev-cam) 0.0)
  (set! (-> self gun-spread) 728.1778)
  (quaternion-axis-angle! (-> self gun-elev-jmod quat) 1.0 0.0 0.0 (-> self gun-elev))
  (quaternion-zero! (-> self tank-quat))
  (quaternion-copy! (-> self rotate-quat) arg1)
  (set! (-> self rotate-rate) 0.0)
  (set! (-> self rotate-mult) arg3)
  (set! (-> self aim-pos 0 quad) (-> self root trans quad))
  (vector-copy! (-> self aim-pos 1) (-> self root trans))
  (vector-copy! (-> self aim-pos 2) (-> self root trans))
  (set-time! (-> self gun-timer))
  (set! (-> self flags) (fac-robotank-turret-flag))
  (set! (-> self fov-mult) 1.0)
  (set! (-> self shot-range) 204800.0)
  (set! (-> self gun-joint-l 0) 10)
  (set! (-> self gun-joint-r 0) 7)
  (set! (-> self gun-joint-l 1) 9)
  (set! (-> self gun-joint-r 1) 6)
  (set! (-> self gun-index) 0)
  (let ((v1-51 (new 'stack-no-clear 'vector)))
    (vector-copy! v1-51 (-> self root trans))
    (+! (-> v1-51 z) 40960.0)
    (+! (-> v1-51 y) 32768.0)
    )
  (ja-no-eval :group! fac-robotank-idle-ja :num! zero)
  (transform-post)
  (set! (-> self turn-sound-id) (new-sound-id))
  (go-virtual ready)
  )
