;;-*-Lisp-*-
(in-package goal)
(bundles "ENGINE.CGO" "GAME.CGO")
(require "engine/game/projectiles-h.gc")
(require "engine/common-obs/generic-obs.gc")
(require "engine/target/target.gc")
(declare-type first-person-hud process)

;; DECOMP BEGINS

(defstate target-load-wait (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('loading) (set-time! (-> self state-time)) #f)
        (else (target-standard-event-handler proc argc message block))))
  :exit target-exit
  :code
    (behavior ()
      (set! (-> self control unknown-surface00) *walk-no-turn-mods*)
      (set-time! (-> self state-time))
      (while (not (time-elapsed? (-> self state-time) (seconds 0.05)))
        (ja-channel-push! 1 (seconds 0.1))
        (ja-no-eval :group! eichar-trip-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (compute-alignment! (-> self align))
          (align! (-> self align) (align-opts adjust-xz-vel) (the-as float 1.0) (the-as float 1.0) (the-as float 1.0))
          (send-event *camera* 'joystick 0.0 0.0)
          (suspend)
          (ja :num! (seek!)))
        (suspend-for (seconds 0.3)
          (suspend)
          (ja :num! (seek! (ja-aframe (the-as float 19.0) 0) 0.05)))
        (ja-channel-push! 1 (seconds 0.3))
        (ja-no-eval :group! eichar-painful-land-ja :num! (seek!) :frame-num (ja-aframe (the-as float 40.0) 0))
        (until (ja-done? 0)
          (suspend)
          (ja :num! (seek!)))
        (ja-no-eval :group! eichar-painful-land-end-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (suspend)
          (ja :num! (seek!))))
      (go target-stance))
  :post target-no-stick-post)

(defstate target-stance-ambient (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('movie) (go target-stance))
        (else (target-standard-event-handler proc argc message block))))
  :enter
    (behavior ()
      (set! (-> self neck flex-blend) 0.0)
      ((-> target-stance enter))
      (let ((v1-2 (rand-vu-int-count 4)))
        (cond
          ((zero? v1-2)
           (set! (-> self control unknown-uint20)
                 (the-as uint (new 'static 'spool-anim :name "eichar-ambient-1" :index #xe7 :parts 1 :command-list '()))))
          ((= v1-2 1)
           (set! (-> self control unknown-uint20)
                 (the-as uint (new 'static 'spool-anim :name "eichar-ambient-2" :index #xe8 :parts 1 :command-list '()))))
          ((= v1-2 2)
           (set! (-> self control unknown-uint20)
                 (the-as uint (new 'static 'spool-anim :name "eichar-ambient-3" :index #xe9 :parts 1 :command-list '()))))
          (else
           (set! (-> self control unknown-uint20)
                 (the-as uint (new 'static 'spool-anim :name "eichar-ambient-4" :index #xea :parts 1 :command-list '()))))))
      (set-time! (-> self state-time)))
  :exit
    (behavior ()
      (let ((a0-0 (-> self control unknown-spoolanim00)))
        (when a0-0
          (ja-abort-spooled-anim a0-0 (the-as art-joint-anim #f) -1)
          (ja-channel-set! 1)
          (ja :group! eichar-stance-loop-ja :num! min)))
      ((-> target-stance exit))
      (target-exit))
  :trans
    (behavior ()
      (spool-push *art-control* (-> self control unknown-spoolanim00 name) 0 self (the-as float -99.0))
      (if (or (cpad-hold? (-> self control unknown-cpad-info00 number) start l1 r1 triangle circle x square) *progress-process*)
        (go target-stance)))
  :code
    (behavior ()
      (while (let ((v1-13 (file-status *art-control* (-> self control unknown-spoolanim00 name) 0)))
               (not (or (= v1-13 'locked) (= v1-13 'active))))
        (suspend)
        (ja :num! (loop!))
        (ja :chan 1 :num! (chan 0))
        (ja :chan 2 :num! (chan 0)))
      (ja-play-spooled-anim (-> self control unknown-spoolanim00)
                            (the-as art-joint-anim eichar-stance-loop-ja)
                            (the-as art-joint-anim eichar-stance-loop-ja)
                            (the-as (function process-drawable symbol) (lambda () (!= (-> *cpad-list* cpads 0 stick0-speed) 0.0))))
      (set! (-> self control unknown-uint20) (the-as uint #f))
      (go target-stance))
  :post target-post)

(deftype first-person-hud (process)
  ((max-nb-of-particles int32)
   (nb-of-particles     int32)
   (particles           hud-particle 3)
   (in-out-position     int32)
   (sides-x-scale       float)
   (sides-y-scale       float)
   (x-offset            int32))
  (:methods
   (spawn-particles! (_type_) none))
  (:states
   hud-coming-in
   hud-going-out
   hud-normal
   hud-waiting))


(define *fp-hud-stack* (malloc 'global #x3800))

(defmethod deactivate ((this first-person-hud))
  (dotimes (s5-0 (-> this nb-of-particles))
    (kill-and-free-particles (-> this particles s5-0 part))
    (set! (-> this particles s5-0 part matrix) -1))
  (enable-hud)
  (set! (-> *target* fp-hud) (the-as handle #f))
  (call-parent-method this)
  (none))

(defbehavior first-person-hud-init-by-other first-person-hud ()
  (logclear! (-> self mask) (process-mask pause))
  (set! (-> self nb-of-particles) 0)
  (set! (-> self max-nb-of-particles) 3)
  (set! (-> self in-out-position) 4096)
  (when (< (-> self nb-of-particles) (-> self max-nb-of-particles))
    (let ((gp-0 (-> self nb-of-particles)))
      (set! (-> self particles gp-0) (new 'static 'hud-particle))
      (set! (-> self particles gp-0 part) (create-launch-control (-> *part-group-id-table* 611) self))
      (set! (-> self particles gp-0 init-pos x) -320.0)
      (set! (-> self particles gp-0 init-pos y) 254.0)
      (set! (-> self particles gp-0 init-pos z) 15.0)
      (set! (-> self particles gp-0 part matrix) -1))
    (+! (-> self nb-of-particles) 1))
  (when (< (-> self nb-of-particles) (-> self max-nb-of-particles))
    (let ((gp-1 (-> self nb-of-particles)))
      (set! (-> self particles gp-1) (new 'static 'hud-particle))
      (set! (-> self particles gp-1 part) (create-launch-control (-> *part-group-id-table* 612) self))
      (set! (-> self particles gp-1 init-pos x) -320.0)
      (set! (-> self particles gp-1 init-pos y) 192.0)
      (set! (-> self particles gp-1 init-pos z) 15.0)
      (set! (-> self particles gp-1 part matrix) -1))
    (+! (-> self nb-of-particles) 1))
  (when (< (-> self nb-of-particles) (-> self max-nb-of-particles))
    (let ((gp-2 (-> self nb-of-particles)))
      (set! (-> self particles gp-2) (new 'static 'hud-particle))
      (set! (-> self particles gp-2 part) (create-launch-control (-> *part-group-id-table* 613) self))
      (set! (-> self particles gp-2 init-pos x) 256.0)
      (set! (-> self particles gp-2 init-pos y) 244.0)
      (set! (-> self particles gp-2 init-pos z) 15.0)
      (set! (-> self particles gp-2 part matrix) -1))
    (+! (-> self nb-of-particles) 1))
  (case (get-aspect-ratio)
    (('aspect4x3) (set! (-> self sides-x-scale) 3.5) (set! (-> self sides-y-scale) 13.0) (set! (-> self x-offset) 0) 0)
    (('aspect16x9) (set! (-> self sides-x-scale) 2.8) (set! (-> self sides-y-scale) 9.75) (set! (-> self x-offset) 12)))
  (set! (-> self event-hook) (-> hud-waiting event))
  (go hud-waiting)
  (none))

(defmethod relocate ((this first-person-hud) (offset int))
  (dotimes (v1-0 (-> this nb-of-particles))
    (when (-> this particles v1-0 part)
      (if (nonzero? (-> this particles v1-0 part)) (&+! (-> this particles v1-0 part) offset))))
  (the-as first-person-hud ((method-of-type process relocate) this offset)))

(defmethod spawn-particles! ((this first-person-hud))
  (dotimes (s5-0 (-> this nb-of-particles))
    (set! (-> this particles s5-0 pos x) (+ -256.0 (-> this particles s5-0 init-pos x)))
    (set! (-> this particles s5-0 pos y)
          (* 0.5
             (- (* (-> this particles s5-0 init-pos y) (-> *video-parms* relative-y-scale)) (the float (-> *video-parms* screen-sy)))))
    (set! (-> this particles s5-0 pos z) (-> this particles s5-0 init-pos z))
    (if (> (-> this particles s5-0 part matrix) 0)
      (set-vector! (sprite-get-user-hvdf (-> this particles s5-0 part matrix))
                   (the float (+ (the int (-> this particles s5-0 pos x)) 2048))
                   (the float (+ (the int (-> this particles s5-0 pos y)) 2048))
                   (- (-> *math-camera* hvdf-off z) (* 1024.0 (-> this particles s5-0 pos z)))
                   (-> *math-camera* hvdf-off w)))
    ;; og:preserve-this Positioning of first person hud sprites
    (when (or (-> *pc-settings* use-vis?) (= s5-0 2))
      (spawn (-> this particles s5-0 part) *null-vector*)))
  0
  (none))

(defstate hud-waiting (first-person-hud)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('go-away) (go hud-going-out))))
  :enter
    (behavior ()
      (disable-hud (the-as int (-> *hud-parts* power))))
  :code
    (behavior ()
      (loop
        (dotimes (gp-0 (-> self nb-of-particles))
          (if (= (-> self particles gp-0 part matrix) -1) (set! (-> self particles gp-0 part matrix) (sprite-allocate-user-hvdf))))
        (set-setting! 'common-page 'set 0.0 1)
        (suspend)
        (go hud-coming-in)
        (suspend))))

(defstate hud-coming-in (first-person-hud)
  :event
    (-> hud-waiting
        event)
  :code
    (behavior ()
      (loop
        (seekl! (-> self in-out-position) 0 (the int (* 350.0 (-> *display* time-adjust-ratio))))
        (if (zero? (-> self in-out-position)) (go hud-normal))
        (suspend)))
  :post
    (behavior ()
      (spawn-particles! self)))

(defstate hud-normal (first-person-hud)
  :event
    (-> hud-waiting
        event)
  :code
    (behavior ()
      (loop
        (if (or (not *progress-process*)
                (= (-> *progress-process* 0 next-state name) 'progress-going-out)
                (= (-> *progress-process* 0 next-state name) 'progress-gone))
          (seekl! (-> self in-out-position) 0 (the int (* 150.0 (-> *display* time-adjust-ratio))))
          (seekl! (-> self in-out-position) 4096 (the int (* 200.0 (-> *display* time-adjust-ratio)))))
        (suspend))))

(defstate hud-going-out (first-person-hud)
  :code
    (behavior ()
      (loop
        (seekl! (-> self in-out-position) 4096 (the int (* 350.0 (-> *display* time-adjust-ratio))))
        (if (= (-> self in-out-position) 4096) (deactivate self))
        (suspend)))
  :post
    (behavior ()
      (spawn-particles! self)))

(defun part-first-person-hud-left-func ((arg0 sparticle-system) (arg1 sparticle-cpuinfo) (arg2 matrix))
  (let ((s5-0 (handle->process (-> *target* fp-hud))))
    (when s5-0
      (let ((f30-0 (* 0.00024414062 (the float (-> (the-as first-person-hud s5-0) in-out-position)))))
        (if (or (-> *setting-control* current movie) (movie?)) (set! f30-0 1.0))
        (if (< 0.25 f30-0) (set! f30-0 1.0) (* 4.0 f30-0))
        (set! (-> (the-as first-person-hud s5-0) particles 0 init-pos x)
              (the float (- 59 (-> (the-as first-person-hud s5-0) x-offset))))
        (set! (-> arg2 vector 0 w) (* 4096.0 (+ (-> (the-as first-person-hud s5-0) sides-x-scale) (* 10.0 f30-0))))
        (set! (-> arg2 vector 1 w) (* 4096.0 (+ (-> (the-as first-person-hud s5-0) sides-y-scale) (* 10.0 f30-0)))))))
  0
  (none))

(defun part-first-person-hud-right-func ((arg0 sparticle-system) (arg1 sparticle-cpuinfo) (arg2 matrix))
  (let ((s5-0 (handle->process (-> *target* fp-hud))))
    (when s5-0
      (let ((f30-0 (* 0.00024414062 (the float (-> (the-as first-person-hud s5-0) in-out-position)))))
        (if (or (-> *setting-control* current movie) (movie?)) (set! f30-0 1.0))
        (if (< 0.25 f30-0) (set! f30-0 1.0) (* 4.0 f30-0))
        (set! (-> (the-as first-person-hud s5-0) particles 1 init-pos x)
              (the float (+ (-> (the-as first-person-hud s5-0) x-offset) 452)))
        (set! (-> arg2 vector 0 w) (* 4096.0 (+ (-> (the-as first-person-hud s5-0) sides-x-scale) (* 10.0 f30-0))))
        (set! (-> arg2 vector 1 w) (* 4096.0 (+ (-> (the-as first-person-hud s5-0) sides-y-scale) (* 10.0 f30-0)))))))
  0
  (none))

(defun part-first-person-hud-selector-func ((arg0 sparticle-system) (arg1 sparticle-cpuinfo) (arg2 matrix))
  (let ((v1-2 (handle->process (-> *target* fp-hud))))
    (when v1-2
      (let ((f30-0 (* 0.00024414062 (the float (-> (the-as first-person-hud v1-2) in-out-position)))))
        (if (or (-> *setting-control* current movie) (movie?)) (set! f30-0 1.0))
        (if (< 0.5 f30-0) (set! f30-0 1.0) (* 2.0 f30-0))
        (set! (-> arg2 vector 2 w) (- 64.0 (* 64.0 f30-0))))))
  0
  (none))

;; ERROR: function was not converted to expressions. Cannot decompile.

(defstate target-stance-look-around (target)
  :event target-standard-event-handler
  :enter
    (-> target-stance
        enter)
  :exit
    (-> target-stance
        exit)
  :trans
    (-> target-stance
        trans)
  :code
    (behavior ()
      (while (let ((a1-0 (new 'stack-no-clear 'event-message-block)))
               (set! (-> a1-0 from) self)
               (set! (-> a1-0 num-params) 0)
               (set! (-> a1-0 message) 'dist-from-interp-src)
               (and (< (send-event-function *camera* a1-0) 4915.2)
                    (not (time-elapsed? (-> self state-time) (seconds 0.07)))
                    (zero? (ja-group-size))))
        (suspend))
      (let ((v1-8 target-stance)) (set! (-> self next-state) v1-8) (set! (-> self state) v1-8))
      ((the-as (function none :behavior target) (-> target-stance code))))
  :post target-post)

(defstate target-look-around (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (cond
        ((and (= message 'query) (= (-> block param 0) 'mode)) (-> self state name))
        ((let ((v1-4 message)) (= v1-4 'end-mode)) (go target-stance-look-around))
        ((-> self control unknown-symbol30) (target-dangerous-event-handler proc argc message block))
        (else (target-standard-event-handler proc argc message block))))
  :enter
    (behavior ()
      (set! (-> self cam-user-mode) 'look-around)
      (set! (-> self control unknown-surface00) *duck-mods*)
      (logior! (-> self state-flags) (state-flags first-person-mode))
      (send-event *camera* 'blend-from-as-fixed)
      (send-event *camera* 'no-intro)
      (camera-change-to (the-as string 'cam-eye) 60 #f)
      (let ((a0-5 (handle->process (-> self fp-hud)))) (if a0-5 (deactivate a0-5)))
      (set! (-> self fp-hud)
            (ppointer->handle (process-spawn first-person-hud :to *dproc* :stack (&+ *fp-hud-stack* #x3800)))))
  :exit
    (behavior ()
      (let ((a0-1 (handle->process (-> self fp-hud)))) (if a0-1 (send-event a0-1 'go-away)))
      (set! (-> self cam-user-mode) 'normal)
      (target-exit)
      (when (send-event *camera* 'query-state cam-eye)
        (send-event *camera* 'no-intro)
        (send-event *camera* 'force-blend (seconds 0.2))
        (send-event *camera* 'clear-entity)
        (camera-change-to (the-as string 'base) 60 #f)))
  :trans
    (behavior ()
      (local-vars (sv-48 vector))
      (rlet ((vf0 :class vf)
             (vf4 :class vf)
             (vf5 :class vf)
             (vf6 :class vf))
        (init-vf0-vector)
        ;; og:preserve-this - High FPS Fix
        (when (and (recently-pressed? r2 circle square)
                   (and (= (-> self fact eco-type) (pickup-type eco-yellow)) (>= (-> self fact eco-level) 1.0))
                   (time-elapsed? (-> self control unknown-dword82) (seconds 0.5))
                   (not *pause-lock*))
          (let ((gp-1 (vector-float*! (new-stack-vector0)
                                      (-> *math-camera* inv-camera-rot vector 2)
                                      (the-as float (-> *TARGET-bank* yellow-projectile-speed))))
                (s5-1 (vector-float*! (new-stack-vector0) (-> *math-camera* inv-camera-rot vector 2) 8192.0)))
            (vector+float*! s5-1 s5-1 (-> *math-camera* inv-camera-rot vector 1) (the-as float -2048.0))
            (let ((s4-0 (get-process *default-dead-pool* projectile-yellow #x4000)))
              (when s4-0
                (let ((t9-2 (method-of-type projectile-yellow activate)))
                  (t9-2 (the-as projectile-yellow s4-0) self 'projectile-yellow (the-as pointer #x70004000)))
                (let ((s3-0 run-function-in-process)
                      (s2-0 s4-0)
                      (s1-0 projectile-init-by-other)
                      (s0-0 (-> self entity)))
                  (set! sv-48 s5-1)
                  (let ((v0-3 (camera-pos))) (.mov.vf.w vf6 vf0) (.lvf vf4 (&-> v0-3 quad)))
                  (.lvf vf5 (&-> s5-1 quad))
                  (.add.vf.xyz vf6 vf4 vf5)
                  (.svf (&-> sv-48 quad) vf6)
                  (let ((t1-0 (if (>= (-> self fact eco-level) (-> *FACT-bank* eco-level-max)) 56 40))
                        (t2-0 #f))
                    ((the-as (function object object object object object object object none) s3-0) s2-0 s1-0 s0-0 sv-48 gp-1 t1-0 t2-0)))
                (-> s4-0 ppointer))))
          (set-time! (-> self control unknown-dword82)))
        (when (cpad-pressed? (-> self control unknown-cpad-info00 number) triangle)
          (logclear! (-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) button0-abs 0) (pad-buttons triangle))
          (logclear! (-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) button0-rel 0) (pad-buttons triangle))
          (set! (-> self cam-user-mode) 'normal))))
  :code
    (behavior ()
      (while (let ((f30-0 8192.0)) (< f30-0 (send-event *camera* 'dist-from-interp-dest)))
        (if (!= (-> self cam-user-mode) 'look-around) (go target-stance))
        (suspend))
      (ja-channel-set! 0)
      (set! (-> self control transv quad) (the-as uint128 0))
      (loop
        (if (!= (-> self cam-user-mode) 'look-around) (go target-stance-look-around))
        (suspend)))
  :post target-no-move-post)

(defstate target-billy-game (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (cond
        ((and (= message 'query) (= (-> block param 0) 'mode)) (-> self state name))
        ((let ((v1-4 message)) (= v1-4 'end-mode)) (go target-stance))
        (else (target-standard-event-handler proc argc message block))))
  :enter
    (behavior ()
      (set! (-> self neck flex-blend) 0.0)
      (set! (-> self control unknown-surface00) *duck-mods*)
      (logior! (-> self state-flags) (state-flags first-person-mode))
      (send-event *camera* 'blend-from-as-fixed)
      (send-event *camera* 'clear-entity)
      (send-event *camera* 'no-intro)
      (camera-change-to (the-as string 'cam-billy) 0 #f)
      (let ((a0-6 (handle->process (-> self fp-hud)))) (if a0-6 (deactivate a0-6)))
      (set! (-> self fp-hud)
            (ppointer->handle (process-spawn first-person-hud :to *dproc* :stack (&+ *fp-hud-stack* #x3800)))))
  :exit
    (behavior ()
      (let ((a0-1 (handle->process (-> self fp-hud)))) (if a0-1 (send-event a0-1 'go-away)))
      (when (send-event *camera* 'query-state cam-billy)
        (send-event *camera* 'no-intro)
        (send-event *camera* 'force-blend 0)
        (camera-change-to (the-as string 'base) 0 #f))
      (target-exit))
  :trans
    (behavior ()
      (local-vars (sv-48 vector))
      (rlet ((vf0 :class vf)
             (vf4 :class vf)
             (vf5 :class vf)
             (vf6 :class vf))
        (init-vf0-vector)
        ;; og:preserve-this - High FPS Fix
        (when (and (recently-pressed? r2 circle square)
                   (time-elapsed? (-> self control unknown-dword82) (seconds 0.45))
                   (and (= (-> self fact eco-type) (pickup-type eco-yellow)) (>= (-> self fact eco-level) 1.0))
                   (not *pause-lock*))
          (let ((gp-1 (vector-float*! (new-stack-vector0)
                                      (-> *math-camera* inv-camera-rot vector 2)
                                      (the-as float (-> *TARGET-bank* yellow-projectile-speed))))
                (s5-1 (vector-float*! (new-stack-vector0) (-> *math-camera* inv-camera-rot vector 2) 8192.0)))
            (vector+float*! s5-1 s5-1 (-> *math-camera* inv-camera-rot vector 1) (the-as float -2048.0))
            (let ((s4-0 (get-process *default-dead-pool* projectile-yellow #x4000)))
              (when s4-0
                (let ((t9-2 (method-of-type projectile-yellow activate)))
                  (t9-2 (the-as projectile-yellow s4-0) self 'projectile-yellow (the-as pointer #x70004000)))
                (let ((s3-0 run-function-in-process)
                      (s2-0 s4-0)
                      (s1-0 projectile-init-by-other)
                      (s0-0 (-> self entity)))
                  (set! sv-48 s5-1)
                  (let ((v0-4 (camera-pos))) (.mov.vf.w vf6 vf0) (.lvf vf4 (&-> v0-4 quad)))
                  (.lvf vf5 (&-> s5-1 quad))
                  (.add.vf.xyz vf6 vf4 vf5)
                  (.svf (&-> sv-48 quad) vf6)
                  (let ((t1-0 (if (>= (-> self fact eco-level) (-> *FACT-bank* eco-level-max)) 120 104))
                        (t2-0 #f))
                    ((the-as (function object object object object object object object none) s3-0) s2-0 s1-0 s0-0 sv-48 gp-1 t1-0 t2-0)))
                (-> s4-0 ppointer))))
          (set-time! (-> self control unknown-dword82)))))
  :code
    (behavior ()
      (ja-channel-set! 0)
      (set! (-> self control transv quad) (the-as uint128 0))
      (anim-loop))
  :post target-no-move-post)

(defstate target-grab (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (cond
        ((and (= message 'query) (= (-> block param 0) 'mode)) (-> self state name))
        (else
         (case message
           (('end-mode) (go target-stance))
           (('play-anim)
            (let ((v0-0 (the-as object (-> block param 0)))) (set! (-> self control unknown-uint20) (the-as uint v0-0)) v0-0))
           (('clone-anim) (go target-clone-anim (process->handle (the-as process (-> block param 0)))))
           (('change-mode)
            (case (-> block param 0)
              (('final-door)
               (go target-final-door
                   (the-as basic (process->handle (the-as process (-> block param 1))))
                   (process->handle (the-as process (-> block param 2)))))))
           (else (target-generic-event-handler proc argc message block))))))
  :enter
    (behavior ()
      (set! (-> self control unknown-surface00) *grab-mods*)
      (set! (-> self neck flex-blend) 0.0)
      (logior! (-> self state-flags) (state-flags invulnerable grabbed))
      (set! (-> self control unknown-uint20) (the-as uint 'stance)))
  :exit
    (behavior ()
      (logclear! (-> self state-flags) (state-flags invulnerable))
      (target-exit))
  :code
    (behavior ()
      (set-forward-vel (the-as float 0.0))
      (let ((gp-0 0))
        (while (not (logtest? (-> self control status) (cshape-moving-flags onsurf)))
          (target-falling-anim-trans)
          (+! gp-0 (- (current-time) (-> *display* old-base-frame-counter)))
          (suspend))
        (if (or (> gp-0 0)
                (let ((v1-11 (ja-group)))
                  (or (= v1-11 eichar-jump-ja)
                      (= v1-11 eichar-jump-loop-ja)
                      (= v1-11 eichar-launch-jump-ja)
                      (= v1-11 eichar-launch-jump-loop-ja)
                      (= v1-11 eichar-duck-high-jump-ja))))
          (target-hit-ground-anim #f)))
      (-> self control unknown-spoolanim00)
      (loop
        (let ((gp-1 (-> self control unknown-spoolanim00)))
          (case gp-1
            (('stance)
             (cond
               ((or (and (ja-group? eichar-walk-ja) (< 0.5 (-> self skel root-channel 6 frame-interp)))
                    (let ((v1-32 (ja-group)))
                      (or (= v1-32 eichar-run-squash-ja)
                          (= v1-32 eichar-run-squash-weak-ja)
                          (= v1-32 eichar-attack-from-stance-run-end-ja)
                          (= v1-32 eichar-attack-from-stance-run-alt-end-ja))))
                (ja-channel-push! 1 (seconds 0.15))
                (ja-no-eval :group! eichar-run-to-stance-loop-ja :num! (seek!) :frame-num 0.0)
                (until (ja-done? 0)
                  (suspend)
                  (ja :num! (seek!)))
                (ja-no-eval :group! eichar-run-to-stance-ja :num! (seek!) :frame-num 0.0)
                (until (ja-done? 0)
                  (suspend)
                  (ja :num! (seek!)))
                (ja-channel-push! 1 (seconds 0.15)))
               ((let ((v1-87 (ja-group)))
                  (and (or (= v1-87 eichar-jump-short-land-ja) (= v1-87 eichar-jump-land-ja)) (not (ja-max? 0))))
                (ja-no-eval :num! (seek!))
                (while (not (ja-done? 0))
                  (suspend)
                  (ja-eval))
                (ja-channel-push! 1 (seconds 0.075)))
               ((not (and (ja-group? eichar-stance-loop-ja) (= (ja-group-size) 1))) (ja-channel-push! 1 (seconds 0.075))))
             (loop
               (ja-no-eval :group! eichar-stance-loop-ja :num! (seek!) :frame-num 0.0)
               (until (ja-done? 0)
                 (if (!= gp-1 (-> self control unknown-spoolanim00)) (goto cfg-94))
                 (suspend)
                 (ja :num! (seek!)))))
            (('shock-in)
             (ja-channel-push! 1 (seconds 0.2))
             (ja-no-eval :group! eichar-shocked-ja :num! (seek! (ja-aframe (the-as float 18.0) 0)) :frame-num 0.0)
             (until (ja-done? 0)
               (if (!= gp-1 (-> self control unknown-spoolanim00)) (goto cfg-94))
               (suspend)
               (ja :num! (seek! (ja-aframe (the-as float 18.0) 0))))
             (loop
               (if (!= gp-1 (-> self control unknown-spoolanim00)) (goto cfg-94))
               (suspend)))
            (('shock-out)
             (if (not (ja-group? eichar-shocked-ja)) (ja-channel-push! 1 (seconds 0.2)))
             (ja-no-eval :group! eichar-shocked-ja :num! (seek!) :frame-num (ja-aframe (the-as float 18.0) 0))
             (until (ja-done? 0)
               (if (!= gp-1 (-> self control unknown-spoolanim00)) (goto cfg-94))
               (suspend)
               (ja :num! (seek!)))
             (set! (-> self control unknown-uint20) (the-as uint 'stance)))))
        (label cfg-94)))
  :post
    (behavior ()
      (if (logtest? (-> self control status) (cshape-moving-flags onsurf))
        (set! (-> self control transv quad) (the-as uint128 0)))
      (target-no-stick-post)))

(defstate target-pole-cycle (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (if (and (= message 'query) (= (-> block param 0) 'mode))
        (-> self state name)
        (target-standard-event-handler proc argc message block)))
  :enter
    (behavior ((arg0 handle))
      (set! (-> self control unknown-handle10) arg0)
      (set-time! (-> self state-time))
      (set! (-> self control unknown-surface00) *pole-mods*)
      (logior! (-> self control root-prim prim-core action) (collide-action swingpole-active))
      (target-collide-set! 'pole (the-as float 0.0))
      (set! (-> self control unknown-vector102 quad) (-> self control transv quad))
      (set! (-> self control transv quad) (the-as uint128 0))
      (send-event *camera* 'ease-in)
      (set! (-> self control unknown-int21) (the-as int #f)))
  :exit
    (behavior ()
      (target-collide-set! 'normal (the-as float 0.0))
      (logclear! (-> self control root-prim prim-core action) (collide-action swingpole-active))
      (set! (-> self control unknown-handle10) (the-as handle #f)))
  :trans
    (behavior ()
      ;; og:preserve-this - High FPS Fix
      (when (and (recently-pressed? x)
                 (not (logtest? (-> self state-flags) (state-flags prevent-jump)))
                 (time-elapsed? (-> self state-time) (seconds 0.1)))
        (set! (-> self control transv quad) (the-as uint128 0))
        (cond
          ((< 44.0 (ja-aframe-num 0))
           (set-forward-vel (the-as float -49152.0))
           (let ((gp-0 (new-stack-vector0)))
             (let ((f0-2 (vector-dot (-> self control dynam gravity-normal) (-> self control transv))))
               0.0
               (vector-! gp-0 (-> self control transv) (vector-float*! gp-0 (-> self control dynam gravity-normal) f0-2)))
             (let* ((f0-3 (vector-length gp-0))
                    (f1-1 f0-3)
                    (f2-0 -81920.0))
               (vector+! (-> self control transv)
                         (vector-float*! (-> self control transv) (-> self control dynam gravity-normal) f2-0)
                         (vector-float*! gp-0 gp-0 (/ f0-3 f1-1)))))
           (logclear! (-> self control status) (cshape-moving-flags onsurf onground tsurf))
           (go target-falling 'target-pole-cycle))
          ((>= (ja-aframe-num 0) 14.0)
           (remove-exit)
           (go target-pole-flip-up 28672.0 28672.0 (* 1024.0 (- 26.0 (ja-aframe-num 0)))))
          (else (remove-exit) (go target-pole-flip-forward (the-as float 14336.0) (the-as float 14336.0) (the-as float 57344.0))))))
  :code
    (behavior ((arg0 handle))
      (target-compute-pole)
      (set! (-> self control unknown-uint20)
            (the-as uint
                    (vector-dot (-> self control unknown-vector100)
                                (vector-normalize! (-> self control unknown-vector102) (the-as float 1.0)))))
      (cond
        ((ja-group? eichar-pole-jump-loop-ja)
         (while (not (-> self control unknown-int21))
           (ja :num! (seek!))
           (suspend))
         (ja :num-func num-func-identity :frame-num (ja-aframe (the-as float 37.0) 0)))
        (else (while (not (-> self control unknown-int21)) (suspend)) (suspend) (ja-channel-push! 1 (seconds 0.15))))
      (ja-no-eval :group! eichar-pole-cycle-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!)))
      (loop
        (set! (-> self anim-seed) (the-as uint (if (rand-vu-percent? (the-as float 0.1)) 0 1)))
        (ja-no-eval :group! eichar-pole-cycle-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (suspend)
          (ja :num! (seek!)))))
  :post target-no-move-post)

(defstate target-pole-flip-up (target)
  :event target-standard-event-handler
  :exit
    (-> target-pole-cycle
        exit)
  :code
    (behavior ((arg0 object) (arg1 object) (arg2 float))
      (ja-no-eval :group! eichar-pole-flip-up-ja :num! (seek!) :frame-num (ja-aframe (+ 1.0 (fmin 17.0 (ja-aframe-num 0))) 0))
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!)))
      (set-forward-vel arg2)
      (go target-pole-flip-up-jump (the-as float arg0) (the-as float arg1)))
  :post target-no-move-post)

(defstate target-pole-flip-up-jump (target)
  :event target-standard-event-handler
  :enter
    (-> target-jump-forward
        enter)
  :exit target-exit
  :trans
    (behavior ()
      ((-> target-jump-forward trans))
      (vector-flatten! (-> self control transv) (-> self control transv) (-> self control unknown-vector100)))
  :code
    (behavior ((arg0 float) (arg1 float))
      (sound-play "jump")
      (send-event *camera* 'damp-up)
      (ja :group! eichar-pole-jump-loop-ja :num! min)
      (let ((f0-1 (target-height-above-ground))
            (f1-1 (vector-dot (-> self control dynam gravity-normal) (-> self control transv))))
        (while (not (and (< (fabs (/ f0-1 (/ f1-1 300))) 40.0) (and (< f1-1 0.0) (ja-min? 0))))
          (suspend)
          (ja :num! (loop!))
          (set! f0-1 (target-height-above-ground))
          (set! f1-1 (vector-dot (-> self control dynam gravity-normal) (-> self control transv)))))
      (ja-channel-push! 1 (seconds 0.25))
      (ja-no-eval :group! eichar-jump-loop-ja :num! (loop!) :frame-num 0.0)
      (loop
        (suspend)
        (ja :group! eichar-jump-loop-ja :num! (loop!))))
  :post target-post)

(defstate target-pole-flip-forward (target)
  :event target-standard-event-handler
  :exit
    (-> target-pole-cycle
        exit)
  :code
    (behavior ((arg0 float) (arg1 float) (arg2 float))
      (ja-no-eval :group!
                  eichar-pole-flip-forward-ja
                  :num!
                  (seek! (ja-aframe (the-as float 16.0) 0))
                  :frame-num
                  (ja-aframe (+ 1.0 (ja-aframe-num 0)) 0))
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek! (ja-aframe (the-as float 16.0) 0))))
      (set-forward-vel arg2)
      (go target-pole-flip-forward-jump arg0 arg1))
  :post target-no-move-post)

(defstate target-pole-flip-forward-jump (target)
  :event target-standard-event-handler
  :enter
    (behavior ((arg0 float) (arg1 float))
      ((-> target-jump enter) arg0 arg1 (the-as surface #f))
      (set! (-> self control unknown-surface00) *forward-pole-jump-mods*))
  :exit target-exit
  :trans
    (behavior ()
      ((-> target-jump-forward trans))
      (vector-flatten! (-> self control transv) (-> self control transv) (-> self control unknown-vector100)))
  :code
    (behavior ((arg0 float) (arg1 float))
      (sound-play "jump")
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!)))
      ((the-as (function none :behavior target) (-> target-pole-flip-up-jump code))))
  :post target-post)

(defstate target-edge-grab (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('end-mode) (go target-falling 'target-edge-grab))
        (else (target-standard-event-handler proc argc message block))))
  :enter
    (behavior ()
      (set-time! (-> self state-time))
      (set! (-> self control unknown-surface00) *edge-grab-mods*)
      (set-time! (-> self control unknown-dword41))
      (logior! (-> self control root-prim prim-core action) (collide-action edgegrab-active edgegrab-cam))
      (set! (-> self control unknown-vector102 quad) (-> self control transv quad))
      (set! (-> self control transv quad) (the-as uint128 0))
      (send-event *camera* 'ease-in))
  :exit
    (behavior ()
      (when (logtest? (-> self control root-prim prim-core action) (collide-action edgegrab-cam))
        (logclear! (-> self control root-prim prim-core action) (collide-action edgegrab-active edgegrab-cam))
        (send-event *camera* 'damp-up)))
  :trans
    (behavior ()
      (when (and (time-elapsed? (-> self state-time) (seconds 0.2))
                 ;; og:preserve-this - High FPS Fix
                 (recently-pressed? x)
                 (not (logtest? (-> self state-flags) (state-flags prevent-jump))))
        (cond
          ((or (< -0.2 (local-pad-angle)) (= (-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) stick0-speed) 0.0))
           (let ((a1-2 (new 'stack-no-clear 'collide-using-spheres-params)))
             (set! (-> a1-2 spheres) (-> *collide-edge-work* world-player-leap-up-spheres))
             (set! (-> a1-2 num-spheres) (the-as uint 6))
             (set! (-> a1-2 collide-with) (-> self control root-prim collide-with))
             (set! (-> a1-2 proc) #f)
             (set! (-> a1-2 ignore-pat) (new 'static 'pat-surface :noentity #x1))
             (set! (-> a1-2 solid-only) #t)
             (when (not (fill-and-probe-using-spheres *collide-cache* a1-2))
               (remove-exit)
               (go target-edge-grab-jump (-> *TARGET-bank* edge-grab-jump-height-min) (-> *TARGET-bank* edge-grab-jump-height-max)))))
          (else (remove-exit) (go target-edge-grab-off)))))
  :code
    (behavior ()
      (target-compute-edge)
      (set! (-> self control unknown-uint20)
            (the-as uint
                    (vector-dot (-> self control unknown-vector100)
                                (vector-normalize! (-> self control unknown-vector102) (the-as float 1.0)))))
      (while (< 0.0 (-> self control unknown-float110))
        (when (not (ja-group? eichar-jump-loop-ja))
          (ja-channel-push! 1 (seconds 0.15))
          (ja :group! eichar-jump-loop-ja :num! min))
        (suspend))
      (ja-channel-push! 1 (seconds 0.15))
      (cond
        ((< (the-as float (-> self control unknown-uint20)) -0.3) (ja :group! eichar-edge-grab-swing-right-ja :num! min))
        ((< 0.3 (the-as float (-> self control unknown-uint20))) (ja :group! eichar-edge-grab-swing-left-ja :num! min))
        (else (ja :group! eichar-falling-to-edge-grab-ja :num! min)))
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!)))
      (ja-channel-set! 1)
      (loop
        (ja-no-eval :group! eichar-edge-grab-stance0-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (suspend)
          (ja :num! (seek!)))
        (+! (-> self anim-seed) 1)
        (ja-no-eval :group! eichar-edge-grab-stance1-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (suspend)
          (ja :num! (seek!)))))
  :post target-no-move-post)

(defstate target-edge-grab-jump (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('end-mode) (go target-falling 'target-edge-grab))
        (else (target-standard-event-handler proc argc message block))))
  :exit
    (-> target-edge-grab
        exit)
  :code
    (behavior ((arg0 float) (arg1 float))
      (ja-channel-set! 1)
      (set-quaternion! (-> self control) (-> self control dir-targ))
      (logclear! (-> self control root-prim prim-core action) (collide-action edgegrab-active edgegrab-cam))
      (set! (-> self control transv quad) (the-as uint128 0))
      (let ((s4-0 (new 'stack-no-clear 'vector)))
        (ja-no-eval :group! eichar-edge-grab-to-jump-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (target-compute-edge-rider)
          (compute-alignment! (-> self align))
          (when (not (logtest? (-> self align flags) (align-flags disabled)))
            (vector-matrix*! s4-0 (the-as vector (-> self align delta)) (-> self control unknown-matrix01))
            (move-by-vector! (-> self control) s4-0))
          (suspend)
          (ja :num! (seek!))))
      (set! (-> self control transv quad) (the-as uint128 0))
      (set! (-> self control unknown-dword70) 0)
      (set-forward-vel (the-as float 16384.0))
      (send-event *camera* 'damp-up)
      (go target-jump-forward arg0 arg1))
  :post target-no-move-post)

(defstate target-edge-grab-off (target)
  :event target-standard-event-handler
  :exit
    (-> target-edge-grab
        exit)
  :code
    (behavior ()
      (ja-channel-set! 1)
      (set-quaternion! (-> self control) (-> self control dir-targ))
      (send-event *camera* 'damp-up)
      (let ((gp-0 (new 'stack-no-clear 'vector)))
        (ja-no-eval :group! eichar-edge-grab-off-ja :num! (seek! (ja-aframe (the-as float 191.0) 0)) :frame-num 0.0)
        (until (ja-done? 0)
          (compute-alignment! (-> self align))
          (when (not (logtest? (-> self align flags) (align-flags disabled)))
            (vector-matrix*! gp-0 (the-as vector (-> self align delta)) (-> self control unknown-matrix01))
            (move-by-vector! (-> self control) gp-0))
          (suspend)
          (ja :num! (seek! (ja-aframe (the-as float 191.0) 0)))))
      (set! (-> self control transv quad) (the-as uint128 0))
      (logclear! (-> self control root-prim prim-core action) (collide-action edgegrab-active edgegrab-cam))
      (vector-float*! (-> self control transv) (-> self control unknown-vector101) -40960.0)
      (when (and (not (time-elapsed? (-> self control rider-time) (seconds 0.2)))
                 (or (logtest? (-> self control unknown-surface01 flags) (surface-flags moving-ground))
                     (= (-> self control poly-pat material) (pat-material rotate))))
        (+! (-> self control transv x) (-> self control rider-last-move x))
        (+! (-> self control transv z) (-> self control rider-last-move z)))
      (go target-falling 'target-edge-grab))
  :post target-no-move-post)

(defstate target-yellow-blast (target)
  :event
    (-> target-running-attack
        event)
  :enter
    (behavior ()
      (set-time! (-> self state-time))
      (set! (-> self control unknown-surface00) *run-attack-mods*)
      (set! (-> *run-attack-mods* turnv) 655360.0)
      (set! (-> *run-attack-mods* turnvv) 655360.0)
      (target-start-attack)
      (target-danger-set! 'spin #f)
      (set! (-> self control unknown-uint20) (the-as uint 0))
      (set! (-> self control unknown-int21) 0)
      (set! (-> self control unknown-uint31) (the-as uint 0))
      (let ((gp-0 (new-stack-vector0))
            (f30-0 (vector-dot (-> self control dynam gravity-normal) (-> self control transv))))
        0.0
        (vector-! gp-0 (-> self control transv) (vector-float*! gp-0 (-> self control dynam gravity-normal) f30-0))
        (let* ((f0-5 (vector-length gp-0))
               (f1-0 f0-5))
          (if (< 0.0 f30-0) (set! f30-0 0.0))
          (vector+! (-> self control transv)
                    (vector-float*! (-> self control transv) (-> self control dynam gravity-normal) f30-0)
                    (vector-float*! gp-0 gp-0 (/ f0-5 f1-0))))))
  :exit
    (behavior ()
      (set! (-> *run-attack-mods* turnv) 0.0)
      (set! (-> *run-attack-mods* turnvv) 0.0)
      (set-time! (-> self control unknown-dword31))
      (target-exit))
  :code
    (behavior ()
      (let ((gp-0 (the-as handle #f)))
        (ja-channel-push! 1 (seconds 0.075))
        (level-hint-spawn (text-id swamp-eco-yellow-first-use) "sksp0145" (the-as entity #f) *entity-pool* (game-task none))
        (case (-> (level-get-target-inside *level*) name)
          (('maincave)
           (level-hint-spawn (text-id cave-gnawers-look-around) "sksp0328" (the-as entity #f) *entity-pool* (game-task none))))
        (ja-no-eval :group! eichar-yellow-running-blast-ja :num! (seek! (ja-aframe (the-as float 9.0) 0)) :frame-num 0.0)
        (until (ja-done? 0)
          (if (time-elapsed? (-> self state-time) (seconds 0.1)) (set! (-> *run-attack-mods* turnvv) 0.0))
          (suspend)
          (ja :num! (seek! (ja-aframe (the-as float 9.0) 0))))
        (let ((s5-2 (vector-z-quaternion! (new 'stack-no-clear 'vector) (-> self control quat))))
          (set! (-> s5-2 y) 0.0)
          (vector-normalize! s5-2 (-> *TARGET-bank* yellow-projectile-speed))
          (when (and (= (-> self fact eco-type) (pickup-type eco-yellow)) (>= (-> self fact eco-level) 1.0))
            (let ((gp-1 (get-process *default-dead-pool* projectile-yellow #x4000)))
              (set! gp-0
                    (ppointer->handle (when gp-1
                                        (let ((t9-12 (method-of-type projectile-yellow activate)))
                                          (t9-12 (the-as projectile-yellow gp-1) self 'projectile-yellow (the-as pointer #x70004000)))
                                        (run-now-in-process gp-1
                                                            projectile-init-by-other
                                                            (-> self entity)
                                                            (vector<-cspace! (new 'stack-no-clear 'vector) (joint-node eichar-lod0-jg sk_rhand))
                                                            s5-2
                                                            (if (>= (-> self fact eco-level) (-> *FACT-bank* eco-level-max)) 25 9)
                                                            #f)
                                        (-> gp-1 ppointer)))))
            (set-time! (-> self control unknown-dword82))))
        (ja-no-eval :group! eichar-yellow-running-blast-ja :num! (seek!) :frame-num (ja-aframe (the-as float 9.0) 0))
        (until (ja-done? 0)
          (if (or (< (the-as uint (- (current-time) (the-as int (-> self control unknown-uint30)))) (the-as uint 30))
                  (= (-> self control unknown-uint31) 1))
            (send-event (handle->process gp-0) 'die))
          (suspend)
          (ja :num! (seek!))))
      (if (logtest? (-> self control status) (cshape-moving-flags onsurf)) (go target-stance) (go target-falling #f)))
  :post target-post)

(define *yellow-jump-mods*
  (new 'static
       'surface
       :name 'run
       :tiltv 65536.0
       :tiltvv 131072.0
       :transv-max 40960.0
       :target-speed 40960.0
       :fric 0.1
       :nonlin-fric-dist 1.0
       :slip-factor 1.0
       :slide-factor 1.0
       :slope-up-factor 1.0
       :slope-down-factor 1.0
       :slope-slip-angle 1.0
       :impact-fric 1.0
       :bend-factor 1.0
       :bend-speed 1.0
       :alignv 1.0
       :slope-up-traction 1.0
       :align-speed 1.0
       :mode 'air
       :flags (surface-flags jump)))

(defstate target-yellow-jump-blast (target)
  :event target-standard-event-handler
  :enter
    (behavior ()
      (set! (-> self control unknown-surface00) *yellow-jump-mods*)
      (let ((gp-0 (new-stack-vector0)))
        (let ((f0-1 (vector-dot (-> self control dynam gravity-normal) (-> self control transv))))
          0.0
          (vector-! gp-0 (-> self control transv) (vector-float*! gp-0 (-> self control dynam gravity-normal) f0-1)))
        (let* ((f0-2 (vector-length gp-0))
               (f1-1 f0-2)
               (f2-0 46917.434))
          (vector+! (-> self control transv)
                    (vector-float*! (-> self control transv) (-> self control dynam gravity-normal) f2-0)
                    (vector-float*! gp-0 gp-0 (/ f0-2 f1-1))))))
  :exit
    (behavior ()
      (rot->dir-targ! (-> self control))
      (set-time! (-> self control unknown-dword31))
      (target-exit))
  :code
    (behavior ()
      (ja-channel-push! 1 (seconds 0.075))
      (ja-no-eval :group! eichar-yellow-jumping-blast-ja :num! (seek! (ja-aframe (the-as float 15.0) 0)) :frame-num 0.0)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek! (ja-aframe (the-as float 15.0) 0))))
      (suspend)
      (let ((gp-2 (new-stack-vector0)))
        (let ((f0-6 (vector-dot (-> self control dynam gravity-normal) (-> self control transv))))
          0.0
          (vector-! gp-2 (-> self control transv) (vector-float*! gp-2 (-> self control dynam gravity-normal) f0-6)))
        (let* ((f0-7 (vector-length gp-2))
               (f1-1 f0-7)
               (f2-0 46917.434))
          (vector+! (-> self control transv)
                    (vector-float*! (-> self control transv) (-> self control dynam gravity-normal) f2-0)
                    (vector-float*! gp-2 gp-2 (/ f0-7 f1-1)))))
      (ja :num! (seek!))
      (process-spawn projectile-yellow
                     :init
                     projectile-init-by-other
                     (-> self entity)
                     (-> self control unknown-vector90)
                     (vector-float*! (new 'stack-no-clear 'vector)
                                     (vector-z-quaternion! (new 'stack-no-clear 'vector) (-> self control quat))
                                     (the-as float (-> *TARGET-bank* yellow-projectile-speed)))
                     (if (>= (-> self fact eco-level) (-> *FACT-bank* eco-level-max)) 16 0)
                     #f
                     :to
                     self)
      (set-time! (-> self control unknown-dword82))
      (suspend-for (seconds 0.1))
      (ja-no-eval :group! eichar-yellow-jumping-blast-ja :num! (seek!) :frame-num (ja-frame-num 0))
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!)))
      (if (logtest? (-> self control status) (cshape-moving-flags onsurf)) (go target-stance) (go target-falling #f)))
  :post target-no-stick-post)

(defstate target-eco-powerup (target)
  :event target-standard-event-handler
  :exit target-exit
  :trans
    (behavior ()
      (slide-down-test))
  :code
    (behavior ((arg0 object) (arg1 float))
      (set! (-> self neck flex-blend) 0.0)
      (set-time! (-> self state-time))
      (if (= arg1 (-> *FACT-bank* eco-full-inc))
        (set! (-> self control unknown-surface00) *double-jump-mods*)
        (set! (-> self control unknown-surface00) *walk-mods*))
      (ja-channel-push! 1 (seconds 0.05))
      (ja-no-eval :group!
                  eichar-powerup-ja
                  :num!
                  (seek! max (the-as float (if (= arg1 (-> *FACT-bank* eco-full-inc)) 2.0 3.0)))
                  :frame-num
                  (ja-aframe (the-as float (if (= arg1 (-> *FACT-bank* eco-full-inc)) 0.0 6.0)) 0))
      (until (ja-done? 0)
        ;; og:preserve-this - High FPS Fix
        (if (and (recently-pressed? x)
                 (not (logtest? (-> self water flags) (water-flags wt09)))
                 (not (logtest? (-> self state-flags) (state-flags prevent-jump))))
          (go target-jump (-> *TARGET-bank* jump-height-min) (-> *TARGET-bank* jump-height-max) (the-as surface #f)))
        (if (and (cpad-pressed? (-> self control unknown-cpad-info00 number) circle) (can-feet?)) (go target-attack-air #f))
        (when (can-hands? #f)
          (if (and (= (-> self fact eco-type) (pickup-type eco-yellow)) (>= (-> self fact eco-level) 1.0))
            (go target-yellow-jump-blast)
            (go target-running-attack)))
        (compute-alignment! (-> self align))
        (align! (-> self align)
                (align-opts adjust-y-vel)
                (the-as float 1.0)
                (the-as float (if (= arg1 (-> *FACT-bank* eco-full-inc)) 2.0 1.0))
                (the-as float 1.0))
        (suspend)
        (ja :num! (seek! max (the-as float (if (= arg1 (-> *FACT-bank* eco-full-inc)) 2.0 3.0)))))
      (go target-falling 'target-eco-powerup))
  :post target-post)

(defstate target-wade-stance (target)
  :event target-standard-event-handler
  :enter
    (behavior ()
      (set-time! (-> self state-time))
      (set! (-> self control unknown-surface00) *wade-mods*)
      (set-zero! (-> self water bob)))
  :exit
    (behavior ()
      (target-state-hook-exit)
      (target-exit)
      (let ((v1-1 (-> self skel effect))) (set! (-> v1-1 channel-offset) 0))
      0)
  :trans
    (behavior ()
      ((-> self state-hook))
      (when (and (not (logtest? (-> self water flags) (water-flags wt10))) (time-elapsed? (-> self water wade-time) (seconds 0.05)))
        (if (logtest? (-> self water flags) (water-flags wt11)) (go target-swim-stance) (go target-stance)))
      (if (and (cpad-hold? (-> self control unknown-cpad-info00 number) l1 r1) (can-duck?)) (go target-duck-stance))
      (if (!= (-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) stick0-speed) 0.0) (go target-wade-walk))
      ;; og:preserve-this - High FPS Fix
      (if (and (recently-pressed? x) (can-jump? #f))
        (go target-jump (-> *TARGET-bank* jump-height-min) (-> *TARGET-bank* jump-height-max) (the-as surface #f)))
      (when (and (cpad-pressed? (-> self control unknown-cpad-info00 number) circle) (can-feet?))
        (sound-play "swim-stroke")
        (create-splash (-> self water) (the-as float 1.4) (-> self control trans) 0 (-> self control transv))
        (go target-attack))
      (if (can-hands? #t) (go target-running-attack)))
  :code
    (-> target-stance
        code)
  :post target-post)

(defstate target-wade-walk (target)
  :event target-standard-event-handler
  :enter
    (-> target-wade-stance
        enter)
  :exit
    (-> target-wade-stance
        exit)
  :trans
    (behavior ()
      ((-> self state-hook))
      (when (and (not (logtest? (-> self water flags) (water-flags wt10))) (time-elapsed? (-> self water wade-time) (seconds 0.1)))
        (if (logtest? (-> self water flags) (water-flags wt11)) (go target-swim-stance) (go target-stance)))
      (if (= (-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) stick0-speed) 0.0) (go target-wade-stance))
      (if (and (cpad-hold? (-> self control unknown-cpad-info00 number) l1 r1) (can-duck?)) (go target-duck-walk))
      ;; og:preserve-this - High FPS Fix
      (if (and (recently-pressed? x) (can-jump? #f))
        (go target-jump (-> *TARGET-bank* jump-height-min) (-> *TARGET-bank* jump-height-max) (the-as surface #f)))
      (when (and (cpad-pressed? (-> self control unknown-cpad-info00 number) circle) (can-feet?))
        (sound-play "swim-stroke")
        (create-splash (-> self water) (the-as float 1.4) (-> self control trans) 0 (-> self control transv))
        (go target-attack))
      (if (can-hands? #t) (go target-running-attack)))
  :code
    (behavior ()
      (let ((gp-0 105)
            (f30-0 0.0))
        (let ((v1-2 (ja-group)))
          (cond
            ((or (= v1-2 eichar-walk-ja) (= v1-2 eichar-run-ja)) (set! gp-0 15) (set! f30-0 (ja-frame-num 0)))
            ((let ((v1-9 (ja-group))) (or (= v1-9 eichar-jump-ja) (= v1-9 eichar-jump-loop-ja))) (set! gp-0 30))
            ((ja-group? eichar-swim-walk-ja) (set! gp-0 120))))
        (cond
          ((and (= (ja-group-size) 6) (ja-group? eichar-wade-shallow-walk-ja)))
          (else
           (ja-channel-push! 6 (the-as time-frame gp-0))
           (ja :group! eichar-wade-shallow-walk-ja :num! (identity f30-0) :dist (-> *TARGET-bank* wade-shallow-walk-cycle-dist))
           (ja :chan 1 :group! eichar-wade-deep-walk-ja :num! (identity f30-0) :dist (-> *TARGET-bank* wade-deep-walk-cycle-dist))
           (ja :chan 2 :group! eichar-walk-ja :num! (identity f30-0) :frame-interp 0.0 :dist (-> *TARGET-bank* walk-cycle-dist))
           (ja :chan 3
               :group!
               eichar-walk-down-ja
               :num! (identity f30-0)
               :frame-interp 0.0
               :dist (-> *TARGET-bank* walk-down-cycle-dist))
           (ja :chan 4
               :group!
               eichar-walk-left-ja
               :num! (identity f30-0)
               :frame-interp 0.0
               :dist (-> *TARGET-bank* walk-side-cycle-dist)))))
      (set! (-> self skel root-channel 2 command) 'push)
      (set! (-> self skel root-channel 5 command) 'stack)
      (let ((f30-1 0.0)
            (f28-0 0.0)
            (f26-0 (lerp-scale (the-as float 1.0)
                               (the-as float 0.0)
                               (-> self control unknown-float01)
                               (the-as float 16384.0)
                               (the-as float 32768.0)))
            (gp-6 0))
        (loop
          (let ((f0-10 (fmax -1.0 (fmin 1.0 (* 2.0 (-> self control unknown-float61)))))
                (f24-0 (fmax -1.0 (fmin 1.0 (* 1.6 (-> self control unknown-float62))))))
            (let ((f1-4 (fabs (- f0-10 f30-1)))) (set! f30-1 (seek f30-1 f0-10 (fmax 0.05 (fmin 0.2 (/ f1-4 4))))))
            (let ((f0-14 (fabs (- f24-0 f28-0)))) (set! f28-0 (seek f28-0 f24-0 (fmax 0.05 (fmin 0.2 (/ f0-14 4)))))))
          (ja :chan 3 :group! eichar-walk-down-ja :dist (-> *TARGET-bank* walk-down-cycle-dist))
          (if (>= f30-1 0.0)
            (ja :chan 3 :group! eichar-walk-up-ja :frame-interp (fabs f30-1) :dist (-> *TARGET-bank* walk-up-cycle-dist))
            (ja :chan 3 :group! eichar-walk-down-ja :frame-interp (fabs f30-1) :dist (-> *TARGET-bank* walk-down-cycle-dist)))
          (if (>= f28-0 0.0)
            (ja :chan 4 :group! eichar-walk-right-ja :frame-interp (fabs f28-0) :dist (-> *TARGET-bank* walk-side-cycle-dist))
            (ja :chan 4 :group! eichar-walk-left-ja :frame-interp (fabs f28-0) :dist (-> *TARGET-bank* walk-side-cycle-dist)))
          (let* ((f0-30 (- (-> self water height) (-> self control trans y)))
                 (f24-1 (lerp-scale (the-as float 0.0)
                                    (the-as float 1.0)
                                    f0-30
                                    (lerp (-> self water wade-height) (-> self water swim-height) (the-as float 0.25))
                                    (lerp (-> self water wade-height) (-> self water swim-height) (the-as float 0.75)))))
            (let ((v1-108 (-> self skel effect))) (set! (-> v1-108 channel-offset) (if (< 0.5 f24-1) 1 0)))
            0
            (set! f26-0
                  (seek f26-0
                        (lerp-scale (the-as float 1.0)
                                    (the-as float 0.0)
                                    (-> self control unknown-float01)
                                    (the-as float 16384.0)
                                    (the-as float 32768.0))
                        (* 4.0 (seconds-per-frame))))
            (set! (-> self skel root-channel 1 frame-interp) f24-1)
            (ja :num!
                (loop! (/ (-> self control unknown-float01)
                          (* 60.0 (/ (current-cycle-distance (-> self skel)) (-> *TARGET-bank* run-cycle-length))))))
            (ja :chan 5 :frame-interp (lerp f26-0 (the-as float 0.0) f24-1)))
          (ja :chan 1 :num! (chan 0))
          (ja :chan 2 :num! (chan 0))
          (ja :chan 3 :num! (chan 0))
          (ja :chan 4 :num! (chan 0))
          (when (and (time-elapsed? (the-as time-frame gp-6) (seconds 0.2))
                     (< (- (-> self water height) (-> self control trans y)) 4096.0))
            (case (the int (ja-aframe-num 0))
              ((15 16 17 18)
               (create-splash (-> self water)
                              (the-as float 0.2)
                              (vector<-cspace! (new 'stack-no-clear 'vector) (joint-node eichar-lod0-jg Rtoes))
                              0
                              (vector-float*! (new 'stack-no-clear 'vector) (-> self control transv) 2.5))
               (set! gp-6 (the-as int (current-time))))
              ((46 47 48 49)
               (create-splash (-> self water)
                              (the-as float 0.2)
                              (vector<-cspace! (new 'stack-no-clear 'vector) (joint-node eichar-lod0-jg Ltoes))
                              0
                              (vector-float*! (new 'stack-no-clear 'vector) (-> self control transv) 2.5))
               (set! gp-6 (the-as int (current-time))))))
          (suspend))))
  :post target-post)

(defbehavior target-swim-tilt target ((arg0 float) (arg1 float) (arg2 float) (arg3 float))
  (let ((gp-0 (vector-z-quaternion! (new 'stack-no-clear 'vector) (-> self control unknown-quaternion00))))
    (let ((v1-2 (vector-z-quaternion! (new 'stack-no-clear 'vector) (-> self control dir-targ)))
          (f0-1 (fmin 1.0 (* arg0 (/ (-> self control unknown-float01) (-> self control unknown-surface01 target-speed))))))
      (seek! (-> self control unknown-float130)
             (fmax (fmin (* (+ f0-1 arg2) (fmax 0.5 (+ 0.5 (vector-dot gp-0 v1-2)))) arg3) (- arg3))
             (* arg1 (seconds-per-frame))))
    (let ((a2-2 (vector-y-quaternion! (new 'stack-no-clear 'vector) (-> self control unknown-quaternion00))))
      (forward-up-nopitch->quaternion (-> self control unknown-quaternion01) gp-0 a2-2)))
  (quaternion-rotate-x! (-> self control unknown-quaternion01)
                        (-> self control unknown-quaternion01)
                        (the-as float (if (>= (-> self control unknown-float130) 0.0) 16384.0 -16384.0)))
  (set! (-> self control unknown-float00) (fabs (-> self control unknown-float130)))
  (if (= (-> self next-state name) 'target-swim-down)
    (seek! (-> self control unknown-float131) (the-as float -6144.0) (* 4096.0 (seconds-per-frame)))
    (seek! (-> self control unknown-float131) (the-as float 0.0) (* 2048.0 (seconds-per-frame))))
  (set! (-> self control unknown-vector11 y) (-> self control unknown-float131)))

(defstate target-swim-stance (target)
  :event target-standard-event-handler
  :enter
    (behavior ()
      (set-time! (-> self state-time))
      (set! (-> self control unknown-surface00) *swim-mods*)
      (logior! (-> self water flags) (water-flags wt04)))
  :exit
    (behavior ()
      (target-state-hook-exit)
      (set! (-> self control unknown-surface00 target-speed) 28672.0)
      (target-exit)
      (when (not (or (= (-> self next-state name) 'target-swim-stance)
                     (= (-> self next-state name) 'target-swim-walk)
                     (= (-> self next-state name) 'target-swim-down)
                     (= (-> self next-state name) 'target-swim-up)))
        (quaternion-identity! (-> self control unknown-quaternion01))
        (set! (-> self control unknown-float00) 0.0)))
  :trans
    (behavior ()
      ((-> self state-hook))
      (if (and (logtest? (-> self control status) (cshape-moving-flags onsurf))
               (not (logtest? (-> self control status) (cshape-moving-flags on-water))))
        (set-zero! (-> self water bob)))
      (when (and (not (logtest? (-> self water flags) (water-flags wt11))) (time-elapsed? (-> self state-time) (seconds 0.1)))
        (if (logtest? (-> self water flags) (water-flags wt10)) (go target-wade-stance) (go target-stance)))
      ;; og:preserve-this - High FPS Fix
      (if (and (recently-pressed? x) (can-jump? #f) (time-elapsed? (-> self water enter-swim-time) (seconds 0.1)))
        (go target-swim-jump (-> *TARGET-bank* swim-jump-height-min) (-> *TARGET-bank* swim-jump-height-max)))
      ;; og:preserve-this - High FPS Fix
      (if (and (recently-pressed? square) (< (-> *TARGET-bank* min-dive-depth) (target-height-above-ground)))
        (go target-swim-down))
      (if (and (!= (-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) stick0-speed) 0.0)
               (let ((gp-0 (ja-group)))
                 (ja-aframe-num 0)
                 (if (or (and (= gp-0 eichar-swim-up-ja) #t) (and (= gp-0 eichar-swim-down-to-up-ja) #t)) #f #t)))
        (go target-swim-walk))
      (target-swim-tilt (the-as float 0.0) (the-as float 2.0) (the-as float 0.0) (the-as float 1.0)))
  :code
    (behavior ()
      (let ((v1-2 (ja-group)))
        (cond
          ((or (= v1-2 eichar-swim-up-ja) (= v1-2 eichar-swim-down-to-up-ja))
           (ja-channel-push! 1 (seconds 0.075))
           (ja-no-eval :group!
                       eichar-swim-up-to-stance-ja
                       :num!
                       (seek! max
                              (the-as float (if (= (-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) stick0-speed) 0.0) 1.0 2.0)))
                       :frame-num 0.0)
           (until (ja-done? 0)
             (suspend)
             (let ((a0-9 (-> self skel root-channel 0)))
               (set! (-> a0-9 param 0) (the float (+ (-> a0-9 frame-group data 0 length) -1)))
               (let ((v1-41 (if (= (-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) stick0-speed) 0.0) 1.0 2.0)))
                 (set! (-> a0-9 param 1) (the-as float v1-41)))
               (joint-control-channel-group-eval! a0-9 (the-as art-joint-anim #f) num-func-seek!))))
          ((ja-group? eichar-swim-walk-ja) (ja-channel-push! 1 (seconds 0.83)))
          (else (ja-channel-push! 1 (seconds 0.15)))))
      (loop
        (ja :group! eichar-swim-stance-ja :num! min)
        (until (and (ja-done? 0) (= (-> self skel root-channel 0) (-> self skel channel)))
          (suspend)
          (if (= (-> self skel root-channel 0) (-> self skel channel)) (ja :num! (seek!))))))
  :post target-swim-post)

(defstate target-swim-walk (target)
  :event target-standard-event-handler
  :enter
    (behavior ()
      ((-> target-swim-stance enter))
      (die-on-next-update! (-> self water bob))
      (set! (-> self control unknown-uint20) (the-as uint (current-time))))
  :exit
    (-> target-swim-stance
        exit)
  :trans
    (behavior ()
      ((-> self state-hook))
      (if (and (logtest? (-> self control status) (cshape-moving-flags onsurf))
               (not (logtest? (-> self control status) (cshape-moving-flags on-water))))
        (set-zero! (-> self water bob)))
      (when (and (not (logtest? (-> self water flags) (water-flags wt11))) (time-elapsed? (-> self water swim-time) (seconds 0.1)))
        (if (logtest? (-> self water flags) (water-flags wt10)) (go target-wade-stance) (go target-stance)))
      ;; og:preserve-this - High FPS Fix
      (if (and (recently-pressed? x) (can-jump? #f) (time-elapsed? (-> self water enter-swim-time) (seconds 0.1)))
        (go target-swim-jump (-> *TARGET-bank* swim-jump-height-min) (-> *TARGET-bank* swim-jump-height-max)))
      ;; og:preserve-this - High FPS Fix
      (if (and (recently-pressed? square) (< (-> *TARGET-bank* min-dive-depth) (target-height-above-ground)))
        (go target-swim-down))
      (cond
        ((= (-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) stick0-speed) 0.0)
         (if (>= (the-as uint (- (current-time) (the-as int (-> self control unknown-uint20)))) (the-as uint 15))
           (go target-swim-stance)))
        (else (set! (-> self control unknown-uint20) (the-as uint (current-time)))))
      (target-swim-tilt (the-as float 0.0) (the-as float 2.0) (the-as float 0.0) (the-as float 1.0)))
  :code
    (behavior ()
      (let ((v1-2 (ja-group)))
        (cond
          ((or (= v1-2 eichar-swim-up-ja) (= v1-2 eichar-swim-down-to-up-ja) (= v1-2 eichar-swim-up-to-stance-ja))
           (ja-channel-push! 1 (seconds 0.3)))
          ((ja-group? eichar-swim-up-to-stance-ja)
           (ja-channel-push! 1 (seconds 0.15))
           (ja-no-eval :group! eichar-swim-walk-ja :num! (seek!) :frame-num (ja-aframe (the-as float 19.0) 0))
           (until (ja-done? 0)
             (compute-alignment! (-> self align))
             (if (not (logtest? (-> self align flags) (align-flags disabled)))
               (set! (-> self control unknown-surface00 target-speed)
                     (* (-> self align delta trans z) (-> self control unknown-surface01 alignv) (-> *display* frames-per-second))))
             (suspend)
             (ja :num! (seek!))))
          (else (ja-channel-push! 1 (seconds 0.15)))))
      (loop
        (ja-no-eval :group! eichar-swim-walk-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (compute-alignment! (-> self align))
          (if (not (logtest? (-> self align flags) (align-flags disabled)))
            (set! (-> self control unknown-surface00 target-speed)
                  (* (-> self align delta trans z) (-> self control unknown-surface01 alignv) (-> *display* frames-per-second))))
          (suspend)
          (ja :num! (seek!)))))
  :post target-swim-post)

(defstate target-swim-down (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('attack 'attack-invinc)
         (let ((v1-2 (the-as attack-info (-> block param 1))))
           (when (or (not (logtest? (-> v1-2 mask) (attack-mask mode))) (= (-> v1-2 mode) 'generic) (= (-> v1-2 mode) 'drown))
             (set! (-> v1-2 mode) 'damage)
             (if (and (= (-> self game mode) 'play) (>= 1.0 (-> self fact health))) (set! (-> v1-2 mode) 'drown-death))
             (logior! (-> v1-2 mask) (attack-mask mode))
             (set! (-> self control unknown-uint20) (the-as uint #t))))))
      (target-standard-event-handler proc argc message block))
  :enter
    (behavior ()
      (set-time! (-> self state-time))
      (logclear! (-> self water flags) (water-flags wt04))
      (set! (-> self control unknown-surface00) *dive-mods*)
      (set! (-> self control dynam gravity-max) 16384.0)
      (set! (-> self control dynam gravity-length) 16384.0)
      (set-time! (-> self water swim-time))
      (set! (-> self control unknown-uint20) (the-as uint #f))
      (if (= (-> self next-state name) 'target-swim-down) (set! (-> self control unknown-float130) 0.0)))
  :exit
    (behavior ()
      (set! (-> self control dynam gravity-max) (-> self control unknown-dynamics00 gravity-max))
      (set! (-> self control dynam gravity-length) (-> self control unknown-dynamics00 gravity-length))
      (target-exit)
      (when (not (or (= (-> self next-state name) 'target-swim-stance)
                     (= (-> self next-state name) 'target-swim-walk)
                     (= (-> self next-state name) 'target-swim-down)
                     (= (-> self next-state name) 'target-swim-up)))
        (quaternion-identity! (-> self control unknown-quaternion01))
        (set! (-> self control unknown-float00) 0.0)))
  :trans
    (behavior ()
      (if (time-elapsed? (-> self water swim-time) (seconds 0.5)) (go target-stance))
      (cond
        ((time-elapsed? (-> self control unknown-dword11) (seconds 0.1))
         (set! (-> self control unknown-surface00) *dive-mods*)
         (if (= (-> self next-state name) 'target-swim-down)
           (target-swim-tilt (the-as float -0.9) (the-as float 1.0) (the-as float 0.0) (the-as float 0.5))))
        (else
         (set! (-> self control unknown-surface00) *dive-bottom-mods*)
         (if (or (= (-> self next-state name) 'target-swim-down) (= (-> self next-state name) 'target-swim-stance))
           (target-swim-tilt (the-as float 0.0) (the-as float 2.0) (the-as float -1.0) (the-as float 1.0))))))
  :code
    (behavior ()
      (let ((gp-0 60)
            (s5-0 3000)
            (f30-0 0.0))
        (let ((v1-2 (ja-group)))
          (set! f30-0
                (cond
                  ((or (= v1-2 eichar-swim-stance-ja)
                       (= v1-2 eichar-swim-walk-ja)
                       (= v1-2 eichar-swim-up-to-stance-ja)
                       (= v1-2 eichar-swim-up-ja)
                       (= v1-2 eichar-swim-down-to-up-ja))
                   (ja-channel-push! 1 (seconds 0.075))
                   (ja-no-eval :group! eichar-swim-walk-to-down-ja :num! (seek!) :frame-num 0.0)
                   (until (ja-done? 0)
                     (compute-alignment! (-> self align))
                     (align! (-> self align)
                             (align-opts adjust-y-vel adjust-xz-vel)
                             (the-as float 1.0)
                             (the-as float 1.0)
                             (the-as float 1.0))
                     (if (= (ja-aframe-num 0) 73.0) (create-splash (-> self water) (the-as float 0.7) (-> self control trans) 1 *null-vector*))
                     (suspend)
                     (ja :num! (seek!)))
                   (ja :group! eichar-swim-down-ja :num! min)
                   f30-0)
                  (else
                   (case (ja-group)
                     ((eichar-flop-down-ja eichar-moving-flop-down-ja eichar-flop-down-loop-ja eichar-moving-flop-down-loop-ja)
                      (ja-channel-push! 1 (seconds 0.075))
                      (set! gp-0 120)
                      (ja :group! eichar-swim-down-ja :num! (identity (ja-aframe (the-as float 124.0) 0)))
                      -16384.0)
                     (else (ja-channel-push! 1 (seconds 0.075)) (ja :group! eichar-swim-down-ja :num! min) f30-0))))))
        (loop
          (if (and (or (not (cpad-hold? (-> self control unknown-cpad-info00 number) square)) (-> self control unknown-spoolanim00))
                   (time-elapsed? (-> self state-time) gp-0))
            (go target-swim-up))
          (if (or (time-elapsed? (-> self state-time) s5-0)
                  (and (logtest? (-> self control status) (cshape-moving-flags onsurf))
                       (and (< (-> self water swim-depth) 8192.0) (time-elapsed? (-> self state-time) gp-0))))
            (go target-swim-up))
          (let ((s4-3 (new-stack-vector0))
                (f24-0 (vector-dot (-> self control dynam gravity-normal) (-> self control transv))))
            0.0
            (vector-! s4-3 (-> self control transv) (vector-float*! s4-3 (-> self control dynam gravity-normal) f24-0))
            (let* ((f28-0 (vector-length s4-3))
                   (f26-0 f28-0)
                   (f24-1 (+ f24-0 f30-0)))
              (set! f30-0 (seek f30-0 (the-as float 0.0) (* 32768.0 (seconds-per-frame))))
              (vector+! (-> self control transv)
                        (vector-float*! (-> self control transv) (-> self control dynam gravity-normal) f24-1)
                        (vector-float*! s4-3 s4-3 (/ f28-0 f26-0)))))
          (suspend)
          (ja :num!
              (loop! (lerp-scale (the-as float 0.4)
                                 (the-as float 1.0)
                                 (vector-length (-> self control transv))
                                 (the-as float 0.0)
                                 (the-as float 16384.0)))))))
  :post target-swim-post)

(defstate target-swim-up (target)
  :event
    (-> target-swim-down
        event)
  :enter
    (-> target-swim-down
        enter)
  :exit
    (-> target-swim-down
        exit)
  :trans
    (behavior ()
      (if (and (cpad-pressed? (-> self control unknown-cpad-info00 number) x)
               (not (logtest? (-> self state-flags) (state-flags prevent-jump)))
               (not (logtest? (-> self water flags) (water-flags wt13 wt14))))
        (go target-swim-jump-jump
            (-> *TARGET-bank* swim-jump-height-min)
            (-> *TARGET-bank* swim-jump-height-max)
            (the-as surface #f)))
      (if (and (time-elapsed? (-> self state-time) (seconds 10))
               (< (target-move-dist (-> *TARGET-bank* stuck-time)) (-> *TARGET-bank* stuck-distance)))
        (send-event self 'attack #f (static-attack-info ((mode 'drown-death)))))
      ((-> target-swim-down trans)))
  :code
    (behavior ()
      (ja-channel-push! 1 (seconds 0.1))
      (let ((f30-0 1.0))
        (let ((gp-0 #t))
          (ja-no-eval :group! eichar-swim-down-to-up-ja :num! (seek!) :frame-num 0.0)
          (until (ja-done? 0)
            (target-swim-tilt (the-as float (if (< 8192.0 (-> self water swim-depth)) 0.5 0.0))
                              (the-as float 1.0)
                              (the-as float 0.0)
                              (the-as float 0.1))
            (if (and (not (logtest? (-> self water flags) (water-flags wt12)))
                     (or (>= (ja-aframe-num 0) 222.0)
                         (and (!= (-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) stick0-speed) 0.0)
                              (>= (ja-aframe-num 0) 200.0))))
              (goto cfg-37))
            (compute-alignment! (-> self align))
            (when (not (logtest? (-> self water flags) (water-flags wt12)))
              (logior! (-> self water flags) (water-flags wt04))
              (set! gp-0 #f))
            (if gp-0 (align! (-> self align) (align-opts adjust-y-vel) (the-as float 1.0) (the-as float 1.0) (the-as float 1.0)))
            (suspend)
            (ja :num! (seek!))))
        (ja :group! eichar-swim-up-ja :num! min)
        (loop
          (target-swim-tilt (the-as float (if (< 8192.0 (-> self water swim-depth)) 0.3 0.0))
                            (the-as float 1.0)
                            (the-as float 0.0)
                            (the-as float 0.1))
          (if (not (logtest? (-> self water flags) (water-flags wt12))) (goto cfg-37))
          (if (cpad-pressed? (-> self control unknown-cpad-info00 number) x) (set! f30-0 2.0))
          (compute-alignment! (-> self align))
          (when (logtest? (-> self water flags) (water-flags wt12))
            (align! (-> self align) (align-opts adjust-y-vel) (the-as float 1.0) (the-as float 1.0) (the-as float 1.0))
            (set! (-> self control transv y) (+ 8192.0 (* 8192.0 f30-0))))
          (suspend)
          (ja :num! (loop! f30-0))
          (set! f30-0 (seek f30-0 (the-as float 1.0) (seconds-per-frame)))))
      (label cfg-37)
      (logior! (-> self water flags) (water-flags wt04))
      (set-time! (-> self water swim-time))
      (start-bobbing! (-> self water) (the-as float -4096.0) 600 1500)
      (set! (-> self water bob start-time) (+ (current-time) (seconds -0.05)))
      (go target-swim-stance))
  :post target-swim-post)

(defstate target-swim-jump-jump (target)
  :event
    (-> target-jump
        event)
  :enter
    (-> target-jump
        enter)
  :exit target-exit
  :trans
    (behavior ()
      (cond
        ((not (time-elapsed? (-> self state-time) (seconds 0.5)))
         (logior! (-> self water flags) (water-flags wt16))
         (logclear! (-> self control status) (cshape-moving-flags onsurf onground tsurf)))
        (else (set! (-> self trans-hook) (-> target-jump trans))))
      ((-> target-jump trans)))
  :code
    (-> target-jump
        code)
  :post target-post)

(defstate target-swim-jump (target)
  :event target-standard-event-handler
  :enter
    (-> target-swim-stance
        enter)
  :exit
    (behavior ()
      ((-> target-swim-stance exit))
      (die-on-next-update! (-> self water bob))
      (set! (-> self water align-offset) 0.0)
      (logior! (-> self water flags) (water-flags wt16)))
  :code
    (behavior ((arg0 float) (arg1 float))
      (die-on-next-update! (-> self water bob))
      (ja-channel-push! 1 (seconds 0.05))
      (ja :group! eichar-swim-jump-ja :num! min)
      (until (and (ja-done? 0) (= (-> self skel root-channel 0) (-> self skel channel)))
        (compute-alignment! (-> self align))
        (if (not (logtest? (-> self align flags) (align-flags disabled)))
          (+! (-> self water align-offset) (* 0.6 (-> self align delta trans y))))
        (suspend)
        (if (= (-> self skel root-channel 0) (-> self skel channel)) (ja :num! (seek! max 2.0))))
      (let ((f30-0 (fmax 0.0 (- (-> self water bob-offset)))))
        (let ((s4-1 (new-stack-vector0)))
          (let ((f0-8 (vector-dot (-> self control dynam gravity-normal) (-> self control transv))))
            0.0
            (vector-! s4-1 (-> self control transv) (vector-float*! s4-1 (-> self control dynam gravity-normal) f0-8)))
          (let* ((f0-9 (vector-length s4-1))
                 (f1-5 f0-9)
                 (f2-1 0.4096))
            (vector+! (-> self control transv)
                      (vector-float*! (-> self control transv) (-> self control dynam gravity-normal) f2-1)
                      (vector-float*! s4-1 s4-1 (/ f0-9 f1-5)))))
        (go target-swim-jump-jump (+ f30-0 arg0) (+ f30-0 arg1) (the-as surface #f))))
  :post target-swim-post)

(defstate target-hit-ground-hard (target)
  :event target-standard-event-handler
  :enter
    (behavior ((arg0 float))
      (set! (-> self control unknown-dword31) 0)
      (set! (-> self control unknown-dword33) 0)
      (set-forward-vel (the-as float 0.0))
      (set! (-> self control unknown-surface00) *walk-mods*))
  :code
    (behavior ((arg0 float))
      (when (!= arg0 0.0)
        (let ((f0-5 (the float (the int (+ 1.0 (/ (- arg0 (-> *TARGET-bank* fall-far)) (-> *TARGET-bank* fall-far-inc)))))))
          (pickup-collectable! (-> self fact)
                               (pickup-type eco-green)
                               (* (-> *FACT-bank* health-single-inc) (- (fmax 0.0 f0-5)))
                               (the-as handle #f)))
        (if (not (cpad-hold? 0 l3)) (target-timed-invulnerable (-> *TARGET-bank* hit-invulnerable-timeout) self)))
      (cond
        ((and (= (-> self game mode) 'play) (>= 0.0 (-> self fact health)))
         (set! (-> self attack-info attacker) (the-as handle #f))
         (go target-death 'target-hit-ground-hard))
        (else
         (cpad-set-buzz! (-> *cpad-list* cpads 0) 1 255 (seconds 0.1))
         (ja-channel-push! 1 1)
         (ja :group! eichar-painful-land-ja :num! min)
         (until (and (ja-done? 0) (= (-> self skel root-channel 0) (-> self skel channel)))
           (suspend)
           (if (= (-> self skel root-channel 0) (-> self skel channel)) (ja :num! (seek!))))
         (ja :group! eichar-painful-land-end-ja :num! min)
         (until (and (ja-done? 0) (= (-> self skel root-channel 0) (-> self skel channel)))
           (suspend)
           (if (= (-> self skel root-channel 0) (-> self skel channel)) (ja :num! (seek!))))
         (go target-stance))))
  :post target-no-stick-post)

(defstate target-launch (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (if (and (= message 'query) (= (-> block param 0) 'mode))
        'target-launch
        (target-standard-event-handler proc argc message block)))
  :code
    (behavior ((arg0 float) (arg1 symbol) (arg2 vector) (arg3 int))
      (set-time! (-> self state-time))
      (set! (-> self control unknown-surface00) *turn-around-mods*)
      (ja-channel-push! 1 (seconds 0.15))
      (set-forward-vel (the-as float 0.0))
      (ja-no-eval :group! eichar-duck-stance-ja :num! (seek! (ja-aframe (the-as float 15.0) 0) 3.0) :frame-num 0.0)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek! (ja-aframe (the-as float 15.0) 0) 3.0)))
      (if arg1 (send-event *camera* 'change-state arg1 (seconds 0.6)))
      (if (nonzero? arg3)
        (process-spawn-function process
          (lambda :behavior process ((arg0 vector) (arg1 time-frame) (arg2 float))
            (local-vars (sv-32 time-frame) (sv-40 vector) (sv-44 symbol))
            (set! sv-32 (current-time))
            (let ((v1-2 (new-stack-vector0))) (set! (-> v1-2 quad) (-> arg0 quad)) (set! sv-40 v1-2))
            (set! sv-44 #t)
            (until (time-elapsed? sv-32 arg1)
              (let ((s4-0 (ppointer->process (-> self parent))))
                (cond
                  ((and sv-44 (< (- (-> (the-as target s4-0) control trans y) (-> (the-as target s4-0) control unknown-vector52 y)) arg2))
                   (vector-xz-normalize! (-> (the-as target s4-0) control transv) (the-as float 0.0))
                   ;; og:preserve-this PAL patch here
                   (when (< (vector-vector-xz-distance (-> (the-as target s4-0) control trans) sv-40) 20480.0)
                     (let ((v1-16 (vector-! (new-stack-vector0) (-> (the-as target s4-0) control trans) sv-40)))
                       (set! (-> (the-as target s4-0) control trans x) (+ (-> sv-40 x) (fmax -2867.2 (fmin 2867.2 (-> v1-16 x)))))
                       (set! (-> (the-as target s4-0) control trans z) (+ (-> sv-40 z) (fmax -2867.2 (fmin 2867.2 (-> v1-16 z))))))))
                  (else
                   (if sv-44 (set! sv-32 (current-time)))
                   (set! sv-44 (the-as symbol #f))
                   (when (or (= (-> (the-as target s4-0) next-state name) 'target-duck-high-jump-jump)
                             (= (-> (the-as target s4-0) next-state name) 'target-falling))
                     (let ((v1-30 (-> (the-as target s4-0) control trans))
                           (s3-0 (-> (the-as target s4-0) control transv)))
                       (set! (-> s3-0 x) (- (-> sv-40 x) (-> v1-30 x)))
                       (set! (-> s3-0 z) (- (-> sv-40 z) (-> v1-30 z)))
                       (let ((f30-0 (vector-xz-length s3-0)))
                         (if (< 122880.0 f30-0) (vector-xz-normalize! s3-0 (the-as float 122880.0)))
                         (if (< 4096.0 f30-0)
                           (forward-up-nopitch->quaternion (-> (the-as target s4-0) control dir-targ)
                                                           (vector-normalize-copy! (new 'stack-no-clear 'vector) s3-0 (the-as float 1.0))
                                                           (vector-y-quaternion! (new 'stack-no-clear 'vector) (-> (the-as target s4-0) control quat))))))))))
              (suspend)
              0)
            #f)
          arg2
          arg3
          143360.0
          :to
          self))
      ;; og:preserve-this PAL patch (sound plays elsewhere)
      ;(sound-play "launch-fire")
      (go target-high-jump arg0 arg0 'launch))
  :post target-no-stick-post)

(defstate target-periscope (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('change-mode) #f)
        (('end-mode) (when (-> self control unknown-spoolanim00) (set! (-> self control unknown-uint20) (the-as uint #f)) #t))
        (else (target-generic-event-handler proc argc message block))))
  :exit
    (behavior ()
      (target-exit)
      (set! (-> self cam-user-mode) 'normal)
      ;; og:preserve-this PAL patch here
      (logclear! (-> self state-flags) (state-flags invulnerable grabbed)))
  :code
    (behavior ((arg0 handle))
      (set! (-> self neck flex-blend) 0.0)
      (target-exit)
      (logior! (-> self state-flags) (state-flags invulnerable do-not-notice))
      (let ((v1-4 (handle->process arg0)))
        (if v1-4
          (quaterion<-rotate-y-vector (-> self control dir-targ)
                                      (vector-! (new 'stack-no-clear 'vector) (-> (the-as process-drawable v1-4) root trans) (-> self control trans)))))
      (set! (-> self control unknown-uint20) (the-as uint #t))
      (ja-channel-push! 1 (seconds 0.1))
      (ja-no-eval :group! eichar-periscope-grab-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!)))
      (send-event (handle->process arg0) 'change-mode)
      (while (-> self control unknown-spoolanim00)
        (suspend))
      (ja-no-eval :group! eichar-periscope-grab-ja :num! (seek! 0.0 2.0) :frame-num max)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek! 0.0 2.0)))
      (go target-stance))
  :post target-no-stick-post)

(defstate target-play-anim (target)
  :event target-generic-event-handler
  :enter
    (behavior ((arg0 string) (arg1 handle))
      (set! (-> self control unknown-handle10) arg1)
      (move-to-ground (-> self control)
                      (the-as float 40960.0)
                      (the-as float 40960.0)
                      #f
                      (-> self control root-prim collide-with))
      (logior! (-> self state-flags) (state-flags grabbed))
      (set! (-> self neck flex-blend) 0.0))
  :exit
    (behavior ()
      (send-event (handle->process (-> self control unknown-handle10)) 'end-mode)
      (target-exit))
  :code
    (behavior ((arg0 string) (arg1 handle))
      (let ((gp-0 (the-as art-joint-anim (lookup-art (-> self draw art-group) arg0 art-joint-anim))))
        (when gp-0
          (send-event (ppointer->process (-> self sidekick)) 'matrix 'play-anim)
          (ja-channel-set! 1)
          (ja-no-eval :group! gp-0 :num! (seek!) :frame-num 0.0)
          (until (ja-done? 0)
            (suspend)
            (ja :num! (seek!)))
          (send-event (ppointer->process (-> self sidekick)) 'matrix 'normal)))
      (go target-stance))
  :post target-no-stick-post)

(defstate target-clone-anim (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (if (and (= message 'trans) (= (-> block param 0) 'restore)) (set! (-> self control unknown-uint20) (the-as uint #f)))
      ((-> target-grab event) proc argc message block))
  :enter
    (behavior ((arg0 handle))
      (set! (-> self control unknown-handle10) arg0)
      (set! (-> self control unknown-vector102 quad) (-> self control trans quad))
      (set! (-> self control unknown-uint20) (the-as uint #t))
      (quaternion-copy! (the-as quaternion (-> self control unknown-vector103)) (-> self control quat))
      (logior! (-> self state-flags) (state-flags grabbed))
      (vector-reset! (-> self control transv))
      (set! (-> self neck flex-blend) 0.0)
      (send-event (ppointer->process (-> self sidekick)) 'shadow #t))
  :exit
    (behavior ()
      (send-event (ppointer->process (-> self sidekick)) 'matrix 'normal)
      (send-event (ppointer->process (-> self sidekick)) 'shadow #t)
      (let ((gp-0 (joint-node eichar-lod0-jg main))
            (a1-2 (&-> (-> self control) unknown-qword00)))
        (cond
          ((not (-> self control unknown-spoolanim00)))
          ((not (logtest? (-> self draw status) (draw-status hidden)))
           (move-to-point! (-> self control) (the-as vector a1-2))
           (matrix->quaternion (-> self control unknown-quaternion00) (-> gp-0 bone transform))
           (quaternion-copy! (-> self control quat) (-> self control unknown-quaternion00))
           (move-to-ground (-> self control)
                           (the-as float 4096.0)
                           (the-as float 40960.0)
                           #t
                           (-> self control root-prim collide-with))
           (when (logtest? (-> self control status) (cshape-moving-flags on-water))
             (let ((a1-6 (new-stack-vector0)))
               (set! (-> a1-6 x) (-> self control trans x))
               (set! (-> a1-6 y) (-> self water height))
               (set! (-> a1-6 z) (-> self control trans z))
               (set! (-> a1-6 w) 1.0)
               (move-to-point! (-> self control) a1-6))))
          (else
           (format 0 "ERROR: <ASG>: camera used backup position~%")
           (move-to-point! (-> self control) (-> self control unknown-vector102))
           (quaternion-copy! (-> self control quat) (the-as quaternion (-> self control unknown-vector103))))))
      (rot->dir-targ! (-> self control))
      (logior! (-> self control status) (cshape-moving-flags onsurf onground tsurf))
      (set-time! (-> self control unknown-dword11))
      (ja-channel-set! 0)
      (ja-post)
      (target-exit))
  :code
    (behavior ((arg0 handle))
      (clone-anim arg0 (the-as int (-> self draw origin-joint-index)) #t "")
      (go target-stance))
  :post target-no-ja-move-post)
