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

;; name: flying-turret.gc
;; name in dgo: flying-turret
;; dgos: CTYPESC

;; DECOMP BEGINS

(defskelgroup skel-flying-turret kg-flying-turret kg-flying-turret-lod0-jg kg-flying-turret-idle-ja
              ((kg-flying-turret-lod0-mg (meters 999999)))
              :bounds (static-spherem 0 0 0 4)
              )

(defpart 4709
  :init-specs ((:texture (gun-yellow-muzzleflash level-default-sprite))
    (:birth-func 'birth-func-set-quat)
    (:num 1.0)
    (:scale-x (meters 0.4))
    (:scale-y (meters 3))
    (:r 128.0 128.0)
    (:g 32.0 96.0)
    (:b :copy g)
    (:a 128.0 64.0)
    (:timer (seconds 0.017))
    (:flags (sp-cpuinfo-flag-2 sp-cpuinfo-flag-3))
    )
  )

(define *flying-turret-nav-enemy-info*
  (new 'static 'nav-enemy-info
    :use-die-falling #f
    :use-victory #f
    :use-jump-blocked #f
    :debug-draw-neck #f
    :jump-debug-draw #f
    :move-to-ground #f
    :hover-if-no-ground #f
    :idle-anim-script (new 'static 'inline-array idle-control-frame 3
      (new 'static 'idle-control-frame :command (idle-control-cmd push) :param0 30)
      (new 'static 'idle-control-frame
        :command (idle-control-cmd play)
        :anim #x2
        :param0 100
        :param1 100
        :param2 '((new 'static 'bfloat :data 1.0) (new 'static 'bfloat :data 1.0))
        )
      (new 'static 'idle-control-frame)
      )
    :idle-anim 2
    :notice-anim 2
    :hostile-anim 2
    :hit-anim 2
    :knocked-anim 2
    :knocked-land-anim 2
    :die-anim 2
    :die-falling-anim -1
    :victory-anim -1
    :jump-wind-up-anim -1
    :jump-in-air-anim -1
    :jump-land-anim -1
    :neck-joint -1
    :notice-distance (meters 30)
    :notice-distance-delta (meters 10)
    :default-hit-points 1.0
    :gnd-collide-with (collide-spec backgnd obstacle hit-by-others-list)
    :overlaps-others-collide-with-filter (collide-spec jak bot player-list)
    :movement-gravity (meters -100)
    :friction 0.8
    :attack-shove-back (meters 3.5)
    :attack-shove-up (meters 2)
    :attack-mode 'generic
    :attack-damage 2
    :recover-gnd-collide-with (collide-spec backgnd crate obstacle hit-by-others-list pusher)
    :knocked-can-land-timeout (seconds 0.1)
    :knocked-recover-timeout (seconds 2)
    :ragdoll-blend-out-time (seconds 0.25)
    :ragdoll-rotate-velocity-mult 1.0
    :jump-height-min (meters 3)
    :jump-height-factor 0.5
    :knocked-seek-ry-clamp 2730.6667
    :knocked-soft-vxz-lo (meters 17.6)
    :knocked-soft-vxz-hi (meters 26.4)
    :knocked-soft-vy-lo (meters 20)
    :knocked-soft-vy-hi (meters 30)
    :knocked-medium-vxz-lo (meters 36)
    :knocked-medium-vxz-hi (meters 48)
    :knocked-medium-vy-lo (meters 33)
    :knocked-medium-vy-hi (meters 37)
    :knocked-hard-vxz-lo (meters 19.2)
    :knocked-hard-vxz-hi (meters 28.8)
    :knocked-hard-vy-lo (meters 44.8)
    :knocked-hard-vy-hi (meters 51.2)
    :knocked-huge-vxz-lo (meters 40.2)
    :knocked-huge-vxz-hi (meters 60.8)
    :knocked-huge-vy-lo (meters 44.8)
    :knocked-huge-vy-hi (meters 53.2)
    :knocked-yellow-vxz-lo (meters 10)
    :knocked-yellow-vxz-hi (meters 12)
    :knocked-yellow-vy-lo (meters 14)
    :knocked-yellow-vy-hi (meters 20)
    :knocked-red-vxz-lo (meters 6)
    :knocked-red-vxz-hi (meters 48)
    :knocked-red-vy-lo (meters 23)
    :knocked-red-vy-hi (meters 37)
    :knocked-blue-vxz-lo (meters 10)
    :knocked-blue-vxz-hi (meters 12)
    :knocked-blue-vy-lo (meters 6)
    :knocked-blue-vy-hi (meters 20)
    :ragdoll-info #f
    :shadow-size (meters 1)
    :shadow-max-y (meters 1)
    :shadow-min-y (meters -1)
    :shadow-locus-dist (meters 150)
    :gem-joint -1
    :gem-offset (new 'static 'sphere :r 163840.0)
    :knocked-off #t
    :callback-info #f
    :use-momentum #t
    :use-frustration #t
    :use-stop-chase #f
    :use-circling #f
    :use-pacing #f
    :walk-anim 2
    :turn-anim -1
    :run-anim 2
    :taunt-anim -1
    :run-travel-speed (meters 25)
    :run-acceleration (meters 1)
    :run-turning-acceleration (meters 2)
    :walk-travel-speed (meters 25)
    :walk-acceleration (meters 1)
    :walk-turning-acceleration (meters 1)
    :maximum-rotation-rate (degrees 720)
    :notice-nav-radius (meters 1)
    :frustration-distance (meters 8)
    :frustration-time (seconds 4)
    :blocked-time (seconds 0.3)
    :circle-dist-lo 20480.0
    :circle-dist-hi 61440.0
    :nav-mesh #f
    )
  )

(set! (-> *flying-turret-nav-enemy-info* fact-defaults) *fact-info-enemy-defaults*)

(define *flying-turret-debris-params*
  (new 'static 'debris-static-params
    :joints (new 'static 'boxed-array :type debris-static-joint-params
      (new 'static 'debris-static-joint-params :parent-joint-index 3 :group "skel-kg-debris-a")
      (new 'static 'debris-static-joint-params :parent-joint-index 4 :group "skel-kg-debris-b")
      (new 'static 'debris-static-joint-params :parent-joint-index 5 :group "skel-kg-debris-c")
      (new 'static 'debris-static-joint-params :parent-joint-index 6 :group "skel-kg-debris-d")
      (new 'static 'debris-static-joint-params :parent-joint-index 7 :group "skel-kg-debris-a")
      )
    )
  )

(deftype ft-gun-info (structure)
  ((gun-position  float)
   (fire?         symbol)
   )
  )


(deftype flying-turret (kg-squad-member)
  ((thrust-dir                 vector       :inline)
   (speed                      float)
   (speed-target               float)
   (ground-height              float)
   (last-heading-quat          quaternion   :inline)
   (last-roll-quat             quaternion   :inline)
   (thrust-mode                uint8)
   (pursuit-start-time         time-frame)
   (chase-mode                 uint8)
   (last-check-chase-pos-time  time-frame)
   (circle-angle               float)
   (last-fire-time             time-frame)
   (num-shots-fired            int8)
   (ground-point               vector       :inline)
   (guns                       ft-gun-info  2 :inline)
   (turret-aim-blend           float)
   (hit-player?                symbol)
   (desired-height-offset      float)
   (float-height               float)
   (bob-velocity               float)
   (bouncing?                  symbol)
   (bounce-start-time          time-frame)
   (changed-targets?           symbol)
   (thruster-intensity         float)
   (up-bobbing?                symbol)
   (bob-scale-factor           float)
   (bob-scale-target           float)
   (bob-t                      float)
   (thruster-intensity-scalar  float)
   (engine-sound               sound-id)
   (tilt-sound                 sound-id)
   (roll-sound-amount          float)
   )
  (:state-methods
    flying-turret-base-state
    fire
    exit-transport
    )
  (:methods
    (flying-turret-method-225 (_type_) float)
    (flying-turret-method-226 (_type_) none)
    (flying-turret-method-227 (_type_) quaternion)
    (fire-shot-from-joint-idx (_type_ int) (pointer process))
    (flying-turret-method-229 (_type_) none)
    (flying-turret-method-230 (_type_ uint) uint)
    )
  )


(defmethod init-enemy-collision! ((this flying-turret))
  "Typical place to construct collision shapes"
  (let ((s5-0 (new 'process 'collide-shape-moving this (collide-list-enum usually-hit-by-player))))
    (set! (-> s5-0 dynam) (copy *standard-dynamics* 'process))
    (set! (-> s5-0 reaction) cshape-reaction-default)
    (set! (-> s5-0 no-reaction)
          (the-as (function collide-shape-moving collide-query vector vector object) nothing)
          )
    (set! (-> s5-0 penetrated-by) (penetrate
                                    generic-attack
                                    lunge
                                    flop
                                    punch
                                    spin
                                    roll
                                    uppercut
                                    bonk
                                    tube
                                    flut-attack
                                    board
                                    mech-punch
                                    dark-punch
                                    dark-smack
                                    flut
                                    )
          )
    (let ((v1-7 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 0))))
      (set! (-> v1-7 prim-core collide-as) (collide-spec enemy))
      (set! (-> v1-7 prim-core collide-with)
            (collide-spec backgnd jak bot enemy obstacle hit-by-others-list player-list)
            )
      (set! (-> v1-7 prim-core action) (collide-action solid semi-solid no-standon))
      (set-vector! (-> v1-7 local-sphere) 0.0 0.0 0.0 8192.0)
      (set! (-> s5-0 total-prims) (the-as uint 1))
      (set! (-> s5-0 root-prim) v1-7)
      )
    (set! (-> s5-0 nav-radius) 40.96)
    (let ((v1-9 (-> s5-0 root-prim)))
      (set! (-> s5-0 backup-collide-as) (-> v1-9 prim-core collide-as))
      (set! (-> s5-0 backup-collide-with) (-> v1-9 prim-core collide-with))
      )
    (set! (-> this root) s5-0)
    )
  0
  (none)
  )

;; WARN: Return type mismatch vector vs process.
(defmethod update-focus ((this flying-turret))
  "Potentially update the focus, if there is something better to focus on."
  (the-as process (when (handle->process (-> this focus handle))
                    (let ((a0-9 (as-type (handle->process (-> this focus handle)) process-focusable))
                          (s5-0 (-> this focus-pos))
                          )
                      (vector-copy! s5-0 (get-trans a0-9 3))
                      s5-0
                      )
                    )
          )
  )

(defmethod flying-turret-method-226 ((this flying-turret))
  (when (not (handle->process (-> this current-enemy)))
    (set! (-> this focus handle) (the-as handle #f))
    (set! (-> this current-enemy) (the-as handle #f))
    )
  (let ((a0-6 (get-current-enemy this)))
    (cond
      (a0-6
        (let ((v1-8 (process->handle a0-6)))
          (when (!= (-> this current-enemy) v1-8)
            (set-time! (-> this pursuit-start-time))
            (logior! (-> this flags) (citizen-flag persistent in-pursuit))
            (set! (-> this changed-targets?) #t)
            )
          (set! (-> this current-enemy) (the-as handle v1-8))
          )
        )
      (else
        (set! (-> this current-enemy) (the-as handle #f))
        )
      )
    )
  (when (logtest? (-> this attacker-info flags) (city-attacker-info-flag cai2))
    (set! (-> this attacker-info next-update-target-time) (+ (current-time) (seconds 3)))
    (logclear! (-> this attacker-info flags) (city-attacker-info-flag cai2))
    )
  (if (time-elapsed? (-> this pursuit-start-time) (seconds 5))
      (logclear! (-> this flags) (citizen-flag persistent in-pursuit))
      )
  (let ((a0-27 (as-type (handle->process (-> this current-enemy)) process-focusable)))
    (cond
      ((and a0-27
            (not (logtest? (-> (the-as process-focusable a0-27) focus-status) (focus-status disable dead inactive)))
            )
       (set-focus!
         this
         (the-as process-focusable (as-type (handle->process (-> this current-enemy)) process-focusable))
         (the-as enemy-aware #f)
         )
       (update-focus this)
       (let ((f0-0 (vector-vector-xz-distance-squared (-> this root trans) (-> this focus-pos)))
             (f1-0 204800.0)
             )
         (when (< f0-0 (* f1-0 f1-0))
           (set-time! (-> this pursuit-start-time))
           (logior! (-> this flags) (citizen-flag persistent in-pursuit))
           )
         )
       )
      (else
        (set! (-> this current-enemy) (the-as handle #f))
        (set! (-> this focus handle) (the-as handle #f))
        (logclear! (-> this flags) (citizen-flag persistent in-pursuit hostile))
        (when (not (and (-> this next-state) (= (-> this next-state name) 'active)))
          (citizen-method-208 this (vector-z-quaternion! (new 'stack-no-clear 'vector) (-> this root quat)))
          (go (method-of-object this active))
          )
        )
      )
    )
  0
  (none)
  )

(defmethod kg-squad-member-method-219 ((this flying-turret) (arg0 process-focusable))
  (let* ((s4-0 (get-trans arg0 0))
         (f0-0 (vector-vector-xz-distance-squared (-> this root trans) s4-0))
         (f1-0 245760.0)
         )
    (or (and (< f0-0 (* f1-0 f1-0))
             (< (fabs (- (-> s4-0 y) (-> this root trans y))) 61440.0)
             (< (-> s4-0 y) (-> this root trans y))
             )
        (< 0.0 (get-hatred-val-for-target this (process->handle arg0)))
        )
    )
  )

(defmethod flying-turret-method-227 ((this flying-turret))
  (set! (-> this roll-sound-amount) 0.0)
  (if (zero? (-> this thrust-mode))
      (vector-float*! (-> this root transv) (-> this root transv) (- 1.0 (* 0.1 (seconds-per-frame))))
      (vector-float*! (-> this root transv) (-> this root transv) (- 1.0 (seconds-per-frame)))
      )
  (let ((v1-8 (vector-float*! (new 'stack-no-clear 'vector) (-> this thrust-dir) (-> this speed-target)))
        (a0-6 (new 'stack-no-clear 'vector))
        )
    (vector-copy! a0-6 (-> this root transv))
    (let ((s5-1 (vector-! (new 'stack-no-clear 'vector) v1-8 a0-6))
          (f30-0 0.0)
          )
      (cond
        ((zero? (-> this thrust-mode))
         1.0
         (vector-length (-> this root transv))
         (set! f30-0 (vector-length s5-1))
         (let* ((f1-3 (/ f30-0 (-> this enemy-info run-travel-speed)))
                (f0-10 (fmax 0.0 (fmin 1.0 f1-3)))
                (f0-11 (* f0-10 f0-10))
                (f0-12 (* f0-11 f0-11))
                )
           (when (!= (-> this chase-mode) 3)
             (let ((f1-5 (vector-length (-> this root transv))))
               (set! f0-12 (* f0-12 (fmax 0.2 (fmin 1.0 (/ f1-5 (-> this enemy-info run-travel-speed))))))
               )
             )
           (let ((f28-0 (lerp 2.0 10.0 f0-12)))
             (let* ((s4-0 (new 'stack-no-clear 'vector))
                    (s1-0 (closest-point-on-mesh (-> this nav) s4-0 (-> this ground-point) (the-as nav-poly #f)))
                    (s2-0 (new 'stack 'clamp-travel-vector-to-mesh-return-info))
                    (s3-0 (new 'stack-no-clear 'vector))
                    )
               (vector-copy! s3-0 (-> this root transv))
               (when s1-0
                 (set! (-> s3-0 y) 0.0)
                 (clamp-vector-to-mesh-no-gaps (-> this nav) s4-0 s1-0 s3-0 s2-0)
                 (if (and (-> s2-0 found-boundary) (< (vector-length s3-0) 20480.0))
                     (set! f28-0 (* 4.0 f28-0))
                     )
                 )
               )
             (vector+float*! (-> this root transv) (-> this root transv) s5-1 (* f28-0 (seconds-per-frame)))
             (let* ((f0-19 (fmax 61440.0 (* (vector-length s5-1) f28-0)))
                    (f28-1 (/ f0-19 (meters 30)))
                    (f26-0 0.8)
                    (f24-0 0.40000004)
                    (v1-53 (/ (the-as int (rand-uint31-gen *random-generator*)) 256))
                    (v1-54 (the-as number (logior #x3f800000 v1-53)))
                    (f0-25 (* f28-1 (+ f26-0 (* f24-0 (+ -1.0 (the-as float v1-54))))))
                    )
               (seek! (-> this thruster-intensity) f0-25 (* 2.0 (seconds-per-frame)))
               )
             )
           )
         )
        (else
          (let* ((f0-30 (fmax 61440.0 (* 3.0 (vector-length (-> this root transv)))))
                 (f28-2 (/ f0-30 (meters 30)))
                 (f26-1 0.8)
                 (f24-1 0.40000004)
                 (v1-68 (/ (the-as int (rand-uint31-gen *random-generator*)) 256))
                 (v1-69 (the-as number (logior #x3f800000 v1-68)))
                 (f0-36 (* f28-2 (+ f26-1 (* f24-1 (+ -1.0 (the-as float v1-69))))))
                 )
            (seek! (-> this thruster-intensity) f0-36 (* 2.0 (seconds-per-frame)))
            )
          )
        )
      (let ((s4-2 (vector-float*! (new 'stack-no-clear 'vector) (-> this root transv) (seconds-per-frame))))
        (let* ((s1-1 (new 'stack-no-clear 'vector))
               (s0-0 (closest-point-on-mesh (-> this nav) s1-1 (-> this ground-point) (the-as nav-poly #f)))
               (s2-1 (new 'stack 'clamp-travel-vector-to-mesh-return-info))
               (s3-1 (new 'stack-no-clear 'vector))
               )
          (vector-copy! s3-1 s4-2)
          (when s0-0
            (set! (-> s3-1 y) 0.0)
            (clamp-vector-to-mesh-no-gaps (-> this nav) s1-1 s0-0 s3-1 s2-1)
            (when (-> s2-1 found-boundary)
              (let ((s1-3 (vector-! (new 'stack-no-clear 'vector) s4-2 s3-1)))
                0.0
                (let ((f0-43 (vector-normalize-ret-len! s1-3 1.0)))
                  (let ((f1-23 (vector-dot s1-3 (-> s2-1 boundary-normal))))
                    (vector-float*! (-> s2-1 boundary-normal) (-> s2-1 boundary-normal) f1-23)
                    )
                  (vector-! s1-3 s1-3 (-> s2-1 boundary-normal))
                  (vector-normalize! s1-3 f0-43)
                  )
                (vector+! s4-2 s3-1 s1-3)
                )
              )
            )
          )
        (vector+! (-> this root trans) (-> this root trans) s4-2)
        )
      (let ((s2-2 (new 'stack-no-clear 'vector))
            (s4-3 (quaternion-identity! (new 'stack-no-clear 'quaternion)))
            )
        (vector-copy! s2-2 (-> this thrust-dir))
        (set! (-> s2-2 y) 0.0)
        (vector-normalize! s2-2 1.0)
        (let ((s3-2 (new 'stack-no-clear 'quaternion))
              (f28-3 0.75)
              )
          (quaternion-set! s3-2 0.0 (-> s2-2 x) 0.0 (+ 1.0 (-> s2-2 z)))
          (quaternion-normalize! s3-2)
          (if (= (-> this thrust-mode) 2)
              (set! f28-3 1.5)
              )
          (quaternion-slerp! (-> this last-heading-quat) (-> this last-heading-quat) s3-2 (* f28-3 (seconds-per-frame)))
          )
        (when (zero? (-> this thrust-mode))
          (let ((s3-3 (new 'stack-no-clear 'vector)))
            (vector-copy! s3-3 s5-1)
            (let ((s5-2 (new 'stack-no-clear 'vector)))
              (let ((s2-3 *up-vector*))
                (set! (-> s3-3 y) 0.0)
                (vector-normalize! s3-3 1.0)
                (vector-cross! s5-2 s3-3 s2-3)
                )
              (vector-normalize! s5-2 1.0)
              0.0
              0.0
              (let* ((f1-25 (/ f30-0 (-> this enemy-info run-travel-speed)))
                     (f1-28 (- 1.0 (* (- 1.0 f1-25) (- 1.0 f1-25))))
                     (f0-56 (- 1.0 (* (- 1.0 f1-28) (- 1.0 f1-28))))
                     (f0-57 (lerp 0.0 11832.889 f0-56))
                     )
                (set! (-> this roll-sound-amount) f0-57)
                (let ((f0-58 (* -1.0 f0-57)))
                  (quaternion-vector-angle! s4-3 s5-2 f0-58)
                  )
                )
              )
            )
          )
        (quaternion-slerp! (-> this last-roll-quat) (-> this last-roll-quat) s4-3 (* 2.0 (seconds-per-frame)))
        )
      )
    )
  (quaternion*! (-> this root quat) (-> this last-roll-quat) (-> this last-heading-quat))
  (quaternion-normalize! (-> this root quat))
  )

(defmethod flying-turret-method-229 ((this flying-turret))
  (let ((s4-0 (quaternion->matrix (new 'stack-no-clear 'matrix) (-> this root quat)))
        (gp-0 (new 'stack-no-clear 'vector))
        )
    (vector-copy! gp-0 (-> this root trans))
    (let ((s5-0 (new 'stack-no-clear 'vector)))
      (vector+float*! gp-0 gp-0 (-> s4-0 fvec) -3276.8)
      (vector+float*! gp-0 gp-0 (-> s4-0 uvec) -409.6)
      (vector+float*! gp-0 gp-0 (-> s4-0 rvec) -614.4)
      (vector-float*! s5-0 (-> s4-0 uvec) -1.0)
      0.0
      0.0
      (let ((f0-6 (-> this thruster-intensity)))
        (if (< f0-6 1.0)
            (set! f0-6 (* f0-6 f0-6))
            )
        (let ((f0-8 (* (lerp 3072.0 8601.6 f0-6) (-> this thruster-intensity-scalar))))
          (set! (-> *part-id-table* 4709 init-specs 4 initial-valuef) f0-8)
          (set! (-> *part-id-table* 4709 init-specs 3 initial-valuef) (/ f0-8 2))
          )
        )
      (draw-beam (-> *part-id-table* 4709) gp-0 s5-0 #f)
      (vector+float*! gp-0 gp-0 (-> s4-0 rvec) 1228.8)
      (draw-beam (-> *part-id-table* 4709) gp-0 s5-0 #f)
      )
    )
  (none)
  )

(defmethod enemy-common-post ((this flying-turret))
  "Common implementation of post. Runs ja-post."
  (with-pp
    (logclear! (-> this nav flags) (nav-control-flag limit-rotation-rate update-heading-from-facing))
    (if (not (and (-> this next-state) (= (-> this next-state name) 'exit-transport)))
        (flying-turret-method-226 this)
        )
    (flying-turret-method-227 this)
    (let* ((f0-0 (vector-length (-> this root transv)))
           (f0-1 (/ f0-0 (meters 15)))
           )
      0.0
      0.0
      (let* ((f28-0 (fmax 0.0 (fmin 1.0 f0-1)))
             (f30-0 (lerp 0.5 1.0 f28-0))
             (f0-3 (lerp 0.0 0.25 f28-0))
             )
        (sound-play-by-name
          (static-sound-name "f-turret-engine")
          (-> this engine-sound)
          (the int (* 1024.0 f30-0))
          (the int (* 1524.0 f0-3))
          0
          (sound-group)
          #t
          )
        )
      )
    (let* ((f1-9 (* 0.00008451022 (-> this roll-sound-amount)))
           (f0-8 (* (-> this thruster-intensity) (-> this thruster-intensity-scalar)))
           (f1-11 (fmax 0.0 (fmin 1.0 f1-9)))
           (f28-1 (fmax 0.0 (fmin 1.0 f0-8)))
           (f30-1 (lerp 0.0 0.2 f1-11))
           (f0-10 (lerp 0.5 1.0 f28-1))
           )
      (sound-play-by-name
        (static-sound-name "fly-turret-jets")
        (-> this tilt-sound)
        (the int (* 1024.0 f0-10))
        (the int (* 1524.0 f30-1))
        0
        (sound-group)
        #t
        )
      )
    (if (= (-> this thrust-mode) 2)
        (seek! (-> this turret-aim-blend) 1.0 (* 2.0 (seconds-per-frame)))
        (seek! (-> this turret-aim-blend) 0.0 (* 2.0 (seconds-per-frame)))
        )
    (seek! (-> this bob-scale-factor) (-> this bob-scale-target) (* 3.0 (seconds-per-frame)))
    (let ((f0-30 (* 0.0016666667 (the float (- (current-time) (-> pp clock old-frame-counter))))))
      (cond
        ((-> this up-bobbing?)
         (+! (-> this bob-t) f0-30)
         (+! (-> this root trans y) (* 2048.0 (seconds-per-frame) (-> this bob-scale-factor)))
         (seek! (-> this thruster-intensity-scalar) (lerp 1.0 1.1 (-> this bob-scale-factor)) (seconds-per-frame))
         (when (< 1.0 (-> this bob-t))
           (let ((f0-39 1.0)
                 (f1-23 (-> this bob-t))
                 )
             (set! (-> this bob-t) (- f0-39 (- f1-23 (* (the float (the int (/ f1-23 1.0))) 1.0))))
             )
           (set! (-> this up-bobbing?) #f)
           )
         )
        (else
          (set! (-> this bob-t) (- (-> this bob-t) f0-30))
          (set! (-> this root trans y)
                (- (-> this root trans y) (* 2048.0 (seconds-per-frame) (-> this bob-scale-factor)))
                )
          (seek! (-> this thruster-intensity-scalar) (lerp 1.0 0.7 (-> this bob-scale-factor)) (seconds-per-frame))
          (when (< (-> this bob-t) 0.0)
            (set! (-> this bob-t) (fabs (-> this bob-t)))
            (set! (-> this up-bobbing?) #t)
            )
          )
        )
      )
    (flying-turret-method-225 this)
    (set-vector! (-> this ground-point) (-> this root trans x) (-> this ground-height) (-> this root trans z) 1.0)
    (let ((a1-13 (new 'stack-no-clear 'vector)))
      (vector-copy! a1-13 (-> this ground-point))
      (set-virtual-cur-pos! (-> this nav state) a1-13)
      )
    (let ((f0-56 (+ (-> this desired-height-offset) (-> this ground-height))))
      (if (< 4096.0 (fabs (- (-> this root trans y) f0-56)))
          (seek! (-> this root trans y) f0-56 (* 2867.2 (seconds-per-frame)))
          )
      )
    (set! (-> this root trans y)
          (fmax (fmin (-> this root trans y) (+ 73728.0 (-> this ground-height))) (+ 12288.0 (-> this ground-height)))
          )
    (flying-turret-method-229 this)
    (call-parent-method this)
    (none)
    )
  )

(defstate flying-turret-base-state (flying-turret)
  :virtual #t
  :code sleep-code
  )

(defstate active (flying-turret)
  :virtual #t
  :enter (behavior ()
    (set! (-> self chase-mode) (the-as uint 3))
    (flying-turret-method-230 self (the-as uint 0))
    (call-parent-state-handler enter)
    )
  :trans (behavior ()
    (when (handle->process (-> self current-enemy))
      (let ((gp-0 (handle->process (-> self focus handle))))
        (if (type? gp-0 process-focusable)
            (empty)
            )
        )
      (set! (-> self chase-mode) (the-as uint 0))
      (go-virtual hostile)
      )
    )
  :code sleep-code
  )

(defmethod nav-enemy-method-176 ((this flying-turret))
  (logclear! (-> this nav flags) (nav-control-flag limit-rotation-rate update-heading-from-facing))
  (let ((v1-2 (-> this nav)))
    (set! (-> v1-2 sphere-mask) (the-as uint 65))
    )
  0
  (let ((v1-4 (-> this nav)))
    (set! (-> v1-4 acceleration) 409600000.0)
    )
  0
  (none)
  )

(defmethod nav-enemy-method-177 ((this flying-turret))
  (logclear! (-> this nav flags) (nav-control-flag limit-rotation-rate update-heading-from-facing))
  (let ((v1-2 (-> this nav)))
    (set! (-> v1-2 sphere-mask) (the-as uint 65))
    )
  0
  (let ((v1-4 (-> this nav)))
    (set! (-> v1-4 acceleration) 409600000.0)
    )
  0
  (none)
  )

(defmethod init-enemy! ((this flying-turret))
  "Typical place for shared init code. Runs from entity or process style init."
  (initialize-skeleton
    this
    (the-as skeleton-group (art-group-get-by-name *level* "skel-flying-turret" (the-as (pointer level) #f)))
    (the-as pair 0)
    )
  (setup-enemy! this *flying-turret-nav-enemy-info*)
  (call-parent-method this)
  (set! (-> this align) (new 'process 'align-control this))
  (set! (-> this anim-shuffle) 2)
  (set! (-> this anim-walk) 2)
  (set! (-> this speed-walk) 102400.0)
  (set! (-> this dist-walk-anim) 8192.0)
  (set! (-> this dist-run-anim) 16384.0)
  (set! (-> this anim-run) 2)
  (set! (-> this speed-run) 102400.0)
  (set-vector! (-> this root scale) 2.0 2.0 2.0 1.0)
  (set! (-> this draw lod-set lod 0 dist) 409600.0)
  (set! (-> this engine-sound) (new-sound-id))
  (set! (-> this tilt-sound) (new-sound-id))
  (citizen-method-194 this)
  (none)
  )

(defmethod normalize-heading! ((this flying-turret) (arg0 nav-control))
  0
  (none)
  )

;; WARN: Return type mismatch float vs none.
(defmethod nav-enemy-method-161 ((this flying-turret) (arg0 nav-control))
  (cond
    ((and (logtest? (enemy-flag ef37) (-> this enemy-flags))
          (not (logtest? (enemy-flag ef39) (-> this enemy-flags)))
          (= (-> this thrust-mode) 0)
          )
     (let ((a2-0 (-> arg0 state))
           (v1-8 (new 'stack-no-clear 'vector))
           )
       (vector-copy! v1-8 (-> a2-0 heading))
       (let ((f30-0 (-> arg0 state speed)))
         (vector-copy! (-> this thrust-dir) v1-8)
         (let ((t9-0 vector-vector-xz-distance)
               (a0-7 (-> this root trans))
               (a2-3 (-> this nav state))
               (a1-1 (new 'stack-no-clear 'vector))
               )
           (vector-copy! a1-1 (-> a2-3 target-pos))
           (let ((f0-1 (t9-0 a0-7 a1-1)))
             (set! (-> this speed-target) f30-0)
             (if (!= (-> this chase-mode) 3)
                 (set! (-> this speed-target) (fmin f30-0 f0-1))
                 )
             )
           )
         )
       )
     )
    ((= (-> this thrust-mode) 2)
     (vector-! (-> this thrust-dir) (-> this focus-pos) (-> this root trans))
     (set! (-> this thrust-dir y) 0.0)
     (vector-normalize! (-> this thrust-dir) 1.0)
     (set! (-> this speed-target) 0.0)
     )
    (else
      (set! (-> this speed-target) 0.0)
      )
    )
  (none)
  )

;; WARN: Return type mismatch number vs float.
(defmethod flying-turret-method-225 ((this flying-turret))
  (let ((s5-0 (new 'stack-no-clear 'collide-query)))
    (if (not (above-ground? (-> this root) s5-0 (-> this root trans) (collide-spec backgnd) 8192.0 102400.0 1024.0))
        (return 0.0)
        )
    (set! (-> this ground-height) (-> s5-0 best-other-tri intersect y))
    )
  )

(defun flying-turret-gun-aim-func ((arg0 cspace) (arg1 transformq))
  (let ((s4-0 (the-as flying-turret (-> arg0 param1)))
        (s2-0 (new 'stack-no-clear 'vector))
        )
    (let ((s3-0 (new 'stack-no-clear 'vector)))
      (vector-copy! s3-0 (-> s4-0 focus-pos))
      (cspace<-parented-transformq-joint! arg0 arg1)
      (vector-! s2-0 s3-0 (-> arg0 bone transform trans))
      )
    (vector-normalize! s2-0 1.0)
    (let ((s3-1 (new 'stack-no-clear 'quaternion)))
      (let* ((f0-2 (- (asin (-> s2-0 y))))
             (f0-3 (+ -3640.889 f0-2))
             (f0-5 (fmax -4004.9778 (fmin 11286.756 f0-3)))
             )
        (quaternion-vector-angle! s3-1 *x-vector* f0-5)
        )
      (quaternion-slerp! s3-1 *unity-quaternion* s3-1 (-> s4-0 turret-aim-blend))
      (quaternion*! (-> arg1 quat) (-> arg1 quat) s3-1)
      )
    )
  (cspace<-parented-transformq-joint! arg0 arg1)
  (none)
  )

(defun flying-turret-gun-recoil-jmod-func ((arg0 cspace) (arg1 transformq))
  (-> arg0 param1)
  (cspace<-parented-transformq-joint! arg0 arg1)
  (none)
  )

(deftype flying-turret-shot (guard-shot)
  ()
  )


(defmethod play-impact-sound ((this flying-turret-shot) (arg0 projectile-options))
  (let ((v1-0 arg0))
    (cond
      ((zero? v1-0)
       (sound-play "fly-turret-shot")
       )
      ((= v1-0 (projectile-options po0))
       (sound-play "guard-shot-hit")
       )
      )
    )
  0
  (none)
  )

(defun spawn-turret-projectile ((arg0 flying-turret) (arg1 vector) (arg2 vector) (arg3 float) (arg4 vector))
  (let ((gp-0 (new 'stack-no-clear 'projectile-init-by-other-params)))
    (let ((v1-1 (vector-! (new 'stack-no-clear 'vector) arg2 arg1)))
      (set! (-> gp-0 ent) (-> arg0 entity))
      (set! (-> gp-0 charge) 1.0)
      (set! (-> gp-0 options) (projectile-options))
      (logclear! (-> gp-0 options) (projectile-options po14 po15 po16))
      (set! (-> gp-0 notify-handle) (process->handle arg0))
      (set! (-> gp-0 owner-handle) (the-as handle #f))
      (set! (-> gp-0 target-handle) (the-as handle #f))
      (set! (-> gp-0 target-pos quad) (the-as uint128 0))
      (set! (-> gp-0 ignore-handle) (process->handle arg0))
      (let* ((a0-13 *game-info*)
             (a2-12 (+ (-> a0-13 attack-id) 1))
             )
        (set! (-> a0-13 attack-id) a2-12)
        (set! (-> gp-0 attack-id) a2-12)
        )
      (set! (-> gp-0 timeout) (seconds 4))
      (set! (-> gp-0 damage) 1.0)
      (logior! (-> gp-0 options) (projectile-options po14))
      (set! (-> gp-0 vehicle-damage-factor) 2.0)
      (logior! (-> gp-0 options) (projectile-options po15))
      (set! (-> gp-0 vehicle-impulse-factor) 2.0)
      (logior! (-> gp-0 options) (projectile-options po16))
      (if arg4
          (vector-copy! (-> gp-0 pos) arg4)
          (vector-copy! (-> gp-0 pos) arg1)
          )
      (vector-normalize-copy! (-> gp-0 vel) v1-1 arg3)
      )
    (spawn-projectile flying-turret-shot gp-0 arg0 *default-dead-pool*)
    )
  )

(defmethod fire-shot-from-joint-idx ((this flying-turret) (arg0 int))
  (local-vars (a0-12 city-attacker-info))
  (let ((s5-0 (new 'stack-no-clear 'vector)))
    (vector-copy! s5-0 (-> this node-list data arg0 bone transform uvec))
    (let ((s4-0 (vector<-cspace! (new 'stack-no-clear 'vector) (-> this node-list data arg0))))
      (set! (-> s5-0 y) 0.0)
      (when (or (< (-> this num-shots-fired) 3) (not (logtest? (-> this draw status) (draw-control-status on-screen))))
        (when (handle->process (-> this focus handle))
          (when (and (-> this attacker-info)
                     (-> this mission-squad)
                     (begin (set! a0-12 (get-attacker-at-idx (-> this mission-squad) (-> this attacker-info enemy-index))) a0-12)
                     (logtest? (-> a0-12 flags) (city-attacker-info-flag cai4))
                     )
            (let ((s2-2 (logand (rand-uint31-gen *random-generator*) 1))
                  (s3-0 (vector-x-quaternion! (new 'stack-no-clear 'vector) (-> this root quat)))
                  )
              (set! (-> s3-0 y) 0.0)
              (vector-normalize! s3-0 1.0)
              (if (= s2-2 1)
                  (vector-float*! s3-0 s3-0 -1.0)
                  )
              (let* ((s2-3 s5-0)
                     (s1-0 s5-0)
                     (f30-0 0.1)
                     (f28-0 0.1)
                     (v1-28 (/ (the-as int (rand-uint31-gen *random-generator*)) 256))
                     (v1-29 (the-as number (logior #x3f800000 v1-28)))
                     )
                (vector+float*! s2-3 s1-0 s3-0 (+ f30-0 (* f28-0 (+ -1.0 (the-as float v1-29)))))
                )
              )
            )
          )
        )
      (vector-normalize! s5-0 (vector-vector-xz-distance s4-0 (-> this focus-pos)))
      (set! (-> s5-0 y) (- (-> this focus-pos y) (-> s4-0 y)))
      (vector-normalize! s5-0 40960.0)
      (spawn-turret-projectile
        this
        s4-0
        (vector+! (new 'stack-no-clear 'vector) s4-0 s5-0)
        819200.0
        (the-as vector #f)
        )
      )
    )
  )

(defun update-ft-gun ((arg0 ft-gun-info) (arg1 float) (arg2 float) (arg3 float))
  (local-vars (f0-5 float))
  (let ((f0-2 (/ (- arg3 arg1) arg2)))
    (cond
      ((< f0-2 0.0)
       (set! (-> arg0 fire?) #f)
       (set! (-> arg0 gun-position) 1.0)
       )
      ((begin (set! (-> arg0 fire?) #t) (set! f0-5 (fmax 0.0 (fmin 1.0 f0-2))) 0.0 (< f0-5 0.1))
       (set! (-> arg0 gun-position) (- 1.0 (* 10.0 f0-5)))
       )
      (else
        (set! (-> arg0 gun-position) (* 1.1111112 (+ -0.1 f0-5)))
        )
      )
    )
  )

(defstate fire (flying-turret)
  :virtual #t
  :event enemy-event-handler
  :enter (behavior ()
    (set-time! (-> self state-time))
    (set! (-> self guns 0 fire?) #f)
    (set! (-> self guns 1 fire?) #f)
    (if (< (vector-length (-> self root transv)) 4096.0)
        (set! (-> self bob-scale-target) 0.3)
        )
    )
  :exit (behavior ()
    (set! (-> self bob-scale-target) 1.0)
    )
  :trans (behavior ()
    (let ((f30-0 (* 0.0044444446 (the float (- (current-time) (-> self state-time)))))
          (f0-1 0.01)
          (f28-0 0.26)
          (f26-0 0.75)
          (gp-0 (new 'stack-no-clear 'ft-gun-info))
          )
      (update-ft-gun gp-0 f0-1 f26-0 f30-0)
      (if (and (not (-> self guns 0 fire?)) (-> gp-0 fire?))
          (fire-shot-from-joint-idx self 5)
          )
      (mem-copy! (the-as pointer (-> self guns)) (the-as pointer gp-0) 8)
      (update-ft-gun gp-0 f28-0 f26-0 f30-0)
      (if (and (not (-> self guns 1 fire?)) (-> gp-0 fire?))
          (fire-shot-from-joint-idx self 6)
          )
      (mem-copy! (the-as pointer (-> self guns 1)) (the-as pointer gp-0) 8)
      )
    (when (or (time-elapsed? (-> self state-time) (seconds 1))
              (let ((v1-24 (ja-group)))
                (and (and v1-24 (= v1-24 (-> self draw art-group data 4))) (ja-done? 0))
                )
              )
      (set-time! (-> self last-fire-time))
      (+! (-> self num-shots-fired) 1)
      (go-virtual hostile)
      )
    )
  :code (behavior ()
    (when (< (vector-length (-> self root transv)) 4096.0)
      (ja-channel-push! 1 (seconds 0.1))
      (ja-no-eval :group! (-> self draw art-group data 4) :num! (seek! max 0.25) :frame-num 0.0)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek! max 0.25))
        )
      )
    (set-time! (-> self last-fire-time))
    (+! (-> self num-shots-fired) 1)
    (sleep-code)
    )
  :post (behavior ()
    (nav-enemy-method-187 self)
    )
  )

(defmethod event-handler ((this flying-turret) (arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  "Commmon handler for events."
  (case arg2
    (('notify)
     (case (-> arg3 param 0)
       (('attack)
        (if #t
            (set! (-> this hit-player?) #t)
            )
        )
       )
     )
    )
  ((method-of-type kg-squad-member event-handler) this arg0 arg1 arg2 arg3)
  )

(defmethod flying-turret-method-230 ((this flying-turret) (arg0 uint))
  (when (!= (-> this thrust-mode) arg0)
    (let ((v1-2 arg0))
      (cond
        ((= v1-2 2)
         (set! (-> this bob-scale-target) 1.0)
         )
        ((zero? v1-2)
         (set! (-> this bob-scale-target) 0.0)
         )
        )
      )
    )
  (set! (-> this thrust-mode) arg0)
  arg0
  )

(defstate hostile (flying-turret)
  :virtual #t
  :enter (behavior ()
    (nav-enemy-method-181 self)
    )
  :trans (behavior ()
    (local-vars (a0-34 city-attacker-info) (a0-39 city-attacker-info) (a0-48 city-attacker-info))
    (when (not (handle->process (-> self focus handle)))
      (flying-turret-method-226 self)
      (if (not (handle->process (-> self focus handle)))
          (go-virtual active)
          )
      )
    (let ((f0-0 (vector-vector-xz-distance-squared (-> self root trans) (-> self focus-pos)))
          (f1-0 245760.0)
          )
      (cond
        ((< (* f1-0 f1-0) f0-0)
         (vector-copy! (-> self move-dest) (-> self focus-pos))
         (set! (-> self chase-mode) (the-as uint 0))
         0
         )
        ((and (= (-> self chase-mode) 0) (let ((f1-3 163840.0))
                                           (< f0-0 (* f1-3 f1-3))
                                           )
              )
         (set! (-> self chase-mode) (the-as uint 1))
         (vector-copy! (-> self move-dest) (-> self root trans))
         )
        )
      )
    (when (= (-> self chase-mode) 1)
      (let ((f0-1 (vector-vector-xz-distance-squared (-> self root trans) (-> self move-dest)))
            (f1-6 20480.0)
            )
        (cond
          ((or (< f0-1 (* f1-6 f1-6)) (= (-> self thrust-mode) 2))
           (set-time! (-> self last-check-chase-pos-time))
           (let ((a1-5 (get-handle-pos (-> self squad) (-> self focus handle) (new 'stack-no-clear 'vector)))
                 (f0-2 245760.0)
                 )
             (cond
               ((or (< (* f0-2 f0-2) (vector-vector-xz-distance-squared (-> self move-dest) a1-5)) (-> self hit-player?))
                (set! (-> self hit-player?) #f)
                (squad-control-method-31 (-> self squad) (-> self move-dest) self (-> self current-enemy) 81920.0 0.0)
                (flying-turret-method-230 self (the-as uint 0))
                )
               (else
                 (when (!= (-> self thrust-mode) 2)
                   (flying-turret-method-230 self (the-as uint 2))
                   (set! (-> self num-shots-fired) 0)
                   (set! (-> self hit-player?) #f)
                   )
                 (vector-copy! (-> self move-dest) (-> self root trans))
                 )
               )
             )
           )
          ((time-elapsed? (-> self last-check-chase-pos-time) (seconds 1))
           (set-time! (-> self last-check-chase-pos-time))
           (let ((a1-10 (get-handle-pos (-> self squad) (-> self focus handle) (new 'stack-no-clear 'vector)))
                 (f0-5 204800.0)
                 )
             (if (< (* f0-5 f0-5) (vector-vector-xz-distance-squared (-> self move-dest) a1-10))
                 (squad-control-method-31 (-> self squad) (-> self move-dest) self (-> self current-enemy) 81920.0 0.0)
                 )
             )
           )
          )
        )
      )
    (when (and (= (-> self thrust-mode) 2)
               (or (and (and (-> self attacker-info)
                             (-> self mission-squad)
                             (begin (set! a0-34 (get-attacker-at-idx (-> self mission-squad) (-> self attacker-info enemy-index))) a0-34)
                             (logtest? (-> a0-34 flags) (city-attacker-info-flag cai4))
                             )
                        (time-elapsed? (-> self last-fire-time) (seconds 1.2))
                        )
                   (and (not (and (-> self attacker-info)
                                  (-> self mission-squad)
                                  (begin (set! a0-39 (get-attacker-at-idx (-> self mission-squad) (-> self attacker-info enemy-index))) a0-39)
                                  (logtest? (-> a0-39 flags) (city-attacker-info-flag cai4))
                                  )
                             )
                        (time-elapsed? (-> self last-fire-time) (seconds 0.75))
                        )
                   )
               )
      (let ((s5-0 #t)
            (gp-0 #f)
            )
        (when (and (handle->process (-> self focus handle))
                   (-> self attacker-info)
                   (-> self mission-squad)
                   (begin (set! a0-48 (get-attacker-at-idx (-> self mission-squad) (-> self attacker-info enemy-index))) a0-48)
                   (logtest? (-> a0-48 flags) (city-attacker-info-flag cai4))
                   )
          (cond
            ((not (and (as-type (handle->process (-> self focus handle)) process-focusable)
                       (not (logtest? (-> (the-as process-focusable (as-type (handle->process (-> self focus handle)) process-focusable))
                                          focus-status
                                          )
                                      (focus-status disable dead ignore grabbed)
                                      )
                            )
                       )
                  )
             (set! s5-0 #f)
             )
            ((>= (-> self num-shots-fired) 4)
             (set! gp-0 #t)
             )
            ((< (vector-vector-xz-distance (-> self root trans) (-> self focus-pos)) 40960.0)
             (set! gp-0 #t)
             )
            ((let ((a0-60 (new 'stack-no-clear 'sphere)))
               (set! (-> a0-60 quad) (-> self root trans quad))
               (set! (-> a0-60 r) (-> self root root-prim local-sphere w))
               (or (not (sphere-in-view-frustum? a0-60))
                   (not (logtest? (-> self draw status) (draw-control-status on-screen)))
                   )
               )
             (+! (-> self num-shots-fired) 1)
             (set! s5-0 #f)
             )
            )
          )
        (cond
          (gp-0
            (squad-control-method-31 (-> self squad) (-> self move-dest) self (-> self current-enemy) 81920.0 0.0)
            (flying-turret-method-230 self (the-as uint 0))
            )
          ((not s5-0)
           (set-time! (-> self last-fire-time))
           )
          (else
            (let ((s5-1 (vector-z-quaternion! (new 'stack-no-clear 'vector) (-> self root quat)))
                  (gp-2 (vector-! (new 'stack-no-clear 'vector) (-> self focus-pos) (-> self root trans)))
                  )
              (set! (-> s5-1 y) 0.0)
              (set! (-> gp-2 y) 0.0)
              (vector-normalize! s5-1 1.0)
              (vector-normalize! gp-2 1.0)
              (if (< 0.5 (vector-dot s5-1 gp-2))
                  (go-virtual fire)
                  )
              )
            )
          )
        )
      )
    (let ((a0-71 (-> self nav state))
          (v1-142 (-> self move-dest))
          )
      (logclear! (-> a0-71 flags) (nav-state-flag directional-mode))
      (logior! (-> a0-71 flags) (nav-state-flag target-poly-dirty))
      (vector-copy! (-> a0-71 target-pos) v1-142)
      )
    0
    )
  :code sleep-code
  :post (behavior ()
    (nav-enemy-method-187 self)
    )
  )

;; WARN: Return type mismatch float vs none.
(defmethod citizen-method-194 ((this flying-turret))
  (call-parent-method this)
  (set! (-> this turret-aim-blend) 0.0)
  (set! (-> this hit-player?) #f)
  (set! (-> this bob-velocity) 0.0)
  (let* ((f30-0 14336.0)
         (f28-0 10240.0)
         (v1-3 (/ (the-as int (rand-uint31-gen *random-generator*)) 256))
         (v1-4 (the-as number (logior #x3f800000 v1-3)))
         )
    (set! (-> this desired-height-offset) (+ f30-0 (* f28-0 (+ -1.0 (the-as float v1-4)))))
    )
  (set! (-> this changed-targets?) #f)
  (set! (-> this bob-scale-target) 0.0)
  (set! (-> this bob-scale-factor) 0.0)
  (set! (-> this up-bobbing?) #t)
  (set! (-> this bob-t) 0.0)
  (set! (-> this thruster-intensity-scalar) 1.0)
  (ja-channel-push! 1 0)
  (let ((a0-7 (-> this skel root-channel 0)))
    (set! (-> a0-7 frame-group) (the-as art-joint-anim (-> this draw art-group data 2)))
    (set! (-> a0-7 frame-num) 0.0)
    (joint-control-channel-group! a0-7 (the-as art-joint-anim (-> this draw art-group data 2)) num-func-identity)
    )
  (set! (-> this up-bobbing?) #t)
  (set! (-> this fact pickup-type) (pickup-type ammo-random))
  (set! (-> this fact pickup-amount) 1.0)
  (logior! (-> this fact options) (actor-option dont-override-fact))
  (set! (-> this fact pickup-spawn-amount) 5.0)
  (set! (-> this enemy-flags)
        (the-as enemy-flag (logclear (-> this enemy-flags) (enemy-flag auto-death-phase-out)))
        )
  (let ((a0-13 (-> this node-list data 5)))
    (set! (-> a0-13 param0) flying-turret-gun-recoil-jmod-func)
    (set! (-> a0-13 param1) this)
    )
  (let ((a0-14 (-> this node-list data 6)))
    (set! (-> a0-14 param0) flying-turret-gun-recoil-jmod-func)
    (set! (-> a0-14 param1) this)
    )
  (let ((a0-15 (-> this node-list data 4)))
    (set! (-> a0-15 param0) flying-turret-gun-aim-func)
    (set! (-> a0-15 param1) this)
    )
  (set! (-> this last-fire-time) 0)
  (set! (-> this pursuit-start-time) 0)
  (logclear! (-> this focus-status) (focus-status dangerous))
  (set! (-> this speed) 0.0)
  (set! (-> this speed-target) 0.0)
  (set! (-> this thrust-dir quad) (the-as uint128 0))
  (quaternion-copy! (-> this last-heading-quat) (-> this root quat))
  (quaternion-identity! (-> this last-roll-quat))
  (set! (-> this focus handle) (the-as handle #f))
  (set! (-> this thrust-mode) (the-as uint 0))
  (set! (-> this last-check-chase-pos-time) 0)
  (let* ((f30-1 65536.0)
         (v1-38 (/ (the-as int (rand-uint31-gen *random-generator*)) 256))
         (v1-39 (the-as number (logior #x3f800000 v1-38)))
         )
    (set! (-> this circle-angle) (* f30-1 (+ -1.0 (the-as float v1-39))))
    )
  (none)
  )

(defstate knocked (flying-turret)
  :virtual #t
  :parent (flying-turret flying-turret-base-state)
  :code (behavior ()
    (cond
      ((logtest? (-> group-kg-small-explosion flags) (sp-group-flag sp13))
       (vector-copy! (-> *launch-matrix* trans) (-> self root trans))
       (part-tracker-spawn part-tracker-subsampler :to *entity-pool* :group group-kg-small-explosion)
       )
      (else
        (vector-copy! (-> *launch-matrix* trans) (-> self root trans))
        (part-tracker-spawn part-tracker :to *entity-pool* :group group-kg-small-explosion)
        )
      )
    (when (kg-squad-member-method-220 self)
      (let ((v1-36 (new 'stack 'debris-tuning (the-as uint 1))))
        (set! (-> v1-36 hit-xz-reaction) 0.5)
        (set! (-> v1-36 hit-y-reaction) 0.6)
        (vector-copy! (-> v1-36 fountain-rand-transv-lo) (-> self incoming attack-position))
        )
      )
    (if (not (-> *setting-control* user-current gun-special-mode))
        (drop-pickup (-> self fact) #t *entity-pool* (-> self fact) 0 #f)
        )
    (sound-play "fly-turret-die")
    (cleanup-for-death self)
    )
  )

(defmethod deactivate ((this flying-turret))
  "Make a process dead, clean it up, remove it from the active pool, and return to dead pool."
  (sound-stop (-> this engine-sound))
  (sound-stop (-> this tilt-sound))
  (call-parent-method this)
  (none)
  )

(defmethod go-inactive ((this flying-turret))
  (sound-stop (-> this engine-sound))
  (sound-stop (-> this tilt-sound))
  (call-parent-method this)
  (none)
  )

(defmethod citizen-method-215 ((this flying-turret))
  (when (nonzero? *cty-attack-controller*)
    (set! (-> this mission-squad) *cty-attack-controller*)
    (when (not (-> this attacker-info))
      (set! (-> this attacker-info) (allocate-attacker (-> this mission-squad)))
      (init! (-> this attacker-info) this 10)
      )
    )
  (none)
  )

;; WARN: Return type mismatch object vs none.
(defmethod go-from-behavior ((this flying-turret) (arg0 traffic-object-spawn-params))
  (case (-> arg0 behavior)
    ((6)
     (vector-copy! (-> this root trans) (-> arg0 position))
     (when (handle->process (-> arg0 handle))
       (let ((s5-1 (vector+float*!
                     (new 'stack-no-clear 'vector)
                     (-> this root trans)
                     (vector-z-quaternion! (new 'stack-no-clear 'vector) (-> arg0 rotation))
                     49152.0
                     )
                   )
             )
         (nav-mesh-method-10 (-> this nav state mesh) s5-1 s5-1 (the-as nav-poly #f))
         (let ((v1-13 (-> this nav state)))
           (logclear! (-> v1-13 flags) (nav-state-flag directional-mode))
           (logior! (-> v1-13 flags) (nav-state-flag target-poly-dirty))
           (vector-copy! (-> v1-13 target-pos) s5-1)
           )
         )
       0
       )
     (go (method-of-object this exit-transport))
     )
    (else
      (call-parent-method this arg0)
      )
    )
  (none)
  )

(defstate exit-transport (flying-turret)
  :virtual #t
  :enter (behavior ()
    (set! (-> self chase-mode) (the-as uint 3))
    (flying-turret-method-230 self (the-as uint 0))
    (set-time! (-> self state-time))
    (nav-enemy-method-181 self)
    (nav-enemy-method-183 self)
    (nav-enemy-method-176 self)
    (let ((v1-12 (-> self nav state)))
      (set! (-> v1-12 speed) 0.0)
      )
    0
    (let ((a0-4 (-> self nav state))
          (v1-15 *null-vector*)
          )
      (vector-copy! (-> a0-4 velocity) v1-15)
      )
    0
    (let ((v1-18 (-> self nav)))
      (set! (-> v1-18 target-speed) (* (-> self speed-scale) (-> self speed-walk)))
      )
    0
    )
  :trans (behavior ()
    (let ((t9-0 add-debug-sphere)
          (a0-0 #t)
          (a1-0 583)
          (a3-0 (-> self nav state))
          (a2-0 (new 'stack-no-clear 'vector))
          )
      (vector-copy! a2-0 (-> a3-0 target-pos))
      (t9-0 a0-0 (the-as bucket-id a1-0) a2-0 (meters 2) *color-red*)
      )
    (let ((t9-1 vector-vector-xz-distance)
          (a0-1 (-> self root trans))
          (a2-1 (-> self nav state))
          (a1-1 (new 'stack-no-clear 'vector))
          )
      (vector-copy! a1-1 (-> a2-1 target-pos))
      (if (< (t9-1 a0-1 a1-1) 16384.0)
          (go-virtual active)
          )
      )
    )
  :code sleep-code
  :post (behavior ()
    (nav-enemy-method-187 self)
    )
  )

(defmethod get-trans ((this flying-turret) (arg0 int))
  "Get the `trans` for this process."
  (case arg0
    ((3)
     (let ((s5-1 (new 'static 'vector)))
       (vector-copy! s5-1 (-> this root trans))
       (vector<-cspace! s5-1 (-> this node-list data (-> this enemy-info bullseye-joint)))
       (set! (-> s5-1 w) 10240.0)
       s5-1
       )
     )
    (else
      (call-parent-method this arg0)
      )
    )
  )
