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

;; name: amphibian.gc
;; name in dgo: amphibian
;; dgos: ATE, SEB, SWB, RUI

(defenum amphibian-flags
  :bitfield #t
  :type uint8
  (amflags-0)
  (amflags-1)
  (amflags-2)
  (amflags-3)
  (amflags-4)
  (amflags-5)
  (amflags-6)
  (amflags-7)
  )

;; DECOMP BEGINS

(deftype amphibian-tongue-attack-info (structure)
  ((targ-dist    float)
   (max-length   float)
   (start-pos    vector  :inline)
   (base-dir     vector  :inline)
   (base-rot     vector  :inline)
   (targ-pos     vector  :inline)
   (targ-dir     vector  :inline)
   (targ-rot     vector  :inline)
   (clamped-pos  vector  :inline)
   (clamped-dir  vector  :inline)
   (clamped-rot  vector  :inline)
   )
  )


(deftype amphibian-joint-mod (basic)
  ((joint-index  int32)
   (proc         process-drawable)
   (max-length   float)
   (target       vector  :inline)
   )
  (:methods
    (new (symbol type process-drawable int) _type_)
    (amphibian-joint-mod-method-9 (_type_) none)
    )
  )


(defskelgroup skel-amphibian amphibian amphibian-lod0-jg -1
              ((amphibian-lod0-mg (meters 20)) (amphibian-lod1-mg (meters 999999)))
              :bounds (static-spherem 0 1 0 5.5)
              :shadow amphibian-shadow-mg
              )

(deftype amphibian-anim-info (structure)
  ((anim-index  int32)
   )
  )


(deftype amphibian-global-info (basic)
  ((prev-blue-hit      int8)
   (prev-knocked       int8)
   (notice-anim        int32  2)
   (run-anim           int32  2)
   (knocked-anim       int32  3)
   (knocked-land-anim  int32  3)
   (blue-hit-anim      int32  3)
   (jump-wind-up-anim  int32  2)
   (jump-in-air-anim   int32  2)
   (jump-land-anim     int32  2)
   )
  )


(deftype amphibian (nav-enemy)
  ((tongue-scale        float)
   (flags               amphibian-flags)
   (knocked-anim-index  int8)
   (jump-anim-index     int8)
   (tongue-mode         uint64)
   (tongue-mod          amphibian-joint-mod)
   (attacker-handle     handle)
   (prev-ry             float)
   (prev-ry1            float)
   )
  (:state-methods
    attack-forward
    attack-forward-lunge
    attack-forward-end
    attack-spin
    stare-idle
    tongue-attack
    )
  (:methods
    (amphibian-method-184 (_type_ vector vector) vector)
    (amphibian-method-185 (_type_ amphibian-tongue-attack-info) none)
    (amphibian-method-186 (_type_ vector vector) symbol)
    (amphibian-method-187 (_type_) none)
    )
  )


(define *amphibian-global-info* (new 'static 'amphibian-global-info
                                  :notice-anim (new 'static 'array int32 2 28 29)
                                  :run-anim (new 'static 'array int32 2 26 27)
                                  :knocked-anim (new 'static 'array int32 3 6 8 10)
                                  :knocked-land-anim (new 'static 'array int32 3 7 9 11)
                                  :blue-hit-anim (new 'static 'array int32 3 22 23 24)
                                  :jump-wind-up-anim (new 'static 'array int32 2 30 33)
                                  :jump-in-air-anim (new 'static 'array int32 2 31 34)
                                  :jump-land-anim (new 'static 'array int32 2 32 35)
                                  )
        )

(define *amphibian-nav-enemy-info*
  (new 'static 'nav-enemy-info
    :use-die-falling #t
    :use-victory #f
    :use-jump-blocked #t
    :debug-draw-neck #f
    :jump-debug-draw #f
    :move-to-ground #t
    :hover-if-no-ground #f
    :idle-anim-script (new 'static 'array idle-control-frame 4
      (new 'static 'idle-control-frame :command (ic-cmd play) :anim #x4 :param0 #x1 :param1 #x1)
      (new 'static 'idle-control-frame)
      (new 'static 'idle-control-frame)
      (new 'static 'idle-control-frame)
      )
    :idle-anim 4
    :notice-anim 28
    :hostile-anim 26
    :hit-anim 6
    :knocked-anim 6
    :knocked-land-anim 7
    :die-anim 12
    :die-falling-anim 21
    :victory-anim -1
    :jump-wind-up-anim 30
    :jump-in-air-anim 31
    :jump-land-anim 32
    :neck-joint 11
    :look-at-joint 12
    :bullseye-joint 4
    :sound-hit (static-sound-name "amphibian-hit")
    :sound-die (static-sound-name "amphibian-die")
    :notice-distance (meters 40)
    :notice-distance-delta (meters 10)
    :proximity-notice-distance (meters 20)
    :default-hit-points 4
    :gnd-collide-with (collide-spec backgnd)
    :overlaps-others-collide-with-filter (collide-spec jak bot player-list)
    :penetrate-knocked (penetrate
      generic-attack
      flop
      punch
      spin
      roll
      uppercut
      bonk
      tube
      vehicle
      flut-attack
      board
      mech-punch
      mech-bonk
      dark-skin
      dark-punch
      dark-bomb
      dark-giant
      shield
      explode
      jak-yellow-shot
      jak-red-shot
      jak-blue-shot
      jak-dark-shot
      enemy-yellow-shot
      enemy-dark-shot
      eco-yellow
      knocked
      )
    :movement-gravity (meters -100)
    :friction 0.8
    :attack-shove-back (meters 3.5)
    :attack-shove-up (meters 2)
    :attack-mode 'generic
    :attack-damage 1
    :recover-gnd-collide-with (collide-spec backgnd crate obstacle hit-by-others-list pusher)
    :jump-height-min (meters 3)
    :jump-height-factor 0.5
    :knocked-seek-ry-clamp 6371.5557
    :knocked-soft-vxz-lo 106496.0
    :knocked-soft-vxz-hi 94208.0
    :knocked-soft-vy-lo 122880.0
    :knocked-soft-vy-hi 139264.0
    :knocked-medium-vxz-lo 106496.0
    :knocked-medium-vxz-hi 94208.0
    :knocked-medium-vy-lo 122880.0
    :knocked-medium-vy-hi 139264.0
    :knocked-hard-vxz-lo 78643.2
    :knocked-hard-vxz-hi 117964.8
    :knocked-hard-vy-lo 183500.8
    :knocked-hard-vy-hi 209715.2
    :knocked-huge-vxz-lo 164659.2
    :knocked-huge-vxz-hi 249036.8
    :knocked-huge-vy-lo 183500.8
    :knocked-huge-vy-hi 217907.2
    :knocked-yellow-vxz-lo 40960.0
    :knocked-yellow-vxz-hi 49152.0
    :knocked-yellow-vy-lo 57344.0
    :knocked-yellow-vy-hi 81920.0
    :knocked-red-vxz-lo 24576.0
    :knocked-red-vxz-hi 196608.0
    :knocked-red-vy-lo 94208.0
    :knocked-red-vy-hi 151552.0
    :knocked-blue-vxz-lo 40960.0
    :knocked-blue-vxz-hi 49152.0
    :knocked-blue-vy-lo 24576.0
    :knocked-blue-vy-hi 81920.0
    :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)
    :callback-info #f
    :use-momentum #t
    :use-frustration #t
    :use-stop-chase #t
    :use-circling #t
    :use-pacing #t
    :walk-anim 16
    :turn-anim -1
    :run-anim 26
    :taunt-anim -1
    :run-travel-speed (meters 6)
    :run-acceleration (meters 8)
    :run-turning-acceleration (meters 10)
    :walk-travel-speed (meters 3)
    :walk-acceleration (meters 4)
    :walk-turning-acceleration (meters 3)
    :maximum-rotation-rate (degrees 180)
    :notice-nav-radius (meters 2)
    :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! (-> *amphibian-nav-enemy-info* fact-defaults) *fact-info-enemy-defaults*)

(defmethod relocate ((this amphibian-joint-mod) (offset int))
  (&+! (-> this proc) offset)
  this
  )

(defmethod general-event-handler ((this amphibian) (arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  "Handles various events for the enemy
   @TODO - unsure if there is a pattern for the events and this should have a more specific name"
  (case arg2
    (('hit-knocked)
     (logclear! (-> this mask) (process-mask actor-pause))
     (logclear! (-> this focus-status) (focus-status dangerous))
     (logclear! (-> this enemy-flags) (enemy-flag use-notice-distance))
     (logior! (-> this enemy-flags) (enemy-flag alert))
     (logior! (-> this focus-status) (focus-status hit))
     (if (zero? (-> this hit-points))
         (logior! (-> this focus-status) (focus-status dead))
         )
     (logclear! (-> this enemy-flags) (enemy-flag lock-focus))
     (enemy-method-62 this)
     (logior! (-> this enemy-flags) (enemy-flag lock-focus))
     (process-contact-action arg0)
     (send-event arg0 'get-attack-count 1)
     (when (= (-> this incoming knocked-type) (knocked-type knocked-type-4))
       (set! (-> this incoming knocked-type) (knocked-type knocked-type-0))
       0
       )
     (when (zero? (-> this hit-points))
       (case (-> this incoming knocked-type)
         (((knocked-type knocked-type-4) (knocked-type knocked-type-6))
          (set! (-> this incoming knocked-type) (knocked-type knocked-type-0))
          0
          )
         )
       )
     (go (method-of-object this knocked))
     (if (and (logtest? (-> this incoming penetrate-using) (penetrate punch))
              (nonzero? (-> this hit-points))
              (zero? (-> this fated-time))
              )
         'push
         #t
         )
     )
    (else
      ((method-of-type nav-enemy general-event-handler) this arg0 arg1 arg2 arg3)
      )
    )
  )

(defun amphibian-joint-mod-callback ((arg0 cspace) (arg1 transformq))
  (cspace<-parented-transformq-joint! arg0 arg1)
  (let ((s3-0 (new 'stack-no-clear 'inline-array 'matrix 3))
        (s2-0 (-> arg0 param1))
        (s5-0 (-> arg0 bone transform))
        (s4-0 (-> arg0 parent bone transform))
        )
    (vector-! (the-as vector (-> s3-0 0)) (-> (the-as amphibian-joint-mod s2-0) target) (-> s4-0 trans))
    (let ((f30-0 (fmin (vector-length (the-as vector (-> s3-0 0))) (-> (the-as amphibian-joint-mod s2-0) max-length))))
      (vector-normalize! (the-as vector (-> s3-0 0)) 1.0)
      (quaternion-from-two-vectors!
        (the-as quaternion (-> s3-0 0 vector 1))
        (vector-normalize-copy! (new 'stack-no-clear 'vector) (-> s5-0 vector 2) 1.0)
        (the-as vector (-> s3-0 0))
        )
      (quaternion->matrix (the-as matrix (-> s3-0 0 vector 2)) (the-as quaternion (-> s3-0 0 vector 1)))
      (matrix*! s5-0 s5-0 (the-as matrix (-> s3-0 0 vector 2)))
      (vector-normalize-copy!
        (-> s5-0 trans)
        (-> s5-0 vector 2)
        (* f30-0 (-> (the-as amphibian (-> (the-as amphibian-joint-mod s2-0) proc)) tongue-scale))
        )
      )
    (vector+! (-> s5-0 trans) (-> s5-0 trans) (-> s4-0 trans))
    )
  (set! (-> arg0 param0) #f)
  0
  (none)
  )

;; WARN: Return type mismatch amphibian-joint-mod vs none.
(defmethod amphibian-joint-mod-method-9 ((this amphibian-joint-mod))
  (let ((v1-3 (-> this proc node-list data (-> this joint-index))))
    (set! (-> v1-3 param0) amphibian-joint-mod-callback)
    (set! (-> v1-3 param1) this)
    )
  (none)
  )

(defmethod new amphibian-joint-mod ((allocation symbol) (type-to-make type) (arg0 process-drawable) (arg1 int))
  (let ((v0-0 (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
    (set! (-> v0-0 proc) arg0)
    (set! (-> v0-0 joint-index) arg1)
    v0-0
    )
  )

(defmethod set-incoming-attack-info ((this amphibian) (arg0 process) (arg1 object) (arg2 penetrate) (arg3 attack-info))
  (let ((t9-0 (method-of-type nav-enemy set-incoming-attack-info)))
    (t9-0 this arg0 arg1 arg2 arg3)
    )
  (let ((a0-3 (get-attacker this arg0 arg3)))
    (if a0-3
        (set! (-> this attacker-handle) (process->handle a0-3))
        (set! (-> this attacker-handle) (the-as handle #f))
        )
    )
  0
  (none)
  )

(defmethod damage-amount-from-attack ((this amphibian) (arg0 process) (arg1 event-message-block))
  "@returns the amount of damage taken from an attack.  This can come straight off the [[attack-info]] or via [[penetrate-using->damage]]"
  (let* ((t9-0 (method-of-type nav-enemy damage-amount-from-attack))
         (v0-0 (t9-0 this arg0 arg1))
         )
    (let ((v1-1 (-> this hit-points)))
      (if (> (- v1-1 v0-0) 0)
          (set! v0-0 (+ v1-1 -1))
          )
      )
    v0-0
    )
  )

(defmethod enemy-method-51 ((this amphibian))
  (local-vars (f0-1 float))
  0.0
  (set! f0-1
        (cond
          ((or (zero? (-> this hit-points)) (nonzero? (-> this fated-time)))
           ((method-of-type nav-enemy enemy-method-51) this)
           )
          (else
            (set! f0-1 (quaternion-y-angle (-> this root quat)))
            (let ((a0-5 (handle->process (-> this focus handle))))
              (when a0-5
                (let ((v1-12 (get-trans (the-as process-focusable a0-5) 0)))
                  (set! f0-1 (atan (- (-> v1-12 x) (-> this root trans x)) (- (-> v1-12 z) (-> this root trans z))))
                  )
                )
              )
            f0-1
            )
          )
        )
  f0-1
  )

;; WARN: Return type mismatch object vs none.
(defmethod enemy-method-52 ((this amphibian) (arg0 vector))
  (cond
    ((and (nonzero? (-> this hit-points)) (zero? (-> this fated-time)) (!= (-> this incoming knocked-type) 6))
     (enemy-method-50 this arg0)
     (let ((f30-0 (rnd-float-range this 0.0 1.0)))
       (vector-float*! arg0 arg0 (lerp 43417.6 58982.4 f30-0))
       (set! (-> arg0 y) (lerp 114688.0 116736.0 f30-0))
       )
     )
    (else
      ((method-of-type nav-enemy enemy-method-52) this arg0)
      )
    )
  (none)
  )

(defmethod enemy-method-77 ((this amphibian) (arg0 enemy-knocked-info))
  (case (-> this incoming knocked-type)
    (((knocked-type knocked-type-6))
     (let* ((v1-3 (rnd-bit this 3 (ash 1 (-> *amphibian-global-info* prev-blue-hit))))
            (s5-1 (-> this draw art-group data (-> *amphibian-global-info* blue-hit-anim v1-3)))
            )
       (set! (-> *amphibian-global-info* prev-blue-hit) v1-3)
       (ja-channel-push! 1 (seconds 0.02))
       (let ((a0-10 (-> this skel root-channel 0)))
         (set! (-> a0-10 frame-group) (the-as art-joint-anim s5-1))
         (set! (-> a0-10 param 0) (the float (+ (-> (the-as art-joint-anim s5-1) frames num-frames) -1)))
         (set! (-> a0-10 param 1) 1.0)
         (set! (-> a0-10 frame-num) 0.0)
         (joint-control-channel-group! a0-10 (the-as art-joint-anim s5-1) num-func-seek!)
         )
       )
     )
    (else
      (let ((v1-11 0))
        (when (or (zero? (-> this hit-points)) (nonzero? (-> this fated-time)))
          (let ((a2-5 (logior (ash 1 (-> *amphibian-global-info* prev-knocked)) 1)))
            (set! v1-11 (rnd-bit this 3 a2-5))
            )
          )
        (set! (-> *amphibian-global-info* prev-knocked) v1-11)
        (set! (-> this knocked-anim-index) v1-11)
        (let ((s4-0 (-> this draw art-group data (-> *amphibian-global-info* knocked-anim v1-11))))
          (ja-channel-push! 1 0)
          (let ((a0-25 (-> this skel root-channel 0)))
            (set! (-> a0-25 frame-group) (the-as art-joint-anim s4-0))
            (set! (-> a0-25 param 0) (the float (+ (-> (the-as art-joint-anim s4-0) frames num-frames) -1)))
            (set! (-> a0-25 param 1) (-> arg0 anim-speed))
            (set! (-> a0-25 frame-num) 0.0)
            (joint-control-channel-group! a0-25 (the-as art-joint-anim s4-0) num-func-seek!)
            )
          )
        )
      )
    )
  #t
  )

(defmethod enemy-method-78 ((this amphibian) (arg0 enemy-knocked-info))
  (cond
    ((= (-> this incoming knocked-type) (knocked-type knocked-type-6))
     (when (>= (-> this incoming blue-juggle-count) (the-as uint 2))
       (ja-channel-push! 1 (seconds 0.015))
       (let ((a0-3 (-> this skel root-channel 0)))
         (set! (-> a0-3 frame-group) (the-as art-joint-anim (-> this draw art-group data 25)))
         (set! (-> a0-3 param 0)
               (the float (+ (-> (the-as art-joint-anim (-> this draw art-group data 25)) frames num-frames) -1))
               )
         (set! (-> a0-3 param 1) (-> arg0 anim-speed))
         (set! (-> a0-3 frame-num) 0.0)
         (joint-control-channel-group! a0-3 (the-as art-joint-anim (-> this draw art-group data 25)) num-func-seek!)
         )
       #t
       )
     )
    (else
      (let ((s4-0
              (-> this draw art-group data (-> *amphibian-global-info* knocked-land-anim (-> this knocked-anim-index)))
              )
            )
        (if (zero? (-> this knocked-anim-index))
            (ja-channel-push! 1 (seconds 0.07))
            (ja-channel-push! 1 (seconds 0.15))
            )
        (let ((a0-10 (-> this skel root-channel 0)))
          (set! (-> a0-10 frame-group) (the-as art-joint-anim s4-0))
          (set! (-> a0-10 param 0) (the float (+ (-> (the-as art-joint-anim s4-0) frames num-frames) -1)))
          (set! (-> a0-10 param 1) (-> arg0 anim-speed))
          (set! (-> a0-10 frame-num) 0.0)
          (joint-control-channel-group! a0-10 (the-as art-joint-anim s4-0) num-func-seek!)
          )
        )
      #t
      )
    )
  )

(defmethod enemy-method-89 ((this amphibian) (arg0 enemy-jump-info))
  (let ((a0-1 (-> this skel root-channel 0)))
    (set! (-> a0-1 param 0) 1.0)
    (joint-control-channel-group! a0-1 (the-as art-joint-anim #f) num-func-loop!)
    )
  (let* ((v1-5 (rnd-int-count this 2))
         (s4-0 (-> this draw art-group data (-> *amphibian-global-info* jump-wind-up-anim v1-5)))
         )
    (set! (-> this jump-anim-index) v1-5)
    (ja-channel-push! 1 (seconds 0.1))
    (let ((a0-9 (-> this skel root-channel 0)))
      (set! (-> a0-9 frame-group) (the-as art-joint-anim s4-0))
      (set! (-> a0-9 param 0) (the float (+ (-> (the-as art-joint-anim s4-0) frames num-frames) -1)))
      (set! (-> a0-9 param 1) (-> arg0 anim-speed))
      (set! (-> a0-9 frame-num) 0.0)
      (joint-control-channel-group! a0-9 (the-as art-joint-anim s4-0) num-func-seek!)
      )
    )
  #t
  )

(defmethod enemy-method-87 ((this amphibian) (arg0 enemy-jump-info))
  (let ((s4-0 (-> this draw art-group data (-> *amphibian-global-info* jump-in-air-anim (-> this jump-anim-index)))))
    (ja-channel-push! 1 (seconds 0.07))
    (let ((a0-6 (-> this skel root-channel 0)))
      (set! (-> a0-6 frame-group) (the-as art-joint-anim s4-0))
      (set! (-> a0-6 param 0) (the float (+ (-> (the-as art-joint-anim s4-0) frames num-frames) -1)))
      (set! (-> a0-6 param 1) (-> arg0 anim-speed))
      (set! (-> a0-6 frame-num) 0.0)
      (joint-control-channel-group! a0-6 (the-as art-joint-anim s4-0) num-func-seek!)
      )
    )
  #t
  )

(defmethod enemy-method-88 ((this amphibian) (arg0 enemy-jump-info))
  (let ((s4-0 (-> this draw art-group data (-> *amphibian-global-info* jump-land-anim (-> this jump-anim-index)))))
    (if (zero? (-> this jump-anim-index))
        (ja-channel-push! 1 (seconds 0.07))
        (ja-channel-push! 1 (seconds 0.04))
        )
    (let ((a0-7 (-> this skel root-channel 0)))
      (set! (-> a0-7 frame-group) (the-as art-joint-anim s4-0))
      (set! (-> a0-7 param 0) (the float (+ (-> (the-as art-joint-anim s4-0) frames num-frames) -1)))
      (set! (-> a0-7 param 1) (-> arg0 anim-speed))
      (set! (-> a0-7 frame-num) 0.0)
      (joint-control-channel-group! a0-7 (the-as art-joint-anim s4-0) num-func-seek!)
      )
    )
  #t
  )

;; WARN: Return type mismatch object vs symbol.
(defmethod enemy-method-90 ((this amphibian) (arg0 int) (arg1 enemy-jump-info))
  (when (or (= (-> this jump-why) 3) (= (-> this jump-why) 2))
    (cond
      ((zero? arg0)
       (logior! (-> this focus-status) (focus-status touch-water under-water))
       )
      (else
        (when (focus-test? this touch-water)
          (let ((s3-0 (new 'stack-no-clear 'water-info)))
            (water-info-init! (-> this root) s3-0 (collide-action solid semi-solid))
            (let ((v1-12 #f))
              (cond
                ((not (logtest? (water-flags touch-water) (-> s3-0 flags)))
                 (if (focus-test? this under-water)
                     (set! v1-12 #t)
                     )
                 (logclear! (-> this focus-status) (focus-status touch-water under-water))
                 )
                ((focus-test? this under-water)
                 (let* ((a0-18 (-> this root root-prim prim-core))
                        (f0-1 (+ (-> a0-18 world-sphere y) (-> a0-18 world-sphere w)))
                        )
                   (if (< (-> s3-0 trans y) f0-1)
                       (set! v1-12 #t)
                       )
                   )
                 )
                )
              (when v1-12
                (logclear! (-> this focus-status) (focus-status under-water))
                (let ((s2-0 (new 'stack-no-clear 'vector)))
                  (set! (-> s2-0 quad) (-> this root trans quad))
                  (when (logtest? (water-flags touch-water) (-> s3-0 flags))
                    (set! (-> s2-0 y) (-> s3-0 trans y))
                    (part-tracker-spawn :to *entity-pool* :group group-part-water-splash :mat-joint s2-0)
                    (sound-play "splash-out")
                    )
                  )
                )
              )
            )
          )
        )
      )
    )
  (the-as
    symbol
    (cond
      ((and (= arg0 3) (= (-> this jump-anim-index) 1))
       (let* ((v1-35 (if (> (-> this skel active-channels) 0)
                         (-> this skel root-channel 0 frame-group)
                         )
                     )
              (s4-1 (and v1-35 (= v1-35 (-> this draw art-group data 36))))
              )
         (cond
           ((and (not s4-1) (< (-> this root transv y) 0.0))
            (ja-channel-push! 1 (seconds 0.1))
            (let ((a0-37 (-> this skel root-channel 0)))
              (set! (-> a0-37 frame-group) (the-as art-joint-anim (-> this draw art-group data 36)))
              (set! (-> a0-37 param 0)
                    (the float (+ (-> (the-as art-joint-anim (-> this draw art-group data 36)) frames num-frames) -1))
                    )
              (set! (-> a0-37 param 1) (-> arg1 anim-speed))
              (set! (-> a0-37 frame-num) 0.0)
              (joint-control-channel-group! a0-37 (the-as art-joint-anim (-> this draw art-group data 36)) num-func-seek!)
              )
            #f
            )
           (else
             (set! s4-1 (and (ja-done? 0) s4-1))
             (let ((a0-39 (-> this skel root-channel 0)))
               (set! (-> a0-39 param 0) (the float (+ (-> a0-39 frame-group frames num-frames) -1)))
               (set! (-> a0-39 param 1) (-> arg1 anim-speed))
               (joint-control-channel-group-eval! a0-39 (the-as art-joint-anim #f) num-func-seek!)
               )
             (ja-blend-eval)
             s4-1
             )
           )
         )
       )
      (else
        ((method-of-type nav-enemy enemy-method-90) this arg0 arg1)
        )
      )
    )
  )

(defmethod amphibian-method-184 ((this amphibian) (arg0 vector) (arg1 vector))
  (vector<-cspace! arg0 (-> this node-list data 13))
  (vector-! arg1 (-> this tongue-mod target) arg0)
  (vector-normalize!
    arg1
    (fmin (* (vector-length arg1) (-> this tongue-scale)) (-> this tongue-mod max-length))
    )
  (vector+! arg1 arg1 arg0)
  )

;; WARN: Return type mismatch float vs none.
(defmethod amphibian-method-185 ((this amphibian) (arg0 amphibian-tongue-attack-info))
  (let ((a0-1 (-> this node-list data 11 bone transform)))
    (set! (-> arg0 base-dir quad) (-> a0-1 vector 2 quad))
    )
  (vector-normalize! (-> arg0 base-dir) 1.0)
  (vector<-cspace! (-> arg0 start-pos) (-> this node-list data 13))
  (let ((a0-7 (handle->process (-> this focus handle))))
    (cond
      (a0-7
        (set! (-> arg0 targ-pos quad) (-> (get-trans (the-as process-focusable a0-7) 3) quad))
        )
      (else
        (vector-normalize-copy! (-> arg0 targ-pos) (-> arg0 base-dir) 36864.0)
        (vector+! (-> arg0 targ-pos) (-> arg0 targ-pos) (-> arg0 start-pos))
        )
      )
    )
  (vector-! (-> arg0 targ-dir) (-> arg0 targ-pos) (-> arg0 start-pos))
  (set! (-> arg0 targ-dist) (vector-length (-> arg0 targ-dir)))
  (vector-normalize! (-> arg0 targ-dir) 1.0)
  (rot-zxy-from-vector! (-> arg0 targ-rot) (-> arg0 targ-dir))
  (rot-zxy-from-vector! (-> arg0 base-rot) (-> arg0 base-dir))
  (set! (-> arg0 clamped-dir quad) (-> arg0 targ-dir quad))
  (set! (-> arg0 clamped-rot quad) (-> arg0 targ-rot quad))
  (let ((f30-0 (deg- (-> arg0 clamped-rot x) (-> arg0 base-rot x)))
        (f0-5 (deg- (-> arg0 clamped-rot y) (-> arg0 base-rot y)))
        )
    (when (or (< 4004.9778 (fabs f30-0)) (< 4004.9778 (fabs f0-5)))
      (let ((f1-3 (fmax -4004.9778 (fmin 4004.9778 f30-0)))
            (f0-7 (fmax -4004.9778 (fmin 4004.9778 f0-5)))
            )
        (set! (-> arg0 clamped-rot x) (+ (-> arg0 base-rot x) f1-3))
        (set! (-> arg0 clamped-rot y) (+ (-> arg0 base-rot y) f0-7))
        )
      (set-vector! (-> arg0 clamped-dir) 0.0 0.0 1.0 1.0)
      (vector-rotate-around-x! (-> arg0 clamped-dir) (-> arg0 clamped-dir) (-> arg0 clamped-rot x))
      (vector-rotate-around-y! (-> arg0 clamped-dir) (-> arg0 clamped-dir) (-> arg0 clamped-rot y))
      )
    )
  (vector-normalize-copy! (-> arg0 clamped-pos) (-> arg0 clamped-dir) (fmax 6144.0 (-> arg0 targ-dist)))
  (vector+! (-> arg0 clamped-pos) (-> arg0 clamped-pos) (-> arg0 start-pos))
  (let ((s4-3 (new 'stack-no-clear 'collide-query)))
    (set! (-> s4-3 start-pos quad) (-> arg0 start-pos quad))
    (vector-normalize-copy! (-> s4-3 move-dist) (-> arg0 clamped-dir) 73728.0)
    (let ((v1-32 s4-3))
      (set! (-> v1-32 radius) 409.6)
      (set! (-> v1-32 collide-with) (collide-spec backgnd crate obstacle hit-by-others-list pusher))
      (set! (-> v1-32 ignore-process0) this)
      (set! (-> v1-32 ignore-process1) #f)
      (set! (-> v1-32 ignore-pat) (new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1 :noendlessfall #x1))
      (set! (-> v1-32 action-mask) (collide-action solid))
      )
    (let ((f0-18 (fill-and-probe-using-line-sphere *collide-cache* s4-3)))
      (if (>= f0-18 0.0)
          (set! (-> arg0 max-length) (* 73728.0 f0-18))
          (set! (-> arg0 max-length) 73728.0)
          )
      )
    )
  (none)
  )

(defmethod amphibian-method-186 ((this amphibian) (arg0 vector) (arg1 vector))
  (let ((s4-0 (new 'stack-no-clear 'collide-query))
        (s5-0 (new 'stack-no-clear 'vector))
        )
    (set! (-> s4-0 start-pos quad) (-> arg0 quad))
    (vector-! (-> s4-0 move-dist) arg1 arg0)
    (set! (-> s5-0 quad) (-> s4-0 move-dist quad))
    (let ((v1-4 s4-0))
      (set! (-> v1-4 radius) 409.6)
      (set! (-> v1-4 collide-with) (collide-spec jak bot enemy obstacle hit-by-others-list player-list pusher))
      (set! (-> v1-4 ignore-process0) this)
      (set! (-> v1-4 ignore-process1) #f)
      (set! (-> v1-4 ignore-pat) (new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1 :noendlessfall #x1))
      (set! (-> v1-4 action-mask) (collide-action solid))
      )
    (when (>= (fill-and-probe-using-line-sphere *collide-cache* s4-0) 0.0)
      (let ((s4-1 (as-type (-> s4-0 best-other-tri collide-ptr) collide-shape-prim-sphere)))
        (when s4-1
          (set! (-> s5-0 y) 0.0)
          (vector-normalize! s5-0 1.0)
          (send-event
            (-> s4-1 cshape process)
            'attack
            #f
            (static-attack-info ((id (new-attack-id))
                                 (vector s5-0)
                                 (shove-back (meters 4))
                                 (shove-up (meters 3))
                                 (damage (the float (-> this enemy-info attack-damage)))
                                 )
                                )
            )
          )
        )
      #t
      )
    )
  )

;; WARN: Return type mismatch int vs symbol.
(defmethod enemy-method-76 ((this amphibian) (arg0 process) (arg1 event-message-block))
  (let ((t9-0 (method-of-type nav-enemy enemy-method-76)))
    (t9-0 this (the-as process-focusable arg0) arg1)
    )
  (the-as
    symbol
    (when (and (logtest? (-> (the-as process-focusable arg0) root root-prim prim-core collide-as) (collide-spec jak bot))
               (-> this next-state)
               (let ((v1-8 (-> this next-state name)))
                 (or (= v1-8 'stare) (= v1-8 'hostile))
                 )
               )
      (go (method-of-object this attack-spin))
      0
      )
    )
  )

(defmethod go-stare ((this amphibian))
  (let ((s5-0 (-> this focus aware)))
    (cond
      ((or (and (-> this enemy-info use-frustration) (logtest? (enemy-flag not-frustrated) (-> this enemy-flags)))
           (nav-enemy-method-163 this)
           )
       (go-stare2 this)
       )
      ((and (= s5-0 (enemy-aware enemy-aware-3)) (-> this enemy-info use-circling))
       (go (method-of-object this circling))
       )
      ((and (= s5-0 (enemy-aware enemy-aware-2)) (-> this enemy-info use-pacing))
       (go (method-of-object this pacing))
       )
      ((= s5-0 (enemy-aware unaware))
       (go (method-of-object this flee))
       )
      (else
        (go-stare2 this)
        )
      )
    )
  )

(defmethod go-hostile ((this amphibian))
  (let ((s5-0 (the-as process (as-type (handle->process (-> this attacker-handle)) process-focusable))))
    (when s5-0
      (set! (-> this attacker-handle) (the-as handle #f))
      (when (collide-check? (-> this focus) (the-as process-focusable s5-0))
        (try-update-focus (-> this focus) (the-as process-focusable s5-0) this)
        (go (method-of-object this tongue-attack))
        )
      )
    )
  (go (method-of-object this hostile))
  )

(defmethod common-post ((this amphibian))
  "Does a lot of various things relating to interacting with the target
   - tracks when the enemy was last drawn
   - looks at the target and handles attacking
   @TODO Not extremely well understood yet"
  (set! (-> this prev-ry) (-> this prev-ry1))
  (set! (-> this prev-ry1) (quaternion-y-angle (-> this root quat)))
  ((method-of-type nav-enemy common-post) this)
  (none)
  )

(defmethod amphibian-method-187 ((this amphibian))
  (with-pp
    (let* ((f30-0 (-> this nav state speed))
           (f26-0 0.0)
           (f0-1 (quaternion-y-angle (-> this root quat)))
           (f28-0 (deg- f0-1 (-> this prev-ry)))
           )
      (let ((s5-0 #f))
        (let ((s4-0 #f))
          (let ((v1-6 (if (> (-> this skel active-channels) 0)
                          (-> this skel root-channel 0 frame-group)
                          )
                      )
                )
            (set! f28-0 (cond
                          ((and v1-6 (or (= v1-6 (-> this draw art-group data 26))
                                         (= v1-6 (-> this draw art-group data 27))
                                         (= v1-6 (-> this draw art-group data 16))
                                         )
                                )
                           (set! f26-0 (ja-aframe-num 0))
                           (when (= (-> this skel root-channel 0) (-> this skel channel))
                             (cond
                               ((>= f26-0 13.0)
                                (set! s4-0 #t)
                                )
                               ((and (>= 1.0 f26-0) (logtest? (-> this flags) (amphibian-flags amflags-0)))
                                (set! s5-0 #t)
                                )
                               )
                             )
                           f28-0
                           )
                          (else
                            0.0
                            )
                          )
                  )
            )
          (if s4-0
              (logior! (-> this flags) (amphibian-flags amflags-0))
              (logclear! (-> this flags) (amphibian-flags amflags-0))
              )
          )
        (cond
          ((>= f30-0 18432.0)
           (let ((v1-29 (if (> (-> this skel active-channels) 0)
                            (-> this skel root-channel 0 frame-group)
                            )
                        )
                 )
             (cond
               ((and v1-29 (= v1-29 (-> this draw art-group data 26)))
                (when (and s5-0 (zero? (rnd-int-count this 5)))
                  (ja-channel-push! 1 (seconds 0.15))
                  (let ((s5-3 (-> this skel root-channel 0)))
                    (set! (-> s5-3 dist) 12288.0)
                    (joint-control-channel-group-eval!
                      s5-3
                      (the-as art-joint-anim (-> this draw art-group data 27))
                      num-func-identity
                      )
                    (set! (-> s5-3 frame-num) (ja-aframe f26-0 0))
                    )
                  (logclear! (-> this flags) (amphibian-flags amflags-0))
                  )
                )
               (else
                 (let ((v1-45 (if (> (-> this skel active-channels) 0)
                                  (-> this skel root-channel 0 frame-group)
                                  )
                              )
                       )
                   (cond
                     ((and v1-45 (= v1-45 (-> this draw art-group data 27)))
                      (when s5-0
                        (ja-channel-push! 1 (seconds 0.15))
                        (let ((s5-4 (-> this skel root-channel 0)))
                          (set! (-> s5-4 dist) 12288.0)
                          (joint-control-channel-group-eval!
                            s5-4
                            (the-as art-joint-anim (-> this draw art-group data 26))
                            num-func-identity
                            )
                          (set! (-> s5-4 frame-num) (ja-aframe f26-0 0))
                          )
                        (logclear! (-> this flags) (amphibian-flags amflags-0))
                        )
                      )
                     (else
                       (ja-channel-push! 1 (seconds 0.15))
                       (let ((s5-5 (-> this skel root-channel 0)))
                         (set! (-> s5-5 dist) 12288.0)
                         (joint-control-channel-group-eval!
                           s5-5
                           (the-as art-joint-anim (-> this draw art-group data 26))
                           num-func-identity
                           )
                         (set! (-> s5-5 frame-num) (ja-aframe f26-0 0))
                         )
                       (logclear! (-> this flags) (amphibian-flags amflags-0))
                       )
                     )
                   )
                 )
               )
             )
           )
          (else
            (let ((v1-67 (if (> (-> this skel active-channels) 0)
                             (-> this skel root-channel 0 frame-group)
                             )
                         )
                  )
              (when (not (and v1-67 (= v1-67 (-> this draw art-group data 16))))
                (ja-channel-push! 1 (seconds 0.1))
                (let ((s5-6 (-> this skel root-channel 0)))
                  (set! (-> s5-6 dist) 12288.0)
                  (joint-control-channel-group-eval!
                    s5-6
                    (the-as art-joint-anim (-> this draw art-group data 16))
                    num-func-identity
                    )
                  (set! (-> s5-6 frame-num) (ja-aframe f26-0 0))
                  )
                (logclear! (-> this flags) (amphibian-flags amflags-0))
                )
              )
            )
          )
        )
      (let* ((f0-15 (fmin 24576.0 (* 0.47123888 (-> pp clock frames-per-second) (fabs f28-0))))
             (f0-17 (* 0.00008680556 (fmax f30-0 f0-15)))
             (a0-49 (-> this skel root-channel 0))
             )
        (set! (-> a0-49 param 0) f0-17)
        (joint-control-channel-group-eval! a0-49 (the-as art-joint-anim #f) num-func-loop!)
        )
      )
    (ja-blend-eval)
    (none)
    )
  )

(defstate active (amphibian)
  :virtual #t
  :code (behavior ()
    (until #f
      (set-time! (-> self state-time))
      (until (time-elapsed? (-> self state-time) (seconds 1.067))
        (amphibian-method-187 self)
        (suspend)
        )
      (when (rnd-go-idle? self 0.2)
        (ja-no-eval :num! (loop!))
        (ja-channel-push! 1 (seconds 0.6))
        (let ((v1-15 self))
          (set! (-> v1-15 enemy-flags) (the-as enemy-flag (logclear (-> v1-15 enemy-flags) (enemy-flag enemy-flag36))))
          (set! (-> v1-15 nav callback-info) *nav-enemy-null-callback-info*)
          )
        0
        (nav-enemy-method-167 self)
        (ja-no-eval :group! (-> self draw art-group data (-> self enemy-info idle-anim)) :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (ja-blend-eval)
          (suspend)
          (ja :num! (seek!))
          )
        (until (not (rnd-go-idle? self 0.2))
          (ja-no-eval :group! (-> self draw art-group data (-> self enemy-info idle-anim)) :num! (seek!) :frame-num 0.0)
          (until (ja-done? 0)
            (suspend)
            (ja :num! (seek!))
            )
          )
        (let ((v1-83 self))
          (if (not (logtest? (enemy-flag enemy-flag36) (-> v1-83 enemy-flags)))
              (set! (-> v1-83 enemy-flags) (the-as enemy-flag (logior (enemy-flag enemy-flag38) (-> v1-83 enemy-flags))))
              )
          (set! (-> v1-83 enemy-flags) (the-as enemy-flag (logior (enemy-flag enemy-flag36) (-> v1-83 enemy-flags))))
          (set! (-> v1-83 nav callback-info) (-> v1-83 enemy-info callback-info))
          )
        0
        (nav-enemy-method-165 self)
        (ja-no-eval :num! (loop!))
        (until (time-elapsed? (-> self state-time) (seconds 1.067))
          (amphibian-method-187 self)
          (suspend)
          )
        )
      )
    #f
    )
  )

(defstate notice (amphibian)
  :virtual #t
  :enter (behavior ()
    (local-vars (gp-0 vector))
    (let ((t9-0 (-> (method-of-type nav-enemy notice) enter)))
      (if t9-0
          (t9-0)
          )
      )
    (let ((a0-1 (handle->process (-> self focus handle))))
      (set! gp-0 (cond
                   (a0-1
                     (set! gp-0 (-> self focus-pos))
                     (set! (-> gp-0 quad) (-> (get-trans (the-as process-focusable a0-1) 3) quad))
                     gp-0
                     )
                   (else
                     (vector-z-quaternion! (-> self focus-pos) (-> self root quat))
                     (vector-normalize! (-> self focus-pos) 24576.0)
                     (vector+! (-> self focus-pos) (-> self focus-pos) (-> self root trans))
                     )
                   )
            )
      )
    )
  :code (behavior ()
    (ja-channel-push! 1 (seconds 0.1))
    (let ((f30-0 (rnd-float-range self 0.8 1.2))
          (a1-3 (-> self draw art-group data (-> *amphibian-global-info* notice-anim (rnd-int-count self 2))))
          (gp-1 (new 'stack-no-clear 'vector))
          )
      (vector-! gp-1 (-> self focus-pos) (-> self root trans))
      (ja-no-eval :group! a1-3 :num! (seek! max f30-0) :frame-num 0.0)
      (until (ja-done? 0)
        (seek-toward-heading-vec! (-> self root) gp-1 65536.0 (seconds 0.02))
        (suspend)
        (ja :num! (seek! max f30-0))
        )
      )
    (let ((v1-27 (-> self nav state)))
      (set! (-> v1-27 speed) 8192.0)
      )
    0
    (let ((gp-2 (new 'stack-no-clear 'vector)))
      (vector-z-quaternion! gp-2 (-> self root quat))
      (set! (-> self nav state heading quad) (-> gp-2 quad))
      )
    0
    (react-to-focus self)
    )
  )

(defstate circling (amphibian)
  :virtual #t
  :code (behavior ()
    (nav-enemy-method-165 self)
    (until #f
      (amphibian-method-187 self)
      (suspend)
      )
    #f
    )
  )

(defstate pacing (amphibian)
  :virtual #t
  :code (behavior ()
    (until #f
      (amphibian-method-187 self)
      (suspend)
      )
    #f
    )
  )

(defstate stop-chase (amphibian)
  :virtual #t
  :code (behavior ()
    (until #f
      (amphibian-method-187 self)
      (suspend)
      )
    #f
    )
  )

(defstate stare (amphibian)
  :virtual #t
  :enter (behavior ()
    (local-vars (gp-0 vector))
    (let ((t9-0 (-> (method-of-type nav-enemy stare) enter)))
      (if t9-0
          (t9-0)
          )
      )
    (let ((v1-4 self))
      (set! (-> v1-4 enemy-flags) (the-as enemy-flag (logclear (-> v1-4 enemy-flags) (enemy-flag enemy-flag37))))
      )
    0
    (logior! (-> self enemy-flags) (enemy-flag lock-focus))
    (let ((v1-8 (-> self nav)))
      (set! (-> v1-8 turning-acceleration) 204800.0)
      )
    0
    (let ((a0-5 (handle->process (-> self focus handle))))
      (set! gp-0 (cond
                   (a0-5
                     (set! gp-0 (-> self focus-pos))
                     (set! (-> gp-0 quad) (-> (get-trans (the-as process-focusable a0-5) 0) quad))
                     gp-0
                     )
                   (else
                     (vector-z-quaternion! (-> self focus-pos) (-> self root quat))
                     (let ((f30-0 (rnd-float-range self 8192.0 16384.0)))
                       (if (zero? (rnd-int-count self 2))
                           (set! f30-0 (- f30-0))
                           )
                       (vector-rotate-around-y! (-> self focus-pos) (-> self focus-pos) f30-0)
                       )
                     (vector-normalize! (-> self focus-pos) 12288.0)
                     (vector+! (-> self focus-pos) (-> self focus-pos) (-> self root trans))
                     )
                   )
            )
      )
    )
  :exit (behavior ()
    (let ((t9-0 (-> (method-of-type nav-enemy stare) exit)))
      (if t9-0
          (t9-0)
          )
      )
    (logclear! (-> self enemy-flags) (enemy-flag lock-focus))
    )
  :trans (behavior ()
    (when (logtest? (-> self enemy-flags) (enemy-flag victory))
      (logclear! (-> self enemy-flags) (enemy-flag victory))
      (sound-play "amphib-hit")
      )
    )
  :code (behavior ()
    (ja-channel-push! 1 (seconds 0.07))
    (let ((s5-0 (new 'stack-no-clear 'vector))
          (gp-0 (new 'stack-no-clear 'vector))
          (s4-0 (new 'stack-no-clear 'vector))
          )
      (vector-z-quaternion! s4-0 (-> self root quat))
      (set-vector! s5-0 (- (-> s4-0 z)) 0.0 (-> s4-0 x) 1.0)
      (vector-! gp-0 (-> self focus-pos) (-> self root trans))
      (vector-normalize! s4-0 1.0)
      (vector-normalize! gp-0 1.0)
      (cond
        ((>= (vector-dot s4-0 gp-0) 0.707)
         (ja-no-eval :group! amphibian-attack-forward-ja :num! (seek!) :frame-num (ja-aframe 0.0 0))
         )
        (else
          (let ((v1-22 (>= (vector-dot s5-0 gp-0) 0.0)))
            (if (logtest? (enemy-flag drawn-mirrored) (-> self enemy-flags))
                (set! v1-22 (not v1-22))
                )
            (if v1-22
                (ja-no-eval :group! amphibian-attack-right-ja :num! (seek!) :frame-num (ja-aframe 0.0 0))
                (ja-no-eval :group! amphibian-attack-left-ja :num! (seek!) :frame-num (ja-aframe 0.0 0))
                )
            )
          )
        )
      )
    (until (>= (ja-aframe-num 0) (ja-aframe 2.0 0))
      (suspend)
      (ja :num! (seek!))
      )
    (until (>= (ja-aframe-num 0) (ja-aframe 6.0 0))
      (seek-to-point-toward-point! (-> self root) (-> self focus-pos) 546133.3 (seconds 0.1))
      (suspend)
      (ja :num! (seek!))
      )
    (ja-no-eval :num! (seek!))
    (while (not (ja-done? 0))
      (suspend)
      (ja-eval)
      )
    (go-virtual stare-idle)
    )
  )

(defstate stare-idle (amphibian)
  :virtual #t
  :event enemy-event-handler
  :enter (behavior ()
    ((-> (method-of-type nav-enemy stare) enter))
    (let ((v1-2 self))
      (set! (-> v1-2 enemy-flags) (the-as enemy-flag (logclear (-> v1-2 enemy-flags) (enemy-flag enemy-flag37))))
      )
    0
    )
  :exit (-> (method-of-type nav-enemy stare) exit)
  :trans (-> (method-of-type nav-enemy stare) trans)
  :code (behavior ()
    (ja-channel-push! 1 (seconds 0.1))
    (let ((gp-0 (rnd-int-range self 1 3)))
      (dotimes (s5-0 gp-0)
        (ja-no-eval :group! amphibian-idle-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (suspend)
          (ja :num! (seek!))
          )
        )
      )
    (go-virtual stare)
    )
  :post nav-enemy-stare-post
  )

(defstate hostile (amphibian)
  :virtual #t
  :trans (behavior ()
    (let ((t9-0 (-> (method-of-type nav-enemy hostile) trans)))
      (if t9-0
          (t9-0)
          )
      )
    (when (logtest? (-> self enemy-flags) (enemy-flag victory))
      (logclear! (-> self enemy-flags) (enemy-flag victory))
      (go-virtual attack-spin)
      )
    (let ((a0-2 (get-enemy-target self)))
      (when a0-2
        (let* ((s5-0 (get-trans a0-2 0))
               (f30-0 (vector-vector-xz-distance s5-0 (-> self root trans)))
               )
          (when (>= 20480.0 f30-0)
            (let ((gp-0 (new 'stack-no-clear 'vector)))
              (vector-! gp-0 s5-0 (-> self root trans))
              (let ((f28-0 (quaternion-y-angle (-> self root quat)))
                    (f0-3 (atan (-> gp-0 x) (-> gp-0 z)))
                    )
                (if (>= 8192.0 (fabs (deg- f28-0 f0-3)))
                    (go-virtual attack-forward)
                    )
                )
              )
            (if (>= 14336.0 f30-0)
                (go-virtual attack-spin)
                )
            )
          )
        )
      )
    )
  :code (behavior ()
    (until #f
      (amphibian-method-187 self)
      (suspend)
      )
    #f
    )
  )

(defstate attack-forward (amphibian)
  :virtual #t
  :event enemy-event-handler
  :enter (behavior ()
    (logior! (-> self enemy-flags) (enemy-flag lock-focus))
    (let ((v1-2 self))
      (set! (-> v1-2 enemy-flags) (the-as enemy-flag (logclear (-> v1-2 enemy-flags) (enemy-flag enemy-flag36))))
      (set! (-> v1-2 nav callback-info) *nav-enemy-null-callback-info*)
      )
    0
    (nav-enemy-method-167 self)
    (let ((v1-7 (-> self nav)))
      (set! (-> v1-7 turning-acceleration) 204800.0)
      )
    0
    (logior! (-> self focus-status) (focus-status dangerous))
    (let* ((v1-11 *game-info*)
           (a0-7 (+ (-> v1-11 attack-id) 1))
           )
      (set! (-> v1-11 attack-id) a0-7)
      (set! (-> self attack-id) a0-7)
      )
    (let ((gp-0 (handle->process (-> self focus handle))))
      (if (not gp-0)
          (react-to-focus self)
          )
      (set! (-> self focus-pos quad) (-> (get-trans (the-as process-focusable gp-0) 0) quad))
      )
    )
  :exit (behavior ()
    (logclear! (-> self enemy-flags) (enemy-flag lock-focus))
    (if (logtest? (-> self enemy-flags) (enemy-flag dangerous-backup))
        (logior! (-> self focus-status) (focus-status dangerous))
        (logclear! (-> self focus-status) (focus-status dangerous))
        )
    )
  :trans (behavior ()
    (when (logtest? (-> self enemy-flags) (enemy-flag victory))
      (logclear! (-> self enemy-flags) (enemy-flag victory))
      (sound-play "amphib-hit")
      )
    )
  :code (behavior ()
    (ja-channel-push! 1 (seconds 0.07))
    (ja-no-eval :group! amphibian-attack-ja :num! (seek!) :frame-num (ja-aframe 0.0 0))
    (until (>= (ja-aframe-num 0) (ja-aframe 2.0 0))
      (suspend)
      (ja :num! (seek!))
      )
    (go-virtual attack-forward-lunge)
    )
  :post nav-enemy-simple-post
  )

(defstate attack-forward-lunge (amphibian)
  :virtual #t
  :event enemy-event-handler
  :enter (behavior ()
    (let ((v1-1 (-> self nav state)))
      (set! (-> v1-1 speed) 51200.0)
      )
    0
    (let ((v1-3 (-> self nav)))
      (set! (-> v1-3 turning-acceleration) 204800.0)
      )
    0
    (logior! (-> self enemy-flags) (enemy-flag lock-focus))
    (let ((v1-7 self))
      (if (not (logtest? (enemy-flag enemy-flag36) (-> v1-7 enemy-flags)))
          (set! (-> v1-7 enemy-flags) (the-as enemy-flag (logior (enemy-flag enemy-flag38) (-> v1-7 enemy-flags))))
          )
      (set! (-> v1-7 enemy-flags) (the-as enemy-flag (logior (enemy-flag enemy-flag36) (-> v1-7 enemy-flags))))
      (set! (-> v1-7 nav callback-info) (-> v1-7 enemy-info callback-info))
      )
    0
    (let ((v1-10 self))
      (set! (-> v1-10 enemy-flags) (the-as enemy-flag (logior (enemy-flag enemy-flag37) (-> v1-10 enemy-flags))))
      )
    0
    (logior! (-> self focus-status) (focus-status dangerous))
    )
  :exit (behavior ()
    (logclear! (-> self enemy-flags) (enemy-flag lock-focus))
    (if (logtest? (-> self enemy-flags) (enemy-flag dangerous-backup))
        (logior! (-> self focus-status) (focus-status dangerous))
        (logclear! (-> self focus-status) (focus-status dangerous))
        )
    )
  :trans (behavior ()
    (when (logtest? (-> self enemy-flags) (enemy-flag victory))
      (logclear! (-> self enemy-flags) (enemy-flag victory))
      (sound-play "amphib-hit")
      )
    )
  :code (behavior ()
    (until (>= (ja-aframe-num 0) (ja-aframe 8.0 0))
      (suspend)
      (ja :num! (seek!))
      )
    (go-virtual attack-forward-end)
    )
  :post (behavior ()
    (let ((a0-1 (handle->process (-> self focus handle))))
      (if a0-1
          (set! (-> self focus-pos quad) (-> (get-trans (the-as process-focusable a0-1) 0) quad))
          )
      )
    (let ((a0-4 (-> self nav state))
          (v1-8 (-> self focus-pos))
          )
      (logclear! (-> a0-4 flags) (nav-state-flag directional-mode))
      (logior! (-> a0-4 flags) (nav-state-flag target-poly-dirty))
      (set! (-> a0-4 target-post quad) (-> v1-8 quad))
      )
    0
    (nav-enemy-travel-post)
    )
  )

(defstate attack-forward-end (amphibian)
  :virtual #t
  :event enemy-event-handler
  :enter (behavior ()
    (logior! (-> self enemy-flags) (enemy-flag lock-focus))
    (logior! (-> self focus-status) (focus-status dangerous))
    (let ((v1-4 self))
      (set! (-> v1-4 enemy-flags) (the-as enemy-flag (logclear (-> v1-4 enemy-flags) (enemy-flag enemy-flag36))))
      (set! (-> v1-4 nav callback-info) *nav-enemy-null-callback-info*)
      )
    0
    (nav-enemy-method-167 self)
    )
  :exit (behavior ()
    (logclear! (-> self enemy-flags) (enemy-flag lock-focus))
    (if (logtest? (-> self enemy-flags) (enemy-flag dangerous-backup))
        (logior! (-> self focus-status) (focus-status dangerous))
        (logclear! (-> self focus-status) (focus-status dangerous))
        )
    )
  :trans (behavior ()
    (when (logtest? (-> self enemy-flags) (enemy-flag victory))
      (logclear! (-> self enemy-flags) (enemy-flag victory))
      (sound-play "amphib-hit")
      )
    )
  :code (behavior ()
    (ja-no-eval :num! (seek!))
    (while (not (ja-done? 0))
      (suspend)
      (ja-eval)
      )
    (react-to-focus self)
    )
  :post nav-enemy-simple-post
  )

(defstate attack-spin (amphibian)
  :virtual #t
  :event enemy-event-handler
  :enter (behavior ()
    (logior! (-> self enemy-flags) (enemy-flag lock-focus))
    (let ((v1-2 self))
      (set! (-> v1-2 enemy-flags) (the-as enemy-flag (logclear (-> v1-2 enemy-flags) (enemy-flag enemy-flag36))))
      (set! (-> v1-2 nav callback-info) *nav-enemy-null-callback-info*)
      )
    0
    (nav-enemy-method-167 self)
    (let ((v1-7 self))
      (set! (-> v1-7 enemy-flags) (the-as enemy-flag (logclear (-> v1-7 enemy-flags) (enemy-flag enemy-flag37))))
      )
    0
    (let ((v1-9 (-> self nav)))
      (set! (-> v1-9 turning-acceleration) 204800.0)
      )
    0
    (logior! (-> self focus-status) (focus-status dangerous))
    (let* ((v1-13 *game-info*)
           (a0-9 (+ (-> v1-13 attack-id) 1))
           )
      (set! (-> v1-13 attack-id) a0-9)
      (set! (-> self attack-id) a0-9)
      )
    (let ((gp-0 (handle->process (-> self focus handle))))
      (if (not gp-0)
          (react-to-focus self)
          )
      (set! (-> self focus-pos quad) (-> (get-trans (the-as process-focusable gp-0) 0) quad))
      )
    )
  :exit (behavior ()
    (logclear! (-> self enemy-flags) (enemy-flag lock-focus))
    (if (logtest? (-> self enemy-flags) (enemy-flag dangerous-backup))
        (logior! (-> self focus-status) (focus-status dangerous))
        (logclear! (-> self focus-status) (focus-status dangerous))
        )
    )
  :trans (behavior ()
    (when (logtest? (-> self enemy-flags) (enemy-flag victory))
      (logclear! (-> self enemy-flags) (enemy-flag victory))
      (sound-play "amphib-hit")
      )
    )
  :code (behavior ()
    (ja-channel-push! 1 (seconds 0.07))
    (let ((s5-0 (new 'stack-no-clear 'vector))
          (gp-0 (new 'stack-no-clear 'vector))
          (s4-0 (new 'stack-no-clear 'vector))
          )
      (vector-z-quaternion! s4-0 (-> self root quat))
      (set-vector! s5-0 (- (-> s4-0 z)) 0.0 (-> s4-0 x) 1.0)
      (vector-! gp-0 (-> self focus-pos) (-> self root trans))
      (vector-normalize! s4-0 1.0)
      (vector-normalize! gp-0 1.0)
      (cond
        ((>= (vector-dot s4-0 gp-0) 0.707)
         (ja-no-eval :group! amphibian-attack-forward-ja :num! (seek!) :frame-num (ja-aframe 0.0 0))
         )
        (else
          (let ((v1-22 (>= (vector-dot s5-0 gp-0) 0.0)))
            (if (logtest? (enemy-flag drawn-mirrored) (-> self enemy-flags))
                (set! v1-22 (not v1-22))
                )
            (if v1-22
                (ja-no-eval :group! amphibian-attack-right-ja :num! (seek!) :frame-num (ja-aframe 0.0 0))
                (ja-no-eval :group! amphibian-attack-left-ja :num! (seek!) :frame-num (ja-aframe 0.0 0))
                )
            )
          )
        )
      )
    (until (>= (ja-aframe-num 0) (ja-aframe 2.0 0))
      (suspend)
      (ja :num! (seek!))
      )
    (let ((a0-22 (handle->process (-> self focus handle))))
      (if a0-22
          (set! (-> self focus-pos quad) (-> (get-trans (the-as process-focusable a0-22) 0) quad))
          )
      )
    (until (>= (ja-aframe-num 0) (ja-aframe 6.0 0))
      (seek-to-point-toward-point! (-> self root) (-> self focus-pos) 546133.3 (seconds 0.1))
      (suspend)
      (ja :num! (seek!))
      )
    (ja-no-eval :num! (seek!))
    (while (not (ja-done? 0))
      (suspend)
      (ja-eval)
      )
    (react-to-focus self)
    )
  :post nav-enemy-simple-post
  )

(defstate tongue-attack (amphibian)
  :virtual #t
  :event enemy-event-handler
  :enter (behavior ()
    ((-> (method-of-type nav-enemy hostile) enter))
    (set-time! (-> self state-time))
    (let ((v1-4 self))
      (set! (-> v1-4 enemy-flags) (the-as enemy-flag (logclear (-> v1-4 enemy-flags) (enemy-flag enemy-flag36))))
      (set! (-> v1-4 nav callback-info) *nav-enemy-null-callback-info*)
      )
    0
    (nav-enemy-method-167 self)
    (set! (-> self tongue-scale) 0.0)
    (set! (-> self tongue-mode) (the-as uint 0))
    (logior! (-> self enemy-flags) (enemy-flag lock-focus))
    (sound-play "tongue-warn")
    (let ((gp-1 (new 'stack-no-clear 'amphibian-tongue-attack-info)))
      (amphibian-method-185 self gp-1)
      (set! (-> self tongue-mod max-length) (-> gp-1 max-length))
      (set! (-> self tongue-mod target quad) (-> gp-1 clamped-pos quad))
      )
    )
  :exit (behavior ()
    (set! (-> self draw bounds w) 22528.0)
    (logclear! (-> self enemy-flags) (enemy-flag lock-focus))
    )
  :trans (behavior ()
    (let ((v1-0 (-> self tongue-mode)))
      (cond
        ((zero? v1-0)
         (when (time-elapsed? (-> self state-time) (seconds 0.8))
           (set! (-> self tongue-mode) (the-as uint 1))
           (sound-play "tongue-attack")
           )
         )
        ((= v1-0 1)
         (cond
           ((= (-> self tongue-scale) 1.0)
            (set! (-> self tongue-mode) (the-as uint 2))
            (seek! (-> self tongue-scale) 0.0 (* 7.0 (seconds-per-frame)))
            )
           (else
             (seek! (-> self tongue-scale) 1.0 (* 7.0 (seconds-per-frame)))
             )
           )
         )
        ((= v1-0 2)
         (if (= (-> self tongue-scale) 0.0)
             (set! (-> self tongue-mode) (the-as uint 3))
             (seek! (-> self tongue-scale) 0.0 (* 7.0 (seconds-per-frame)))
             )
         )
        )
      )
    (cond
      ((and (or (= (-> self tongue-mode) 1) (= (-> self tongue-mode) 2)) (!= (-> self tongue-scale) 0.0))
       (amphibian-joint-mod-method-9 (-> self tongue-mod))
       (let ((gp-1 (new 'stack-no-clear 'vector))
             (s5-1 (new 'stack-no-clear 'vector))
             )
         (amphibian-method-184 self gp-1 s5-1)
         (let ((a1-5 (new 'stack-no-clear 'vector)))
           (vector+! a1-5 (-> self draw origin) (-> self draw bounds))
           (set! (-> self draw bounds w) (fmax 22528.0 (+ 12288.0 (vector-vector-distance s5-1 a1-5))))
           )
         (if (amphibian-method-186 self gp-1 s5-1)
             (set! (-> self tongue-mode) (the-as uint 2))
             )
         )
       )
      (else
        (set! (-> self draw bounds w) 22528.0)
        )
      )
    )
  :code (behavior ()
    (ja-channel-push! 1 (seconds 0.7))
    (ja-no-eval :group! amphibian-tongue-attack-ja :num! (seek!) :frame-num 0.0)
    (until (ja-done? 0)
      (suspend)
      (ja :num! (seek!))
      )
    (react-to-focus self)
    )
  :post nav-enemy-simple-post
  )

;; WARN: Return type mismatch nav-enemy vs amphibian.
(defmethod relocate ((this amphibian) (offset int))
  (if (nonzero? (-> this tongue-mod))
      (&+! (-> this tongue-mod) offset)
      )
  (the-as amphibian ((method-of-type nav-enemy relocate) this offset))
  )

(defmethod init-enemy-collision! ((this amphibian))
  "Initializes the [[collide-shape-moving]] and any ancillary tasks to make the enemy collide properly"
  (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
                                    vehicle
                                    flut-attack
                                    board
                                    mech-punch
                                    dark-punch
                                    dark-giant
                                    )
          )
    (let ((s4-0 (new 'process 'collide-shape-prim-group s5-0 (the-as uint 5) 0)))
      (set! (-> s5-0 total-prims) (the-as uint 6))
      (set! (-> s4-0 prim-core collide-as) (collide-spec enemy))
      (set! (-> s4-0 prim-core collide-with)
            (collide-spec backgnd jak bot crate obstacle hit-by-others-list player-list)
            )
      (set! (-> s4-0 prim-core action) (collide-action solid deadly no-standon))
      (set-vector! (-> s4-0 local-sphere) 0.0 8192.0 0.0 19660.8)
      (set! (-> s5-0 root-prim) s4-0)
      )
    (let ((v1-13 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 0))))
      (set! (-> v1-13 prim-core collide-as) (collide-spec enemy))
      (set! (-> v1-13 prim-core collide-with) (collide-spec jak bot crate hit-by-others-list player-list))
      (set! (-> v1-13 prim-core action) (collide-action solid no-standon))
      (set-vector! (-> v1-13 local-sphere) 0.0 4915.2 0.0 4915.2)
      )
    (let ((v1-15 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 0))))
      (set! (-> v1-15 prim-core collide-as) (collide-spec enemy))
      (set! (-> v1-15 prim-core collide-with) (collide-spec jak bot player-list))
      (set! (-> v1-15 prim-core action) (collide-action deadly))
      (set! (-> v1-15 transform-index) 12)
      (set-vector! (-> v1-15 local-sphere) 0.0 0.0 0.0 4096.0)
      )
    (let ((v1-17 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 0))))
      (set! (-> v1-17 prim-core collide-as) (collide-spec enemy))
      (set! (-> v1-17 prim-core collide-with) (collide-spec jak bot player-list))
      (set! (-> v1-17 transform-index) 20)
      (set-vector! (-> v1-17 local-sphere) 0.0 0.0 0.0 4096.0)
      )
    (let ((v1-19 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 0))))
      (set! (-> v1-19 prim-core collide-as) (collide-spec enemy))
      (set! (-> v1-19 prim-core collide-with) (collide-spec jak bot player-list))
      (set! (-> v1-19 transform-index) 22)
      (set-vector! (-> v1-19 local-sphere) 0.0 0.0 0.0 4505.6)
      )
    (let ((v1-21 (new 'process 'collide-shape-prim-sphere s5-0 (the-as uint 0))))
      (set! (-> v1-21 prim-core collide-with) (collide-spec backgnd obstacle hit-by-others-list))
      (set! (-> v1-21 prim-core action) (collide-action solid))
      (set-vector! (-> v1-21 local-sphere) 0.0 11468.8 0.0 11468.8)
      )
    (set! (-> s5-0 nav-radius) 10240.0)
    (let ((v1-23 (-> s5-0 root-prim)))
      (set! (-> s5-0 backup-collide-as) (-> v1-23 prim-core collide-as))
      (set! (-> s5-0 backup-collide-with) (-> v1-23 prim-core collide-with))
      )
    (set! (-> s5-0 max-iteration-count) (the-as uint 3))
    (set! (-> this root) s5-0)
    )
  0
  (none)
  )

(defmethod init-enemy! ((this amphibian))
  "Common method called to initialize the enemy, typically sets up default field values and calls ancillary helper methods"
  (set! (-> this attacker-handle) (the-as handle #f))
  (initialize-skeleton
    this
    (the-as skeleton-group (art-group-get-by-name *level* "skel-amphibian" (the-as (pointer uint32) #f)))
    (the-as pair 0)
    )
  (init-enemy-behaviour-and-stats! this *amphibian-nav-enemy-info*)
  (set! (-> this tongue-mod) (new 'process 'amphibian-joint-mod this 14))
  (let ((v1-6 (-> this neck)))
    (set! (-> v1-6 up) (the-as uint 1))
    (set! (-> v1-6 nose) (the-as uint 2))
    (set! (-> v1-6 ear) (the-as uint 0))
    (set-vector! (-> v1-6 twist-max) 10012.444 10012.444 0.0 1.0)
    (set! (-> v1-6 ignore-angle) 20024.889)
    )
  (let ((v1-8 (-> this nav)))
    (set! (-> v1-8 speed-scale) 1.0)
    )
  0
  (set-gravity-length (-> this root dynam) 573440.0)
  (set! (-> this prev-ry) (quaternion-y-angle (-> this root quat)))
  (set! (-> this prev-ry1) (-> this prev-ry))
  0
  (none)
  )
