;;-*-Lisp-*-
(in-package goal)
(bundles "MIS.DGO")
(require "engine/common-obs/rigid-body.gc")
(require "engine/common-obs/nav-enemy.gc")

;; DECOMP BEGINS

(defpartgroup group-balloonlurker-pilot-death
  :id 203
  :duration (seconds 0.017)
  :linger-duration (seconds 2)
  :flags (use-local-clock)
  :bounds (static-bspherem 0 0 0 12)
  :parts ((sp-item 2015)))

(defpart 2015
  :init-specs
  ((:texture (starflash effects))
   (:num 1.0)
   (:y (meters 1))
   (:scale-x (meters 16))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 196.0)
   (:g 196.0)
   (:b 196.0)
   (:a 128.0)
   (:fade-a -3.2)
   (:timer (seconds 0.085))
   (:flags (bit2 bit3))))

(defpartgroup group-balloonlurker-mine-explosion
  :id 204
  :duration (seconds 2)
  :flags (use-local-clock)
  :bounds (static-bspherem 0 0 0 16)
  :parts
  ((sp-item 964 :period (seconds 4) :length (seconds 0.1))
   (sp-item 965 :fade-after (meters 60) :period (seconds 4) :length (seconds 0.05))
   (sp-item 966 :period (seconds 4) :length (seconds 0.05) :offset 15)
   (sp-item 967 :period (seconds 4) :length (seconds 0.05))
   (sp-item 968 :fade-after (meters 80) :period (seconds 4) :length (seconds 0.1) :binding 963)
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))
   (sp-item 963 :flags (start-dead))))

(defpart 964
  :init-specs
  ((:texture (bigpuff effects))
   (:num 1.5)
   (:y (meters 0.5) (meters 0.5))
   (:scale-x (meters 2.5) (meters 1.5))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 70.0)
   (:g 70.0)
   (:b 70.0 16.0)
   (:a 96.0)
   (:vel-y (meters 0.006666667) (meters 0.033333335))
   (:scalevel-x (meters 0.006))
   (:rotvel-z (degrees -0.2) (degrees 0.4))
   (:scalevel-y :copy scalevel-x)
   (:accel-y (meters 0.00005))
   (:friction 0.92)
   (:timer (seconds 3))
   (:flags (bit2 bit12 bit14))
   (:next-time (seconds 0.1) (seconds 0.997))
   (:next-launcher 969)
   (:conerot-x (degrees 70) (degrees 20))
   (:conerot-y (degrees 0) (degrees 360))
   (:conerot-radius (meters 2))))

(defpart 969
  :init-specs ((:scalevel-x (meters 0)) (:scalevel-y :copy scalevel-x) (:fade-a -0.32)))

(defpart 965
  :init-specs
  ((:texture (flare effects))
   (:num 6.0)
   (:y (meters 0.75))
   (:scale-x (meters 8) (meters 8))
   (:rot-x 4)
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y (meters 1.2) (meters 3))
   (:r 192.0)
   (:g 192.0)
   (:b 64.0 128.0)
   (:a 0.0)
   (:scalevel-x (meters 0.009765625))
   (:rotvel-z (degrees -0.15) (degrees 0.3))
   (:scalevel-y (meters 0.009765625))
   (:fade-a 2.1333334)
   (:timer (seconds 0.1))
   (:flags (bit2 bit3 bit14))
   (:next-time (seconds 0.05))
   (:next-launcher 970)
   (:rotate-y (degrees 0))))

(defpart 970
  :init-specs ((:fade-a -1.3333334)))

(defpart 966
  :init-specs
  ((:texture (starflash effects))
   (:num 1.0)
   (:y (meters 1))
   (:scale-x (meters 24) (meters 16))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 196.0)
   (:g 196.0)
   (:b 196.0)
   (:a 64.0)
   (:timer (seconds 0.017))
   (:flags (bit2 bit3 bit14))))

(defpart 967
  :init-specs
  ((:texture (starflash effects))
   (:num 1.0)
   (:y (meters 1))
   (:scale-x (meters 24) (meters 16))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 196.0)
   (:g 32.0)
   (:b 32.0)
   (:a 64.0)
   (:timer (seconds 0.017))
   (:flags (bit2 bit3 bit14))))

(defpart 968
  :init-specs
  ((:texture (hotdot effects))
   (:num 5.0 10.0)
   (:x (meters -0.5) (meters 1))
   (:y (meters 0.25) (meters 1.5))
   (:z (meters -0.5) (meters 1))
   (:scale-x (meters 0.5))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 255.0)
   (:g 127.0 1 127.0)
   (:b 0.0)
   (:a 127.0)
   (:vel-y (meters 0.06666667) (meters 0.06666667))
   (:fade-g -4.266667)
   (:fade-b -2.8444445)
   (:accel-y (meters -0.004))
   (:friction 0.97)
   (:timer (seconds 0.3))
   (:flags (bit2 bit3))
   (:next-time (seconds 0.017) (seconds 0.127))
   (:next-launcher 971)
   (:conerot-x (degrees 40) (degrees 30))
   (:conerot-y (degrees 0) (degrees 360))))

(defpart 971
  :init-specs
  ((:scalevel-x (meters -0.0033333334))
   (:scalevel-y :copy scalevel-x)
   (:fade-r -4.266667)
   (:fade-g 0.7111111)
   (:fade-b 1.4222223)
   (:fade-a -2.8444445)))

(defpart 963
  :init-specs
  ((:texture (bigpuff effects))
   (:num 2.0)
   (:x (meters -0.25) (meters 0.5))
   (:y (meters -0.25) (meters 0.5))
   (:z (meters -0.25) (meters 0.5))
   (:scale-x (meters 0.5) (meters 0.5))
   (:rot-z (degrees 0) (degrees 360))
   (:scale-y :copy scale-x)
   (:r 70.0)
   (:g 70.0)
   (:b 70.0 16.0)
   (:a 20.0 8.0)
   (:scalevel-x (meters 0.0033333334))
   (:rotvel-z (degrees -0.3) (degrees 0.6))
   (:scalevel-y :copy scalevel-x)
   (:fade-a -0.11666667)
   (:timer (seconds 1))
   (:flags (bit2 bit12))))

(deftype balloonlurker-bank (basic)
  ((buoyancy-depth-offset       meters)
   (player-mass                 float)
   (rudder-factor               float)
   (max-engine-thrust           float)
   (max-rudder-deflection-angle float)
   (throttle-factor             float)
   (throttle-distance           float)
   (throttle-close-distance     float)
   (explosion-force             float)
   (mine-weight                 float)))


(define *BALLOONLURKER-bank*
  (new 'static
       'balloonlurker-bank
       :buoyancy-depth-offset (meters 30)
       :player-mass 20.0
       :rudder-factor 32.0
       :max-engine-thrust 409600.0
       :max-rudder-deflection-angle 8192.0
       :throttle-factor 0.5
       :throttle-distance 53248.0
       :throttle-close-distance 81920.0
       :explosion-force 24576000.0
       :mine-weight 53248.0))

(define *balloonlurker-constants*
  (new 'static
       'rigid-body-platform-constants
       :drag-factor 1.6
       :buoyancy-factor 1.2
       :max-buoyancy-depth (meters 15)
       :gravity-factor 1.0
       :gravity (meters 60)
       :player-weight (meters 6.6)
       :player-bonk-factor 1.0
       :player-dive-factor 1.0
       :player-force-distance (meters 1000)
       :player-force-clamp (meters 1000000)
       :player-force-timeout (seconds 0.1)
       :explosion-force (meters 1000)
       :linear-damping 1.0
       :angular-damping 1.0
       :control-point-count 7
       :mass 2.0
       :inertial-tensor-x (meters 12)
       :inertial-tensor-y (meters 12)
       :inertial-tensor-z (meters 20)
       :cm-joint-y (meters 9)
       :idle-distance (meters 50)
       :platform #f
       :sound-name #f))

(deftype balloonlurker (rigid-body-platform)
  ((explosion-force-position    vector :inline)
   (explosion-force             vector :inline)
   (explosion                   symbol)
   (explosion-joint-index       uint16 2)
   (explosion-joint-index-bytes int8 4 :overlay-at (-> explosion-joint-index 0))
   (vulnerable                  symbol)
   (water-y                     float)
   (propeller                   joint-mod-spinner)
   (rudder                      joint-mod-set-local)
   (mine                        joint-mod-set-world 2)
   (buoyancy-factor             float)
   (rudder-control              float)
   (throttle-control            float)
   (engine-thrust               float)
   (dest-point                  vector :inline)
   (dest-point-old              vector :inline)
   (dest-index                  int8)
   (auto-pilot                  symbol)
   (dead                        symbol)
   (anim-frame                  float)
   (engine-sound-id             sound-id)
   (pedal-sound-id              sound-id)
   (frame-count                 int8))
  (:states
   balloonlurker-die
   (balloonlurker-mine-explode int)
   balloonlurker-patrol))


(deftype balloonlurker-pilot (process-drawable)
  ((root            collide-shape-moving :override)
   (parent-override (pointer balloonlurker) :overlay-at parent))
  (:methods
   (balloonlurker-pilot-method-20 (_type_) none)
   (balloonlurker-pilot-method-21 (_type_) none))
  (:states
   balloonlurker-pilot-die
   balloonlurker-pilot-idle))


(defskelgroup *balloonlurker-sg*
  balloonlurker
  balloonlurker-lod0-jg
  balloonlurker-idle-ja
  ((balloonlurker-lod0-mg (meters 20)) (balloonlurker-lod1-mg (meters 40)) (balloonlurker-lod2-mg (meters 999999)))
  :bounds (static-spherem 0 12 0 17))

(defskelgroup *balloonlurker-pilot-sg*
  balloonlurker
  balloonlurker-pilot-lod0-jg
  balloonlurker-pilot-idle-ja
  ((balloonlurker-pilot-lod0-mg (meters 20))
   (balloonlurker-pilot-lod1-mg (meters 40))
   (balloonlurker-pilot-lod2-mg (meters 999999)))
  :bounds (static-spherem 0 0 0 4))

(defbehavior balloonlurker-get-path-point balloonlurker ((arg0 int))
  (if (<= (-> self path curve num-cverts) 0) (go process-drawable-art-error "no path"))
  (set! (-> self dest-index) arg0)
  (set! (-> self dest-point-old quad) (-> self dest-point quad))
  (eval-path-curve-div! (-> self path) (-> self dest-point) (the float arg0) 'interp)
  0
  (none))

(defbehavior balloonlurker-get-next-path-point balloonlurker ()
  (if (<= (-> self path curve num-cverts) 0) (go process-drawable-art-error "no path"))
  (let ((a0-1 (+ (-> self dest-index) 1)))
    (if (= a0-1 (-> self path curve num-cverts)) (set! a0-1 0))
    (balloonlurker-get-path-point a0-1))
  0
  (none))

(defbehavior balloonlurker-snap-to-path-point balloonlurker ((arg0 int))
  (let ((s4-0 (new 'stack-no-clear 'vector))
        (gp-0 (new 'stack-no-clear 'vector)))
    (eval-path-curve-div! (-> self path) s4-0 (the float arg0) 'interp)
    (set! (-> self root-overlay trans quad) (-> s4-0 quad))
    (path-control-method-12 (-> self path) gp-0 (the float arg0))
    (set! (-> gp-0 y) 0.0)
    (vector-normalize! gp-0 1.0)
    (forward-up-nopitch->quaternion (-> self root-overlay quat) gp-0 *up-vector*)))

(defbehavior balloonlurker-find-nearest-path-point balloonlurker ()
  (let ((gp-0 0))
    (let ((f30-0 409600000.0)
          (s5-0 (new 'stack-no-clear 'vector)))
      (dotimes (s4-0 (-> self path curve num-cverts))
        (eval-path-curve-div! (-> self path) s5-0 (the float s4-0) 'interp)
        (let ((f0-2 (vector-vector-xz-distance (-> self root-overlay trans) s5-0)))
          (when (< f0-2 f30-0)
            (set! f30-0 f0-2)
            (set! gp-0 s4-0)))))
    (balloonlurker-get-path-point gp-0))
  (set! (-> self dest-point-old quad) (-> self dest-point quad))
  0
  (none))

(defbehavior balloonlurker-player-impulse balloonlurker ()
  (when *target*
    (set! (-> self player-impulse) (the-as collide-shape-prim-mesh #t))
    (set! (-> self player-force-position quad) (-> *target* control trans quad))
    (vector-! (-> self player-force) (-> self player-velocity) (-> *target* control transv))
    (vector-float*! (-> self player-force) (-> self player-force) (-> *BALLOONLURKER-bank* player-mass))))

(defbehavior balloonlurker-event-handler balloonlurker ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  (case arg2
    (('touch 'attack)
     (balloonlurker-player-impulse)
     (when ((method-of-type touching-shapes-entry prims-touching?)
            (the-as touching-shapes-entry (-> arg3 param 0))
            (-> self root-overlay)
            (the-as uint 1))
       (do-push-aways! (-> self root-overlay))
       (send-event arg0 'shove (-> arg3 param 0) (static-attack-info ((shove-back (meters 2)) (shove-up (meters 0.5))))))
     (dotimes (s4-0 2)
       (let ((s3-0 (if (zero? s4-0) 8 16)))
         (when ((method-of-type touching-shapes-entry prims-touching?)
                (the-as touching-shapes-entry (-> arg3 param 0))
                (-> self root-overlay)
                (the-as uint s3-0))
           (let ((a0-10 (find-prim-by-id (-> self root-overlay) (the-as uint s3-0))))
             (when a0-10
               (set! (-> self explosion-force-position quad) (-> a0-10 prim-core world-sphere quad))
               (if (send-event arg0 'attack (-> arg3 param 0) (static-attack-info ((mode 'balloonlurker))))
                 (level-hint-spawn (text-id misty-bike-mines-hint) "sksp0063" (the-as entity #f) *entity-pool* (game-task none)))
               (go balloonlurker-mine-explode s4-0))))))
     #f)
    (('die) (go balloonlurker-die))))

(defmethod rigid-body-platform-method-23 ((this balloonlurker) (arg0 float))
  (let ((s5-0 (new 'stack-no-clear 'vector)))
    (let ((s3-0 (new 'stack-no-clear 'vector))
          (s4-0 (-> this rbody matrix)))
      (dotimes (s2-0 4)
        (let ((s1-0 (-> this control-point-array data s2-0)))
          (vector-matrix*! (-> s1-0 world-pos) (-> s1-0 local-pos) s4-0)
          (rigid-body-method-17 (-> this rbody) (-> s1-0 world-pos) (-> s1-0 velocity))
          (let* ((f30-0 (vector-vector-xz-distance (-> this dest-point) (-> this root-overlay trans)))
                 (f0-0 (vector-vector-xz-distance (-> this dest-point-old) (-> this root-overlay trans)))
                 (f0-6 (/ (- (+ (/ (+ (* f30-0 (-> this dest-point-old y)) (* f0-0 (-> this dest-point y))) (fmax 409.6 (+ f30-0 f0-0)))
                                (-> *BALLOONLURKER-bank* buoyancy-depth-offset))
                             (-> s1-0 world-pos y))
                          (-> this info max-buoyancy-depth))))
            (vector-float*! s5-0
                            *y-vector*
                            (* (/ (-> this buoyancy-factor) 4)
                               (-> this info gravity-factor)
                               (fmax 0.3 (fmin 1.0 f0-6))
                               (-> this info gravity)
                               (-> this rbody mass))))
          (rigid-body-method-13 (-> this rbody) (-> s1-0 world-pos) s5-0)
          (vector-float*! s5-0 (-> s1-0 velocity) (* -1.0 (-> this info drag-factor)))
          (rigid-body-method-13 (-> this rbody) (-> s1-0 world-pos) s5-0))
        0)
      (let ((s2-1 (-> this control-point-array data 4)))
        (let ((f30-1 (* (-> *BALLOONLURKER-bank* max-rudder-deflection-angle) (-> this rudder-control))))
          (vector-matrix*! (-> s2-1 world-pos) (-> s2-1 local-pos) s4-0)
          (rigid-body-method-17 (-> this rbody) (-> s2-1 world-pos) (-> s2-1 velocity))
          (set-vector! s3-0 (cos f30-1) 0.0 (sin f30-1) 1.0))
        (vector-rotate*! s3-0 s3-0 s4-0)
        (vector-float*! s5-0 s3-0 (* -1.0 (-> *BALLOONLURKER-bank* rudder-factor) (vector-dot s3-0 (-> s2-1 velocity))))
        (rigid-body-method-13 (-> this rbody) (-> s2-1 world-pos) s5-0))
      0
      (let ((s3-1 (-> this control-point-array data 5)))
        (vector-matrix*! (-> s3-1 world-pos) (-> s3-1 local-pos) s4-0)
        (set! (-> s3-1 world-pos quad) (-> s3-1 world-pos quad))
        (vector-float*! s5-0 (-> s4-0 vector 2) (-> this engine-thrust))
        (rigid-body-method-13 (-> this rbody) (-> s3-1 world-pos) s5-0)))
    (dotimes (s4-1 2)
      (when (-> this mine s4-1 enable)
        (let ((v1-43 (-> this control-point-array data (if (zero? s4-1) 5 4))))
          (vector-float*! s5-0 *y-vector* (-> *BALLOONLURKER-bank* mine-weight))
          (rigid-body-method-13 (-> this rbody) (-> v1-43 world-pos) s5-0))))
    (vector-float*! s5-0 *y-vector* (* -1.0 (-> this info gravity-factor) (-> this info gravity) (-> this rbody mass)))
    (rigid-body-method-15 (-> this rbody) s5-0))
  (when (or (-> this player-impulse) (-> this player-contact))
    (set! (-> this player-impulse) #f)
    (rigid-body-method-13 (-> this rbody) (-> this player-force-position) (-> this player-force)))
  (when (-> this explosion)
    (set! (-> this explosion) #f)
    (rigid-body-method-13 (-> this rbody) (-> this explosion-force-position) (-> this explosion-force)))
  0
  (none))

(define *balloonlurker-rudder-joint-home* (new 'static 'vector :x 0.5 :y -0.5 :z -0.5 :w 0.5))

(defbehavior balloonlurker-play-sounds balloonlurker ()
  (cond
    ((not (-> self dead))
     (if (zero? (-> self engine-sound-id)) (set! (-> self engine-sound-id) (new-sound-id)))
     (if (zero? (-> self pedal-sound-id)) (set! (-> self pedal-sound-id) (new-sound-id)))
     (when (< (vector-vector-distance (-> self root-overlay trans) (ear-trans)) 286720.0)
       (let* ((f0-2 (/ (-> self engine-thrust) (-> *BALLOONLURKER-bank* max-engine-thrust)))
              (f1-2 100.0)
              (f0-3 (* 3.0 f0-2)))
         (sound-play "propeller"
                     :id (-> self engine-sound-id)
                     :vol
                     f1-2
                     :pitch
                     f0-3
                     :position
                     (the-as symbol (-> self node-list data 4 bone transform vector 3))))
       (sound-play "pedals" :id (-> self pedal-sound-id) :position (the-as symbol (-> self root-overlay trans)))))
    (else
     (when (nonzero? (-> self engine-sound-id))
       (sound-stop (-> self engine-sound-id))
       (set! (-> self engine-sound-id) (new 'static 'sound-id))
       0)
     (when (nonzero? (-> self pedal-sound-id))
       (sound-stop (-> self pedal-sound-id))
       (set! (-> self pedal-sound-id) (new 'static 'sound-id))
       0)))
  (none))

(defbehavior balloonlurker-post balloonlurker ()
  (set! (-> self anim-frame) (ja-frame-num 0))
  (cond
    ((and (-> self auto-pilot) (not (-> self dead)))
     (let* ((s4-0 (-> self rbody matrix vector 2))
            (s5-0 (-> self rbody matrix))
            (gp-0 (-> self rbody position))
            (f30-0 (vector-vector-xz-distance (-> self dest-point) gp-0)))
       (when (< f30-0 (-> *BALLOONLURKER-bank* throttle-close-distance))
         (balloonlurker-get-next-path-point)
         (set! f30-0 (vector-vector-xz-distance (-> self dest-point) gp-0)))
       (let ((f0-4 (- (vector-dot s4-0 (-> self dest-point)) (vector-dot s4-0 gp-0)))
             (f2-2 (- (vector-dot (the-as vector s5-0) (-> self dest-point)) (vector-dot (the-as vector s5-0) gp-0))))
         (seek! (-> self rudder-control) (fmax -1.0 (fmin 1.0 (/ f2-2 (fmax 4096.0 f0-4)))) (* 4.0 (seconds-per-frame))))
       (let ((f0-12 0.0)
             (f1-7 1.0)
             (f2-4 (* (-> *BALLOONLURKER-bank* throttle-factor) (- f30-0 (-> *BALLOONLURKER-bank* throttle-distance))))
             (f3-3 (-> *BALLOONLURKER-bank* throttle-distance)))
         (set! (-> self throttle-control) (fmax f0-12 (fmin f1-7 (* f2-4 (/ 1.0 f3-3)))))))
     0)
    (else
     (let ((f0-14 (analog-input (the-as int (-> *cpad-list* cpads 1 leftx)) 128.0 48.0 110.0 -1.0)))
       (seek! (-> self rudder-control) f0-14 (* 2.0 (seconds-per-frame))))
     (if (cpad-hold? 1 x)
       (seek! (-> self throttle-control) 1.0 (seconds-per-frame))
       (seek! (-> self throttle-control) 0.0 (* 0.25 (seconds-per-frame))))))
  (seek! (-> self engine-thrust)
         (* (-> self throttle-control) (-> *BALLOONLURKER-bank* max-engine-thrust))
         (/ (-> *BALLOONLURKER-bank* max-engine-thrust) 200))
  (let ((f0-31 60.0)
        (f1-14 1820.4445)
        (f2-6 6735.6445)
        (f3-6 (-> *BALLOONLURKER-bank* max-engine-thrust)))
    (set! (-> self propeller spin-rate) (* f0-31 (+ f1-14 (* f2-6 (/ 1.0 f3-6) (-> self engine-thrust))))))
  (let ((f0-34 (* (-> *BALLOONLURKER-bank* max-rudder-deflection-angle) (-> self rudder-control)))
        (gp-1 (new 'stack-no-clear 'quaternion)))
    (quaternion-vector-angle! gp-1 *x-vector* f0-34)
    (quaternion*! (-> self rudder transform quat) (the-as quaternion *balloonlurker-rudder-joint-home*) gp-1))
  (rigid-body-platform-method-28 self)
  (quaternion-copy! (-> self root-overlay quat) (-> self rbody rotation))
  (rigid-body-method-18 (-> self rbody) (-> self root-overlay trans))
  (balloonlurker-play-sounds)
  (when (nonzero? (-> self draw))
    (cond
      ((or (logtest? (-> self draw status) (draw-status no-skeleton-update))
           (logtest? (-> self draw status) (draw-status was-drawn)))
       (logclear! (-> self draw status) (draw-status skip-bones))
       (update-transforms! (-> self root-overlay))
       (ja-post))
      (else
       (set! (-> self draw origin quad) (-> self root-overlay trans quad))
       (logior! (-> self draw status) (draw-status skip-bones)))))
  (none))

(defstate balloonlurker-patrol (balloonlurker)
  :event balloonlurker-event-handler
  :trans
    (behavior ()
      (ja :num! (loop!))
      (set! (-> self anim-frame) (ja-frame-num 0)))
  :code
    (behavior ()
      (when (not (ja-group? balloonlurker-idle-ja))
        (ja-channel-push! 1 (seconds 0.07))
        (ja :group! balloonlurker-idle-ja)
        (ja :num-func num-func-identity :frame-num 0.0))
      (ja-post)
      (anim-loop))
  :post balloonlurker-post)

(defstate balloonlurker-mine-explode (balloonlurker)
  :event balloonlurker-event-handler
  :code
    (behavior ((arg0 int))
      (set! (-> self explosion-force-position quad)
            (-> self node-list data (-> self explosion-joint-index-bytes arg0) bone transform vector 3 quad))
      (process-spawn part-tracker
                     :init
                     part-tracker-init
                     group-balloonlurker-mine-explosion
                     -1
                     #f
                     #f
                     #f
                     (-> self explosion-force-position)
                     :to
                     *entity-pool*)
      (sound-play "explosion")
      (set! (-> self explosion) #t)
      (vector-! (-> self explosion-force) (-> self rbody position) (-> self explosion-force-position))
      (set! (-> self explosion-force y) (* 2.0 (-> self explosion-force y)))
      (vector-length (-> self explosion-force))
      (vector-normalize! (-> self explosion-force) (-> *BALLOONLURKER-bank* explosion-force))
      (suspend)
      (ja :num! (loop!))
      (let ((v1-16 (-> self mine arg0))) (set! (-> v1-16 enable) #t) (set-vector! (-> v1-16 transform scale) 0.0 0.0 0.0 1.0))
      (if (-> self dead) (go balloonlurker-die) (go balloonlurker-patrol)))
  :post balloonlurker-post)

(defstate balloonlurker-die (balloonlurker)
  :event #f
  :enter
    (behavior ()
      (set-time! (-> self state-time))
      (set! (-> self vulnerable) #f)
      (set! (-> self dead) #t))
  :code
    (behavior ()
      (local-vars (v1-27 symbol) (sv-16 symbol) (sv-20 (pointer process-tree)) (sv-24 entity-actor))
      (process-entity-status! self (entity-perm-status bit-4) #t)
      (process-entity-status! self (entity-perm-status dead) #t)
      (when (or (-> self link prev) (-> self link next))
        (set! sv-16 (the-as symbol #f))
        (set! sv-20 (-> self child))
        (set! sv-24 (entity-actor-lookup (-> self entity) 'alt-actor 0))
        (entity-birth-no-kill sv-24)
        (apply-all (-> self link) actor-link-dead-hook (& sv-16))
        (when (and sv-16 sv-24)
          (process-grab? *target*)
          (suspend-for (seconds 1))
          (process-release? *target*)
          (while (let ((a1-4 (new 'stack-no-clear 'event-message-block)))
                   (set! (-> a1-4 from) self)
                   (set! (-> a1-4 num-params) 0)
                   (set! (-> a1-4 message) 'task-complete)
                   (let ((t9-7 send-event-function)
                         (v1-17 sv-24))
                     (not (t9-7 (if v1-17 (-> v1-17 extra process)) a1-4))))
            (suspend))))
      (set! (-> self buoyancy-factor) (* 4.0 (-> self buoyancy-factor)))
      (until v1-27
        (suspend)
        (ja :num! (loop!))
        (set! v1-27
              (or (time-elapsed? (-> self state-time) (seconds 30)) (< 819200.0 (- (-> self root-overlay trans y) (-> self water-y))))))
      (cleanup-for-death self)
      (while (-> self child)
        (suspend)))
  :post balloonlurker-post)

(defmethod relocate ((this balloonlurker) (offset int))
  (if (nonzero? (-> this propeller)) (&+! (-> this propeller) offset))
  (if (nonzero? (-> this rudder)) (&+! (-> this rudder) offset))
  (if (nonzero? (-> this mine 0)) (&+! (-> this mine 0) offset))
  (if (nonzero? (-> this mine 1)) (&+! (-> this mine 1) offset))
  (call-parent-method this offset))

(defstate balloonlurker-pilot-idle (balloonlurker-pilot)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('attack) (send-event (ppointer->process (-> self parent-override)) 'die) (go balloonlurker-pilot-die))))
  :code
    (behavior ()
      (ja-channel-push! 1 (seconds 0.1))
      (ja :group! balloonlurker-pilot-idle-ja)
      (ja :num-func num-func-identity :frame-num 0.0)
      (loop
        (suspend)
        (ja :num-func num-func-identity :frame-num (-> self parent-override 0 anim-frame))))
  :post
    (behavior ()
      (set! (-> self root trans quad) (-> self parent-override 0 root-overlay trans quad))
      (quaternion-copy! (-> self root quat) (-> self parent-override 0 root-overlay quat))
      (update-transforms! (-> self root))
      (ja-post)))

(defstate balloonlurker-pilot-die (balloonlurker-pilot)
  :event process-drawable-death-event-handler
  :code
    (behavior ()
      (process-spawn part-tracker
                     :init
                     part-tracker-init
                     group-balloonlurker-pilot-death
                     -1
                     #f
                     #f
                     #f
                     (-> self root trans)
                     :to
                     *entity-pool*)
      (rigid-body-method-17 (-> self parent-override 0 rbody) (-> self root trans) (-> self root transv))
      (clear-collide-with-as (-> self root))
      (ja-channel-push! 1 (seconds 0.1))
      (ja-no-eval :group! balloonlurker-pilot-death-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!)))
      (cleanup-for-death self))
  :post
    (behavior ()
      (vector-v++! (-> self root transv) (compute-acc-due-to-gravity (-> self root) (new-stack-vector0) 0.0))
      (integrate-no-collide! (-> self root) (-> self root transv))
      (ja-post)))

(defmethod balloonlurker-pilot-method-20 ((this balloonlurker-pilot))
  (let ((s5-0 (new 'process 'collide-shape-moving this (collide-list-enum hit-by-player))))
    (set! (-> s5-0 dynam) (copy *standard-dynamics* 'process))
    (set! (-> s5-0 reaction) default-collision-reaction)
    (set! (-> s5-0 no-reaction) (the-as (function collide-shape-moving collide-shape-intersect vector vector none) nothing))
    (let ((s4-0 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 2))))
      (set! (-> s4-0 prim-core collide-as) (collide-kind enemy))
      (set! (-> s4-0 collide-with) (collide-kind target))
      (set! (-> s4-0 prim-core offense) (collide-offense touch))
      (set! (-> s4-0 transform-index) 6)
      (set-vector! (-> s4-0 local-sphere) 0.0 0.0 0.0 10240.0)
      (set-root-prim! s5-0 s4-0))
    (set! (-> s5-0 nav-radius) (* 0.75 (-> s5-0 root-prim local-sphere w)))
    (backup-collide-with-as s5-0)
    (set! (-> this root) s5-0))
  0
  (none))

(defmethod balloonlurker-pilot-method-21 ((this balloonlurker-pilot))
  (initialize-skeleton this *balloonlurker-pilot-sg* '())
  (set! (-> this draw origin-joint-index) (the-as uint 6))
  0
  (none))

(defbehavior balloonlurker-pilot-init-by-other balloonlurker-pilot ((arg0 balloonlurker))
  (logior! (-> self mask) (process-mask enemy))
  (balloonlurker-pilot-method-20 self)
  (logclear! (-> self mask) (process-mask actor-pause))
  (set! (-> self fact) (new 'process 'fact-info-enemy self (pickup-type eco-pill-random) (-> *FACT-bank* default-pill-inc)))
  (set! (-> self root trans quad) (-> arg0 root-overlay trans quad))
  (set! (-> self root quat vec quad) (-> arg0 root-overlay quat vec quad))
  (set! (-> self root scale quad) (-> arg0 root-overlay scale quad))
  (balloonlurker-pilot-method-21 self)
  (go balloonlurker-pilot-idle)
  (none))

(defmethod rigid-body-platform-method-30 ((this balloonlurker))
  (let ((s5-0 (new 'process 'collide-shape-moving this (collide-list-enum hit-by-player))))
    (set! (-> s5-0 dynam) (copy *standard-dynamics* 'process))
    (set! (-> s5-0 reaction) default-collision-reaction)
    (set! (-> s5-0 no-reaction) (the-as (function collide-shape-moving collide-shape-intersect vector vector none) nothing))
    (let ((s4-0 (new 'process 'collide-shape-prim-group s5-0 (the-as uint 4) 0)))
      (set! (-> s4-0 prim-core collide-as) (collide-kind enemy))
      (set! (-> s4-0 collide-with) (collide-kind target))
      (set! (-> s4-0 prim-core action) (collide-action solid))
      (set-vector! (-> s4-0 local-sphere) 0.0 40960.0 0.0 61440.0)
      (set-root-prim! s5-0 s4-0)
      (let ((s3-0 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 1))))
        (set! (-> s3-0 prim-core collide-as) (collide-kind enemy))
        (set! (-> s3-0 collide-with) (collide-kind target))
        (set! (-> s3-0 prim-core action) (collide-action solid))
        (set! (-> s3-0 prim-core offense) (collide-offense indestructible))
        (set-vector! (-> s3-0 local-sphere) 0.0 57344.0 0.0 28672.0)
        (append-prim s4-0 s3-0))
      (let ((s3-1 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 4))))
        (set! (-> s3-1 prim-core collide-as) (collide-kind enemy))
        (set! (-> s3-1 collide-with) (collide-kind target))
        (set! (-> s3-1 prim-core offense) (collide-offense normal-attack))
        (set! (-> s3-1 transform-index) 4)
        (set-vector! (-> s3-1 local-sphere) 0.0 0.0 -8192.0 10240.0)
        (append-prim s4-0 s3-1))
      (let ((s3-2 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 8))))
        (set! (-> s3-2 prim-core collide-as) (collide-kind enemy))
        (set! (-> s3-2 collide-with) (collide-kind target))
        (set! (-> s3-2 prim-core offense) (collide-offense normal-attack))
        (set! (-> s3-2 transform-index) 10)
        (set-vector! (-> s3-2 local-sphere) 0.0 -8192.0 0.0 6144.0)
        (append-prim s4-0 s3-2))
      (let ((s3-3 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 16))))
        (set! (-> s3-3 prim-core collide-as) (collide-kind enemy))
        (set! (-> s3-3 collide-with) (collide-kind target))
        (set! (-> s3-3 prim-core offense) (collide-offense normal-attack))
        (set! (-> s3-3 transform-index) 7)
        (set-vector! (-> s3-3 local-sphere) 0.0 -8192.0 0.0 6144.0)
        (append-prim s4-0 s3-3)))
    (set! (-> s5-0 nav-radius) (* 0.75 (-> s5-0 root-prim local-sphere w)))
    (backup-collide-with-as s5-0)
    (set! (-> s5-0 max-iteration-count) (the-as uint 1))
    (set! (-> this root-overlay) s5-0))
  0
  (none))

(defmethod rigid-body-platform-method-31 ((this balloonlurker))
  (logclear! (-> this mask) (process-mask actor-pause))
  (initialize-skeleton this *balloonlurker-sg* '())
  (set! (-> this root-overlay pause-adjust-distance) 1228800.0)
  (set! (-> this fact) (new 'process 'fact-info-enemy this (pickup-type eco-pill-random) (-> *FACT-bank* default-pill-inc)))
  (set! (-> this water-y) (-> this root-overlay trans y))
  (set! (-> this path) (new 'process 'path-control this 'path 0.0))
  (logior! (-> this path flags) (path-control-flag display draw-line draw-point draw-text))
  (set! (-> this link) (new 'process 'actor-link-info this))
  (balloonlurker-find-nearest-path-point)
  (balloonlurker-snap-to-path-point (-> this dest-index))
  (rigid-body-platform-method-29 this *balloonlurker-constants*)
  (dotimes (s5-0 4)
    (let ((s4-0 (-> this control-point-array data s5-0)))
      (let ((f30-0 (* 16384.0 (the float (logand s5-0 3)))))
        (set! (-> s4-0 local-pos x) (* 24576.0 (cos f30-0)))
        (set! (-> s4-0 local-pos y) 61440.0)
        (set! (-> s4-0 local-pos z) (* 36864.0 (sin f30-0))))
      (set! (-> s4-0 local-pos w) 1.0)))
  (let ((v1-22 (-> this control-point-array data 4)))
    (set! (-> v1-22 local-pos x) 0.0)
    (set! (-> v1-22 local-pos y) 61440.0)
    (set! (-> v1-22 local-pos z) -40960.0)
    (set! (-> v1-22 local-pos w) 1.0))
  (let ((v1-24 (-> this control-point-array data 5)))
    (set! (-> v1-24 local-pos x) 0.0)
    (set! (-> v1-24 local-pos y) 61440.0)
    (set! (-> v1-24 local-pos z) 40960.0)
    (set! (-> v1-24 local-pos w) 1.0))
  (let ((v1-26 (-> this control-point-array data 6)))
    (set! (-> v1-26 local-pos x) 0.0)
    (set! (-> v1-26 local-pos y) 0.0)
    (set! (-> v1-26 local-pos z) 0.0)
    (set! (-> v1-26 local-pos w) 1.0))
  (set! (-> this buoyancy-factor) (-> this info buoyancy-factor))
  (set! (-> this player-impulse) #f)
  (set! (-> this player-contact) #f)
  (set! (-> this auto-pilot) #t)
  (set! (-> this vulnerable) #t)
  (set! (-> this dead) #f)
  (set! (-> this explosion) #f)
  (set! (-> this propeller) (new 'process 'joint-mod-spinner this 4 (new 'static 'vector :z -1.0 :w 1.0) 8192.0))
  (set! (-> this rudder) (new 'process 'joint-mod-set-local this 12 #f #t #f))
  (set! (-> this mine 0) (new 'process 'joint-mod-set-world this 8 #f))
  (set! (-> this mine 1) (new 'process 'joint-mod-set-world this 5 #f))
  (set! (-> this explosion-joint-index-bytes 0) 10)
  (set! (-> this explosion-joint-index-bytes 1) 7)
  (set! (-> this engine-sound-id) (new 'static 'sound-id))
  (set! (-> this pedal-sound-id) (new 'static 'sound-id))
  (set! (-> this player-force quad) (-> *null-vector* quad))
  (set! (-> this player-velocity quad) (-> *null-vector* quad))
  0
  (none))

;; WARN: Function (method 11 balloonlurker) has a return type of none, but the expression builder found a return statement.
(defmethod init-from-entity! ((this balloonlurker) (arg0 entity-actor))
  (logior! (-> this mask) (process-mask enemy))
  (rigid-body-platform-method-30 this)
  (process-drawable-from-entity! this arg0)
  (rigid-body-platform-method-31 this)
  (cond
    ((logtest? (-> (entity-actor-lookup (-> this entity) 'alt-actor 0) extra perm status) (entity-perm-status complete))
     (process-entity-status! this (entity-perm-status dead) #t)
     (return #f))
    (else (process-spawn balloonlurker-pilot this :to this) (go balloonlurker-patrol)))
  (none))
