;;-*-Lisp-*-
(in-package goal)
(bundles "SNO.DGO" "SWA.DGO")
(require "engine/game/projectiles-h.gc")
(require "engine/target/target-death.gc")
(require "engine/anim/aligner.gc")
(require "engine/common-obs/water.gc")
(require "levels/flut_common/flutflut.gc")
(require "engine/common-obs/nav-enemy-h.gc")

;; DECOMP BEGINS

(deftype flut-info (basic)
  ((entity        entity-actor)
   (flut-trans    vector :inline)
   (flut-quat     vector :inline)
   (flut-scale    vector :inline)
   (stick-lock    basic)
   (flap-sound-id sound-id)))


(deftype flut-bank (basic)
  ((jump-height-min        meters)
   (jump-height-max        meters)
   (double-jump-height-min meters)
   (double-jump-height-max meters)
   (air-attack-speed       meters)
   (ground-timeout         time-frame)))


(define *FLUT-bank*
  (new 'static
       'flut-bank
       :jump-height-min (meters 5)
       :jump-height-max (meters 7)
       :double-jump-height-min (meters 1)
       :double-jump-height-max (meters 2)
       :air-attack-speed (meters 20)
       :ground-timeout (seconds 0.5)))

(define *flut-walk-mods*
  (new 'static
       'surface
       :name 'run
       :turnv 54613.332
       :turnvv 524288.0
       :tiltv 65536.0
       :tiltvv 131072.0
       :transv-max 81920.0
       :target-speed 81920.0
       :seek0 1.5
       :seek90 3.0
       :seek180 2.0
       :fric 1.0
       :nonlin-fric-dist 0.1
       :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
       :flags (surface-flags no-turn-around)))

(define *flut-jump-mods*
  (new 'static
       'surface
       :name 'jump
       :turnv 131072.0
       :turnvv 54613.332
       :tiltv 32768.0
       :tiltvv 131072.0
       :transv-max 81920.0
       :target-speed 81920.0
       :seek0 0.9
       :seek90 1.5
       :seek180 1.5
       :fric 0.2
       :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)))

(define *flut-double-jump-mods*
  (new 'static
       'surface
       :name 'jump-double
       :turnv 131072.0
       :turnvv 54613.332
       :tiltv 32768.0
       :tiltvv 131072.0
       :transv-max 81920.0
       :target-speed 81920.0
       :seek0 0.9
       :seek90 1.5
       :seek180 1.5
       :fric 0.1
       :nonlin-fric-dist 10.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)))

(define *flut-run-attack-mods*
  (new 'static
       'surface
       :name 'wheel-flip
       :tiltv 32768.0
       :tiltvv 131072.0
       :transv-max 122880.0
       :target-speed 122880.0
       :seek90 0.5
       :seek180 0.15
       :slip-factor 1.0
       :slide-factor 1.0
       :slope-up-factor 0.25
       :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 'attack
       :flags (surface-flags no-turn-around no-rotate-toward-transv attacking)))

(define *flut-air-attack-mods*
  (new 'static
       'surface
       :name 'flop
       :tiltv 32768.0
       :tiltvv 131072.0
       :transv-max 122880.0
       :target-speed 122880.0
       :seek0 1.0
       :seek90 0.3
       :seek180 1.5
       :slip-factor 1.0
       :slide-factor 1.0
       :slope-up-factor 0.25
       :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 'attack
       :flags (surface-flags jump attacking)))

(defbehavior target-flut-post-post target ()
  (vector+! (-> self flut flut-trans) (-> self control trans) (-> self control unknown-vector12))
  (quaternion-copy! (the-as quaternion (-> self flut flut-quat)) (-> self control quat))
  (set! (-> self flut flut-scale quad) (-> self control scale quad))
  (let ((v1-8 (-> *target-shadow-control* settings shadow-dir quad)))
    (set! (-> *flutflut-shadow-control* settings shadow-dir quad) v1-8))
  0
  (none))

(defbehavior target-flut-post target ()
  (target-post)
  (target-flut-post-post)
  0
  (none))

(defbehavior target-flut-falling-anim-trans target ()
  (let ((v1-2 (ja-group)))
    (b! (or (= v1-2 eichar-flut-jump-loop-ja) (= v1-2 eichar-flut-jump-land-ja)) cfg-7 :delay (empty-form)))
  (ja-channel-push! 1 (seconds 0.33))
  (ja :group! eichar-flut-jump-loop-ja)
  (b! #t cfg-23 :delay (nop!))
  (label cfg-7)
  (cond
    ((and (logtest? (-> self control status) (cshape-moving-flags onsurf)) (not (ja-group? eichar-flut-jump-land-ja)))
     (ja-channel-push! 1 (seconds 0.02))
     (ja :group! eichar-flut-jump-land-ja))
    ((ja-group? eichar-flut-jump-loop-ja) (ja :num! (loop!)))
    ((ja-group? eichar-flut-jump-land-ja) (ja :num! (seek!))))
  (label cfg-23)
  0
  (none))

(defbehavior target-flut-hit-ground-anim target ()
  (cond
    ((ja-group? eichar-flut-jump-loop-ja)
     (if (!= (-> self skel root-channel 0) (-> self skel channel)) (ja-channel-push! 2 (seconds 0.05)) (ja-channel-set! 2))
     (ja :group! eichar-flut-jump-land-ja :num! min)
     (ja :chan 1 :group! eichar-flut-jump-forward-land-ja :num! min)
     (until (ja-done? 0)
       (suspend)
       (ja :num! (seek!))
       (ja :chan 1 :num! (chan 0)))
     #f)
    ((let ((v1-33 (ja-group))) (or (= v1-33 eichar-flut-jump-ja) (= v1-33 eichar-flut-jump-land-ja))) #f)
    ((ja-group? eichar-flut-double-jump-ja)
     (ja-channel-set! 1)
     (ja-no-eval :group! eichar-flut-jump-land-ja :num! (seek!) :frame-num 0.0)
     (until (ja-done? 0)
       (suspend)
       (ja :num! (seek!)))
     #f)
    ((let ((v1-68 (ja-group))) (or (= v1-68 eichar-flut-air-attack-ja) (= v1-68 eichar-flut-air-attack-loop-ja)))
     (ja-channel-set! 1)
     (ja-no-eval :group! eichar-flut-air-attack-land-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))
       (suspend)
       (ja :num! (seek!)))
     #f)))

(defbehavior target-flut-standard-event-handler target ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  (cond
    ((and (= arg2 'query) (= (-> arg3 param 0) 'mode)) 'flut)
    (else
     (case arg2
       (('end-mode) (go target-flut-get-off (process->handle arg0)))
       (('attack 'attack-or-shove 'attack-invinc)
        (target-attacked arg2
                         (the-as attack-info (-> arg3 param 1))
                         arg0
                         (the-as touching-shapes-entry (-> arg3 param 0))
                         target-flut-hit))
       (('shove)
        (when (!= (-> self next-state name) 'target-hit)
          (mem-copy! (the-as pointer (-> self attack-info-rec)) (the-as pointer (-> arg3 param 1)) 104)
          (when (not (logtest? (-> self attack-info-rec mask) (attack-mask attacker)))
            (set! (-> self attack-info-rec attacker) (process->handle arg0))
            (logior! (-> self attack-info-rec mask) (attack-mask attacker)))
          (go target-flut-hit 'shove (-> self attack-info-rec))))
       (('falling) (if #t (go target-flut-falling #f)))
       (('swim)
        (let* ((gp-1 (-> self control last-known-safe-ground))
               (s3-1 (vector-! (new 'stack-no-clear 'vector) gp-1 (-> self control trans)))
               (f30-1 (fmax 8192.0 (fmin 40960.0 (vector-xz-length s3-1)))))
          (vector-xz-normalize! s3-1 f30-1)
          (send-event self
                      'shove
                      #f
                      (static-attack-info ((vector s3-1)
                                           (shove-up (+ (lerp-scale (the-as float 4096.0) (the-as float 16384.0) f30-1 (the-as float 4096.0) (the-as float 40960.0))
                                                        (fmax 0.0 (- (-> gp-1 y) (-> self control trans y)))))
                                           (angle 'up))))))
       (('change-mode)
        (case (-> arg3 param 0)
          (('grab) (go target-flut-grab))))
       (('clone-anim) (go target-flut-clone-anim (process->handle (the-as process (-> arg3 param 0)))))
       (else (target-generic-event-handler arg0 arg1 arg2 arg3))))))

(defbehavior target-flut-dangerous-event-handler target ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  (case arg2
    (('touched)
     (if ((method-of-type touching-shapes-entry prims-touching?)
          (the-as touching-shapes-entry (-> arg3 param 0))
          (-> self control)
          (the-as uint 224))
       (target-send-attack arg0
                           (the-as uint (-> self control unknown-symbol30))
                           (the-as touching-shapes-entry (-> arg3 param 0))
                           (-> self control unknown-dword50)
                           (-> self control unknown-dword51))
       (target-flut-standard-event-handler arg0 arg1 arg2 arg3)))
    (('attack 'attack-or-shove 'attack-invinc)
     (target-attacked arg2
                      (the-as attack-info (-> arg3 param 1))
                      arg0
                      (the-as touching-shapes-entry (-> arg3 param 0))
                      target-flut-hit))
    (else (target-flut-standard-event-handler arg0 arg1 arg2 arg3))))

(defstate target-flut-start (target)
  :event target-flut-standard-event-handler
  :exit
    (behavior ()
      (when (not (or (= (-> self next-state name) 'target-flut-stance)
                     (= (-> self next-state name) 'target-flut-walk)
                     (= (-> self next-state name) 'target-flut-jump)
                     (= (-> self next-state name) 'target-flut-double-jump)
                     (= (-> self next-state name) 'target-flut-hit-ground)
                     (= (-> self next-state name) 'target-flut-falling)
                     (= (-> self next-state name) 'target-flut-running-attack)
                     (= (-> self next-state name) 'target-flut-air-attack)
                     (= (-> self next-state name) 'target-flut-air-attack-hit-ground)
                     (= (-> self next-state name) 'target-flut-hit)
                     (= (-> self next-state name) 'target-flut-death)
                     (= (-> self next-state name) 'target-flut-get-on)
                     (= (-> self next-state name) 'target-flut-get-off)
                     (= (-> self next-state name) 'target-flut-get-off-jump)
                     (= (-> self next-state name) 'target-flut-grab)
                     (= (-> self next-state name) 'target-flut-clone-anim)))
        (let ((v1-33 (-> self manipy)))
          (when v1-33
            (deactivate (-> v1-33 0))
            (set! (-> self manipy) (the-as (pointer manipy) #f))))
        (logclear! (-> self control root-prim prim-core action) (collide-action flut))
        (set! (-> self control unknown-surface00) *walk-mods*)
        (logclear! (-> self state-flags) (state-flags use-alt-cam-pos))
        (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-collide-set! 'normal (the-as float 0.0))
        (set! (-> self control reaction) target-collision-reaction)
        (set! (-> self control unknown-vector12 quad) (the-as uint128 0))
        (remove-setting! 'sound-flava)
        (target-exit)))
  :code
    (behavior ((arg0 handle))
      (target-exit)
      (set! *display-profile* #f)
      (set! *display-entity-errors* #f)
      (set-setting! 'sound-flava #f 30.0 (music-flava flutflut))
      (if (zero? (-> self flut)) (set! (-> self flut) (new 'process 'flut-info)))
      (set! (-> self flut stick-lock) #f)
      (set! (-> self flut flap-sound-id) (new-sound-id))
      (set! (-> self flut entity) #f)
      (let ((v1-11 (handle->process arg0))) (if v1-11 (set! (-> self flut entity) (-> v1-11 entity))))
      (target-collide-set! 'flut (the-as float 0.0))
      (set! (-> self control transv quad) (the-as uint128 0))
      (set! (-> self control unknown-float01) 0.0)
      (logior! (-> self control root-prim prim-core action) (collide-action flut))
      (let ((s5-0 (-> self entity)))
        (set! (-> self entity) (-> self flut entity))
        (set! (-> self manipy)
              (manipy-spawn (-> self control trans) (-> self entity) *flutflut-sg* 'collide-shape-moving :to self))
        (set! (-> self entity) s5-0))
      (when (-> self manipy)
        (send-event (ppointer->process (-> self manipy))
                    'trans-hook
                    (lambda :behavior flutflut ()
                      (let* ((a0-0 (-> self parent-override))
                             (v1-0 (if a0-0 (-> a0-0 0 self-override))))
                        (set! (-> self root trans quad) (-> v1-0 flut flut-trans quad))
                        (let ((a0-4 (-> v1-0 flut flut-quat quad))) (set! (-> self root quat vec quad) a0-4))
                        (set! (-> self root scale quad) (-> v1-0 flut flut-scale quad))
                        (set! (-> self root ground-pat material) (the-as int (-> v1-0 control ground-pat material)))
                        (set! (-> self draw light-index) (the-as uint 255))
                        (let ((a0-13 (-> v1-0 draw color-mult quad))) (set! (-> self draw color-mult quad) a0-13))
                        (let ((a0-15 (-> v1-0 draw color-emissive quad))) (set! (-> self draw color-emissive quad) a0-15))
                        (set! (-> self draw secondary-interp) (-> v1-0 draw secondary-interp)))))
        (send-event (ppointer->process (-> self manipy)) 'anim-mode 'loop)
        (send-event (ppointer->process (-> self manipy)) 'art-joint-anim "flut-get-on" 0.0)
        (send-event (ppointer->process (-> self manipy)) 'blend-shape #t)
        (send-event (ppointer->process (-> self manipy))
                    'eval
                    (lambda :behavior target ()
                      (set! (-> self attack-info intersection z) (the-as float #f))
                      (let ((v1-1 (-> *target-shadow-control* settings shadow-dir quad)))
                        (set! (-> *flutflut-shadow-control* settings shadow-dir quad) v1-1))
                      (let ((v0-0 *flutflut-shadow-control*)) (set! (-> self draw shadow-ctrl) v0-0) v0-0))))
      (remove-exit)
      (go target-flut-get-on arg0))
  :post target-post)

(defstate target-flut-stance (target)
  :event target-flut-standard-event-handler
  :enter
    (behavior ()
      (set! (-> self control unknown-surface00) *flut-walk-mods*))
  :exit
    (-> target-flut-start
        exit)
  :trans
    (behavior ()
      (if (move-legs?) (go target-flut-walk))
      ;; og:preserve-this - High FPS Fix
      (if (and (recently-pressed? x) (can-jump? #f))
        (go target-flut-jump (-> *FLUT-bank* jump-height-min) (-> *FLUT-bank* jump-height-max)))
      (if (can-hands? #t) (go target-flut-running-attack))
      (if (and (not (logtest? (-> self control status) (cshape-moving-flags onsurf)))
               (and (time-elapsed? (-> self control unknown-dword11) (-> *FLUT-bank* ground-timeout))
                    (>= 0.0 (vector-dot (-> self control dynam gravity-normal) (-> self control transv)))
                    (let ((v1-37 (ja-group)))
                      (or (not (or (= v1-37 eichar-attack-punch-ja) (= v1-37 eichar-attack-punch-end-ja) (= v1-37 eichar-attack-punch-alt-end-ja)))
                          (< 4096.0 (target-height-above-ground))))))
        (go target-flut-falling #f)))
  :code
    (behavior ()
      (let ((gp-0 22))
        (let ((v1-2 (ja-group)))
          (cond
            ((or (= v1-2 eichar-flut-walk-ja) (= v1-2 eichar-flut-squash-run-ja)) (set! gp-0 60))
            ((ja-group? eichar-flut-get-on-ja) (ja-no-eval :num! (seek!)) (while (not (ja-done? 0)) (suspend) (ja-eval)))
            ((ja-group? eichar-flut-smack-surface-ja)
             (ja-no-eval :group! eichar-flut-smack-surface-end-ja :num! (seek!) :frame-num 0.0)
             (until (ja-done? 0)
               (suspend)
               (ja :num! (seek!))))
            ((ja-group? eichar-flut-running-attack-ja)
             (ja-no-eval :group! eichar-flut-running-attack-end-ja :num! (seek!) :frame-num 0.0)
             (until (ja-done? 0)
               (suspend)
               (ja :num! (seek!))))))
        (if (not (ja-group? eichar-flut-idle-ja)) (ja-channel-push! 1 (the-as time-frame gp-0))))
      (ja :group! eichar-flut-idle-ja)
      (loop
        (suspend)
        (ja :num! (loop!))))
  :post target-flut-post)

(defstate target-flut-walk (target)
  :event target-flut-standard-event-handler
  :enter
    (behavior ()
      (set-time! (-> self state-time))
      (set! (-> self control unknown-surface00) *flut-walk-mods*)
      (set! (-> self control unknown-uint20) (the-as uint (-> self control unknown-surface00 turnv)))
      (set! (-> self control unknown-int21) (the-as int (-> self control unknown-surface00 target-speed))))
  :exit
    (behavior ()
      (set! (-> self control unknown-surface00 turnv) (the-as float (-> self control unknown-uint20)))
      (set! (-> self control unknown-surface00 target-speed) (the-as float (-> self control unknown-uint30)))
      ((-> target-flut-start exit)))
  :trans
    (behavior ()
      (if (not (move-legs?)) (go target-flut-stance))
      ;; og:preserve-this - High FPS Fix
      (if (and (recently-pressed? x) (can-jump? #f))
        (go target-flut-jump (-> *FLUT-bank* jump-height-min) (-> *FLUT-bank* jump-height-max)))
      (if (can-hands? #t) (go target-flut-running-attack))
      (if (and (not (logtest? (-> self control status) (cshape-moving-flags onsurf)))
               (and (time-elapsed? (-> self control unknown-dword11) (-> *FLUT-bank* ground-timeout))
                    (>= 0.0 (vector-dot (-> self control dynam gravity-normal) (-> self control transv)))
                    (let ((v1-37 (ja-group)))
                      (or (not (or (= v1-37 eichar-attack-punch-ja) (= v1-37 eichar-attack-punch-end-ja) (= v1-37 eichar-attack-punch-alt-end-ja)))
                          (< 4096.0 (target-height-above-ground))))))
        (go target-flut-falling #f))
      (let ((f30-1 (fabs (deg-diff (quaternion-y-angle (-> self control dir-targ)) (y-angle (-> self control))))))
        (set! (-> self control unknown-surface00 turnv)
              (lerp-scale (the-as float (-> self control unknown-uint20))
                          (* 4.0 (the-as float (-> self control unknown-uint20)))
                          f30-1
                          (the-as float 8192.0)
                          (the-as float 21845.334)))
        (if (and (= (-> self control surf name) '*tar-surface*) (< 8192.0 f30-1))
          (seek! (-> self control unknown-surface00 target-speed) (the-as float 4096.0) (* 245760.0 (seconds-per-frame)))
          (seek! (-> self control unknown-surface00 target-speed)
                 (the-as float (-> self control unknown-uint30))
                 (* 81920.0 (seconds-per-frame))))))
  :code
    (behavior ()
      (let ((f28-0 0.0)
            (f30-0 0.0))
        (let ((gp-0 22))
          (cond
            ((ja-group? eichar-flut-idle-ja) (set! gp-0 60))
            ((let ((v1-9 (ja-group)))
               (or (= v1-9 eichar-flut-jump-ja)
                   (= v1-9 eichar-flut-jump-loop-ja)
                   (= v1-9 eichar-flut-air-attack-ja)
                   (= v1-9 eichar-flut-air-attack-land-ja)))
             (ja-channel-push! 1 (seconds 0.08))
             (ja-no-eval :group! eichar-flut-squash-run-ja :num! (seek!) :frame-num 0.0)
             (until (ja-done? 0)
               (suspend)
               (ja :num! (seek!)))))
          (set! f30-0
                (cond
                  ((ja-group? eichar-flut-squash-run-ja) (ja-channel-set! 2) 1.0)
                  ((ja-group? eichar-flut-walk-ja) (set! f28-0 (ja-frame-num 0)) (-> self skel root-channel 1 frame-interp))
                  (else (ja-channel-push! 2 (the-as time-frame gp-0)) f30-0))))
        (ja-no-eval :group! eichar-flut-walk-ja :num! (loop!) :dist 49152.0 :frame-num f28-0)
        (ja-no-eval :chan 1 :group! eichar-flut-run-ja :num! (identity (/ f28-0 2)) :frame-interp f30-0 :dist 40960.0)
        (loop
          (suspend)
          (let ((f0-13 (lerp-scale (the-as float 0.0)
                                   (the-as float 1.0)
                                   (-> self control unknown-float01)
                                   (the-as float 49152.0)
                                   (the-as float 77824.0))))
            (set! f30-0 (seek f30-0 f0-13 (* 4.0 (seconds-per-frame)))))
          (set! (-> self skel root-channel 1 frame-interp) f30-0)
          (let* ((f0-16 (current-cycle-distance (-> self skel)))
                 (f0-18 (/ (* 58.0 (-> self control unknown-float01)) (* 60.0 f0-16))))
            (if (= (-> self control surf name) '*tar-surface*) (set! f0-18 (* 0.4 (-> self control unknown-float12))))
            (ja :num! (loop! f0-18)))
          (ja :chan 1 :num-func num-func-identity :frame-num (* 0.5 (ja-frame-num 0)))
          (let ((f0-22 (ja-aframe-num 0)))
            (cond
              ((and (>= (-> self skel effect last-frame-num) 20.0) (< f0-22 20.0))
               (cpad-set-buzz! (-> *cpad-list* cpads 0) 1 51 (seconds 0.4)))
              ((and (< (-> self skel effect last-frame-num) 12.0) (>= f0-22 12.0))
               (cpad-set-buzz! (-> *cpad-list* cpads 0) 1 51 (seconds 0.4))))))))
  :post target-flut-post)

(defstate target-flut-jump (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (when (and (= message 'touched)
                 ((method-of-type touching-shapes-entry prims-touching?)
                  (the-as touching-shapes-entry (-> block param 0))
                  (-> self control)
                  (the-as uint 6))
                 (< 0.0
                    (vector-dot (-> self control dynam gravity-normal)
                                (vector-! (new 'stack-no-clear 'vector) (the-as vector (-> self control trans-old)) (-> self control trans)))))
        (send-event proc 'bonk (-> block param 0) (-> self control ground-impact-vel))
        (when (target-send-attack proc
                                  (the-as uint 'flut-bonk)
                                  (the-as touching-shapes-entry (-> block param 0))
                                  (-> self control unknown-dword50)
                                  (-> self control unknown-dword51))))
      (case message
        (('jump) (go target-flut-jump (the-as float (-> block param 0)) (the-as float (-> block param 0))))
        (else (target-flut-standard-event-handler proc argc message block))))
  :enter
    (behavior ((arg0 float) (arg1 float))
      (set-time! (-> self state-time))
      (sound-play "jump" :pitch -0.5)
      (init-var-jump arg0 arg1 (the-as vector #t) (the-as vector #t) (-> self control transv))
      (logclear! (-> self control status) (cshape-moving-flags onsurf onground tsurf))
      (set! (-> self control unknown-surface00) *flut-jump-mods*)
      (set! (-> self control unknown-float123)
            (fmax 0.0 (fmin 1.0 (* 0.00004359654 (+ -11468.8 (-> self control unknown-float01))))))
      (set! (-> self control unknown-float122)
            (fmax 0.0 (fmin 1.0 (* 0.000048828126 (+ -10240.0 (-> self control unknown-float01)))))))
  :exit
    (behavior ()
      (target-exit)
      ((-> target-flut-start exit)))
  :trans
    (behavior ()
      (set! (-> self control unknown-float123)
            (fmax (-> self control unknown-float123)
                  (* 0.003921569 (the float (-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) abutton (abutton-idx x)))))) ;; og:preserve-this abutton indexing
      (if (logtest? (-> self control status) (cshape-moving-flags onsurf)) (go target-flut-hit-ground))
      (if (and (cpad-pressed? (-> self control unknown-cpad-info00 number) x)
               (< (vector-dot (-> self control dynam gravity-normal) (-> self control transv)) 40960.0)
               (and (not (logtest? (-> self water flags) (water-flags wt09)))
                    (not (logtest? (-> self state-flags) (state-flags prevent-jump)))
                    (< 4096.0 (target-height-above-ground))))
        (go target-flut-double-jump (-> *FLUT-bank* double-jump-height-min) (-> *FLUT-bank* double-jump-height-max)))
      (if (and (cpad-pressed? (-> self control unknown-cpad-info00 number) square)
               (< (vector-dot (-> self control dynam gravity-normal) (-> self control transv)) 61440.0)
               (and (< -61440.0 (vector-dot (-> self control dynam gravity-normal) (-> self control transv)))
                    (time-elapsed? (-> self control unknown-dword36) (the-as time-frame (-> *TARGET-bank* stuck-timeout)))
                    (not (logtest? (-> self state-flags) (state-flags prevent-attack)))
                    (not (logtest? (-> self control unknown-surface01 flags) (surface-flags prevent-attacks-during-launch-jump surf08)))))
        (go target-flut-air-attack (-> *FLUT-bank* air-attack-speed)))
      (when (if (and (< (target-move-dist (-> *TARGET-bank* stuck-time)) (-> *TARGET-bank* stuck-distance))
                     (and (time-elapsed? (-> self state-time) (seconds 0.1))
                          (not (and *cheat-mode* (cpad-hold? (-> self control unknown-cpad-info00 number) r2)))))
              #t)
        (logior! (-> self control status) (cshape-moving-flags onsurf))
        enter-state
        'stuck
        (go target-flut-hit-ground))
      (mod-var-jump #t #t (cpad-hold? (-> self control unknown-cpad-info00 number) x) (-> self control transv))
      (seek! (-> self control unknown-float122)
             (fmax 0.0 (fmin 1.0 (* 0.000048828126 (+ -10240.0 (-> self control unknown-float01)))))
             (seconds-per-frame)))
  :code
    (behavior ((arg0 float) (arg1 float))
      (ja-channel-push! 2 (seconds 0.12))
      (ja :group! eichar-flut-jump-ja :num! min)
      (ja :chan 1 :group! eichar-flut-jump-forward-ja :num! (chan 0) :frame-interp (-> self control unknown-float122))
      (suspend)
      (ja :group! eichar-flut-jump-ja :num! (+!))
      (ja :chan 1 :group! eichar-flut-jump-forward-ja :num! (chan 0) :frame-interp (-> self control unknown-float122))
      (suspend)
      (until (ja-done? 0)
        (let ((f30-0 (vector-dot (-> self control dynam gravity-normal) (-> self control transv)))
              (f0-10 (/ (- 10.0 (ja-aframe-num 0)) (* (ja-step 0) (ja-speed 0))))
              (gp-1 (-> self skel root-channel 0)))
          (set! (-> gp-1 param 0) (the float (+ (-> gp-1 frame-group data 0 length) -1)))
          (let ((v1-45 (and (< 0.0 f30-0) (< 0.0 f0-10))))
            (set! (-> gp-1 param 1)
                  (the-as float
                          (if v1-45 (fmin (fmin 3.0 f0-10) (/ (* 5.0 f0-10) (the float (time-to-apex f30-0 (the-as float -245760.0))))) 1.0))))
          (joint-control-channel-group-eval! gp-1 (the-as art-joint-anim #f) num-func-seek!))
        (ja :chan 1 :num! (chan 0) :frame-interp (-> self control unknown-float122))
        (suspend))
      (ja-no-eval :group! eichar-flut-jump-loop-ja :num! (loop!) :frame-num 0.0)
      (ja :chan 1 :group! eichar-flut-jump-forward-loop-ja :num! (chan 0) :frame-interp (-> self control unknown-float122))
      (loop
        (suspend)
        (ja :group! eichar-flut-jump-loop-ja :num! (loop!))
        (ja :chan 1 :group! eichar-flut-jump-forward-loop-ja :num! (chan 0) :frame-interp (-> self control unknown-float122))))
  :post target-flut-post)

(defstate target-flut-double-jump (target)
  :event
    (-> target-flut-jump
        event)
  :enter
    (behavior ((arg0 float) (arg1 float))
      (set-time! (-> self state-time))
      (init-var-jump arg0 arg1 (the-as vector #t) (the-as vector #t) (-> self control transv))
      (set! (-> self control dynam gravity-max) 40960.0)
      (set! (-> self control dynam gravity-length) 245760.0)
      (logclear! (-> self control status) (cshape-moving-flags onsurf onground tsurf))
      (set! (-> self control unknown-surface00) *flut-double-jump-mods*))
  :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)
      ((-> target-flut-start exit)))
  :trans
    (behavior ()
      (if (logtest? (-> self control status) (cshape-moving-flags onsurf)) (go target-flut-hit-ground))
      ;; og:preserve-this - High FPS Fix
      (if (and (recently-pressed? square)
               (and (not (logtest? (-> self state-flags) (state-flags prevent-attack)))
                    (not (logtest? (-> self control unknown-surface01 flags) (surface-flags prevent-attacks-during-launch-jump surf08)))
                    (time-elapsed? (-> self control unknown-dword36) (the-as time-frame (-> *TARGET-bank* stuck-timeout)))
                    (< 4096.0 (target-height-above-ground))))
        (go target-flut-air-attack (-> *FLUT-bank* air-attack-speed)))
      (if (!= (-> self state-time) (current-time))
        (mod-var-jump #t #t (cpad-hold? (-> self control unknown-cpad-info00 number) x) (-> self control transv)))
      (if (ja-group? eichar-flut-double-jump-ja) (sound-play "flut-flap" :id (-> self flut flap-sound-id)))
      (seek! (-> self control unknown-float122)
             (fmax 0.0 (fmin 1.0 (* 0.000048828126 (+ -10240.0 (-> self control unknown-float01)))))
             (seconds-per-frame)))
  :code
    (behavior ((arg0 float) (arg1 float))
      (ja-channel-push! 1 (seconds 0.05))
      (ja-no-eval :group! eichar-flut-double-jump-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (cpad-set-buzz! (-> *cpad-list* cpads 0) 0 3 (seconds 0.1))
        (suspend)
        (ja :num! (seek!)))
      (set! (-> self control unknown-surface00) *flut-jump-mods*)
      (dotimes (gp-0 1)
        (ja-no-eval :group! eichar-flut-double-jump-ja :num! (seek!) :frame-num (ja-aframe (the-as float 14.0) 0))
        (until (ja-done? 0)
          (cpad-set-buzz! (-> *cpad-list* cpads 0) 0 3 (seconds 0.1))
          (suspend)
          (ja :num! (seek!))))
      (while (< 8192.0 (target-height-above-ground))
        (suspend)
        (cpad-set-buzz! (-> *cpad-list* cpads 0) 0 3 (seconds 0.1))
        (ja :num! (loop!))
        (if (< (ja-aframe-num 0) 14.0) (ja :num-func num-func-identity :frame-num (ja-aframe (the-as float 14.0) 0)))
        (seek! (-> self control dynam gravity-max)
               (-> self control unknown-dynamics00 gravity-max)
               (* 163840.0 (seconds-per-frame)))
        (seek! (-> self control dynam gravity-length)
               (-> self control unknown-dynamics00 gravity-length)
               (* 163840.0 (seconds-per-frame))))
      (current-time)
      (ja-channel-push! 2 (seconds 0.1))
      (ja-no-eval :group! eichar-flut-jump-loop-ja :num! (loop!) :frame-num 0.0)
      (ja :chan 1 :group! eichar-flut-jump-forward-loop-ja :num! min :frame-interp (-> self control unknown-float122))
      (loop
        (suspend)
        (seek! (-> self control dynam gravity-max)
               (-> self control unknown-dynamics00 gravity-max)
               (* 163840.0 (seconds-per-frame)))
        (seek! (-> self control dynam gravity-length)
               (-> self control unknown-dynamics00 gravity-length)
               (* 163840.0 (seconds-per-frame)))
        (ja :num! (loop! max))
        (ja :chan 1 :num! (chan 0) :frame-interp (-> self control unknown-float122))))
  :post target-flut-post)

(defstate target-flut-hit-ground (target)
  :event target-flut-standard-event-handler
  :enter
    (behavior ()
      (target-land-effect)
      (if (< 40960.0 (-> self control ground-impact-vel)) (cpad-set-buzz! (-> *cpad-list* cpads 0) 1 178 (seconds 0.2)))
      (set! (-> self control unknown-dword31) 0)
      (set! (-> self control unknown-dword33) 0)
      (set! (-> self control unknown-surface00) *flut-walk-mods*))
  :exit
    (-> target-flut-start
        exit)
  :trans
    (behavior ()
      ;; og:preserve-this - High FPS Fix
      (if (and (recently-pressed? x) (can-jump? #f))
        (go target-flut-jump (-> *FLUT-bank* jump-height-min) (-> *FLUT-bank* jump-height-max)))
      (if (move-legs?) (go target-flut-walk))
      (if (and (not (logtest? (-> self control status) (cshape-moving-flags onsurf)))
               (and (time-elapsed? (-> self control unknown-dword11) (-> *FLUT-bank* ground-timeout))
                    (>= 0.0 (vector-dot (-> self control dynam gravity-normal) (-> self control transv)))
                    (let ((v1-34 (ja-group)))
                      (or (not (or (= v1-34 eichar-attack-punch-ja) (= v1-34 eichar-attack-punch-end-ja) (= v1-34 eichar-attack-punch-alt-end-ja)))
                          (< 4096.0 (target-height-above-ground))))))
        (go target-flut-falling #f)))
  :code
    (behavior ()
      (let ((t9-0 target-flut-hit-ground-anim)) (t9-0))
      (go target-flut-stance))
  :post target-flut-post)

(defstate target-flut-falling (target)
  :event
    (-> target-flut-jump
        event)
  :enter
    (behavior ((arg0 symbol))
      (set! (-> self control unknown-surface00) *flut-jump-mods*)
      (set-time! (-> self state-time)))
  :exit
    (-> target-flut-start
        exit)
  :trans
    (behavior ()
      (when (or (logtest? (-> self control status) (cshape-moving-flags onsurf))
                (if (and (< (target-move-dist (-> *TARGET-bank* stuck-time)) (-> *TARGET-bank* stuck-distance))
                         (and (time-elapsed? (-> self state-time) (/ (the-as int (-> *TARGET-bank* stuck-time)) 2))
                              (not (and *cheat-mode* (cpad-hold? (-> self control unknown-cpad-info00 number) r2)))))
                  #t))
        (logior! (-> self control status) (cshape-moving-flags onsurf))
        (go target-flut-hit-ground))
      (seek! (-> self control unknown-float122)
             (fmax 0.0 (fmin 1.0 (* 0.000048828126 (+ -10240.0 (-> self control unknown-float01)))))
             (seconds-per-frame)))
  :code
    (behavior ((arg0 symbol))
      (cond
        ((ja-group? eichar-flut-jump-loop-ja))
        ((ja-group? eichar-flut-double-jump-ja) (ja-channel-push! 2 (seconds 0.2)))
        (else (ja-channel-push! 2 (seconds 0.5))))
      (ja-no-eval :group! eichar-flut-jump-loop-ja :num! (loop!) :frame-num 0.0)
      (ja :chan 1 :group! eichar-flut-jump-forward-loop-ja :num! min :frame-interp (-> self control unknown-float122))
      (loop
        (suspend)
        (ja :num! (loop! max))
        (ja :chan 1 :num! (chan 0) :frame-interp (-> self control unknown-float122))))
  :post target-flut-post)

(defstate target-flut-running-attack (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (case message
        (('touched)
         (cond
           (((method-of-type touching-shapes-entry prims-touching?)
             (the-as touching-shapes-entry (-> block param 0))
             (-> self control)
             (the-as uint 224))
            (let ((gp-1 (target-send-attack proc
                                            (the-as uint (-> self control unknown-symbol30))
                                            (the-as touching-shapes-entry (-> block param 0))
                                            (-> self control unknown-dword50)
                                            (-> self control unknown-dword51))))
              (when gp-1
                (set! (-> self control unknown-uint20) (the-as uint (current-time)))
                (let ((v1-9 (if (and (nonzero? proc) (type-type? (-> proc type) process-drawable)) proc)))
                  (when v1-9
                    (let* ((s5-1 (-> (the-as process-drawable v1-9) root))
                           (v1-11 (if (and (nonzero? s5-1) (type-type? (-> s5-1 type) collide-shape)) s5-1)))
                      (if (and v1-11
                               (or (logtest? (-> (the-as collide-shape v1-11) root-prim prim-core collide-as) (collide-kind enemy))
                                   (logtest? (-> (the-as collide-shape v1-11) root-prim prim-core action) (collide-action attackable))))
                        (set! (-> self control unknown-uint31) (the-as uint 1))))))
                (when (or (= gp-1 'die) (= gp-1 'push))
                  (let ((v0-2 (the-as object (current-time)))) (set! (-> self control unknown-int21) (the-as int v0-2)) v0-2)))))
           (else (target-flut-dangerous-event-handler proc argc message block))))
        (else (target-flut-dangerous-event-handler proc argc message block))))
  :enter
    (behavior ()
      (set-time! (-> self state-time))
      (set! (-> self control unknown-uint20) (the-as uint 0))
      (set! (-> self control unknown-int21) 0)
      (set! (-> self control unknown-uint31) (the-as uint 0))
      (set! (-> self control unknown-surface00) *flut-run-attack-mods*)
      (set! (-> *run-attack-mods* turnv) 655360.0)
      (set! (-> *run-attack-mods* turnvv) 655360.0)
      (target-start-attack)
      (target-danger-set! 'flut-attack #f)
      (when (and (and (= (-> self fact eco-type) (pickup-type eco-yellow)) (>= (-> self fact eco-level) 1.0))
                 (time-elapsed? (-> self control unknown-dword82) (seconds 0.25)))
        (let ((gp-0 (vector-z-quaternion! (new 'stack-no-clear 'vector) (-> self control quat)))
              (s5-0 (vector<-cspace! (new 'stack-no-clear 'vector) (-> self manipy 0 node-list data 32))))
          (set! (-> gp-0 y) 0.0)
          (vector-normalize! gp-0 (+ 81920.0 (-> *TARGET-bank* yellow-projectile-speed)))
          (vector+! gp-0 gp-0 (-> self control transv))
          (process-spawn projectile-yellow
                         :init
                         projectile-init-by-other
                         (-> self entity)
                         s5-0
                         gp-0
                         (if (>= (-> self fact eco-level) (-> *FACT-bank* eco-level-max)) 281 265)
                         #f
                         :to
                         self))
        (set-time! (-> self control unknown-dword82))))
  :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))
      (set! (-> *run-attack-mods* turnv) 0.0)
      (set! (-> *run-attack-mods* turnvv) 0.0)
      (set-time! (-> self control unknown-dword31))
      (target-exit))
  :trans
    (behavior ()
      (when (!= (-> self state-time) (current-time))
        (if (and (or (smack-surface? #t)
                     (and (>= (-> self control unknown-float63) 0.7) (not (logtest? (-> self control status) (cshape-moving-flags t-act)))))
                 (begin
                   (set! (-> self control unknown-int21) (the-as int (current-time)))
                   (set! (-> self control unknown-float81) 0.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-1 f0-5)
                            (f2-1 (fmin 0.0 f30-0)))
                       (vector+! (-> self control transv)
                                 (vector-float*! (-> self control transv) (-> self control dynam gravity-normal) f2-1)
                                 (vector-float*! gp-0 gp-0 (/ f0-5 f1-1)))))
                   #t)
                 (or (zero? (-> self control unknown-uint20))
                     (>= (the-as uint (- (current-time) (the-as int (-> self control unknown-uint20)))) (the-as uint 12)))
                 (!= (-> self control unknown-uint31) 1))
          (target-shoved (meters 2) (-> *TARGET-bank* smack-surface-height) (the-as process #f) target-flut-hit))
        (if (and (logtest? (-> self water flags) (water-flags wt09)) (zero? (mod (- (current-time) (-> self state-time)) 21)))
          (create-splash (-> self water)
                         (the-as float 0.6)
                         (vector<-cspace! (new 'stack-no-clear 'vector) (joint-node eichar-lod0-jg mouth))
                         0
                         (-> self control transv)))))
  :code
    (behavior ()
      (ja-channel-push! 1 (seconds 0.02))
      (sound-play "flut-hit")
      (ja :group! eichar-flut-running-attack-ja :num! min)
      (set! (-> self control dynam gravity-max) 368640.0)
      (set! (-> self control dynam gravity-length) 368640.0)
      (let ((f28-0 0.0)
            (f30-0 (the-as float (if (= (-> self control unknown-dword82) (current-time)) 0.2 0.8))))
        (until (or (ja-done? 0) (< f30-0 0.05))
          (compute-alignment! (-> self align))
          (when (not (ja-min? 0))
            (cond
              ((and (>= (ja-aframe-num 0) 20.0)
                    (and (and (not (logtest? (-> self control status) (cshape-moving-flags onsurf)))
                              (time-elapsed? (-> self control unknown-dword11) (-> *FLUT-bank* ground-timeout))
                              (>= 0.0 (vector-dot (-> self control dynam gravity-normal) (-> self control transv)))
                              (let ((v1-39 (ja-group)))
                                (or (not (or (= v1-39 eichar-attack-punch-ja) (= v1-39 eichar-attack-punch-end-ja) (= v1-39 eichar-attack-punch-alt-end-ja)))
                                    (< 4096.0 (target-height-above-ground)))))
                         (>= (the-as uint (- (current-time) (the-as int (-> self control unknown-uint20)))) (the-as uint 12))))
               (go target-flut-falling #f))
              ((and (nonzero? (-> self control unknown-uint30))
                    (>= (the-as uint (- (current-time) (the-as int (-> self control unknown-uint30)))) (the-as uint 12)))
               (set-forward-vel (the-as float 0.0))
               (set! f30-0 0.0))
              ((ja-done? 0) (set-forward-vel f28-0))
              (else
               (set! f28-0 (* f30-0 (target-align-vel-z-adjust (-> self align delta trans z)) (-> *display* frames-per-second)))
               (set-forward-vel f28-0))))
          (let ((gp-2 (new-stack-vector0)))
            (vector-matrix*! gp-2 (-> self control transv) (-> self control unknown-matrix00))
            (set! (-> gp-2 y) 0.0)
            (vector-matrix*! (-> self control unknown-vector120) gp-2 (-> self control unknown-matrix01)))
          (suspend)
          (ja :num! (seek! max (-> self control unknown-surface01 align-speed)))
          (if (time-elapsed? (-> self state-time) (seconds 0.1)) (set! (-> *flut-run-attack-mods* turnvv) 0.0))
          (if (time-elapsed? (-> self state-time) (seconds 0.1))
            (set! f30-0 (* f30-0 (the-as float (fmin 1.0 (the-as float (-> self control unknown-float140))))))))
        (if (and (not (logtest? (-> self control status) (cshape-moving-flags onsurf)))
                 (time-elapsed? (-> self control unknown-dword11) (-> *FLUT-bank* ground-timeout))
                 (>= 0.0 (vector-dot (-> self control dynam gravity-normal) (-> self control transv)))
                 (let ((v1-105 (ja-group)))
                   (or (not (or (= v1-105 eichar-attack-punch-ja) (= v1-105 eichar-attack-punch-end-ja) (= v1-105 eichar-attack-punch-alt-end-ja)))
                       (< 4096.0 (target-height-above-ground)))))
          (go target-flut-falling #f))
        (when (!= f30-0 0.0)
          (set! (-> self trans-hook) (-> target-flut-hit-ground trans))
          (if (not (ja-done? 0)) (ja-channel-push! 1 (seconds 0.05)))
          (ja-no-eval :group! eichar-flut-running-attack-end-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) f30-0)
            (suspend)
            (ja :num! (seek!)))))
      (go target-flut-stance))
  :post target-flut-post)

(defstate target-flut-air-attack (target)
  :event
    (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
      (if (and (= message 'touched)
               ((method-of-type touching-shapes-entry prims-touching?)
                (the-as touching-shapes-entry (-> block param 0))
                (-> self control)
                (the-as uint 6))
               (< 0.0
                  (vector-dot (-> self control dynam gravity-normal)
                              (vector-! (new 'stack-no-clear 'vector) (the-as vector (-> self control trans-old)) (-> self control trans)))))
        (send-event proc 'bonk (-> block param 0) (-> self control ground-impact-vel)))
      (case message
        (('jump) (go target-flut-jump (the-as float (-> block param 0)) (the-as float (-> block param 0))))
        (else (target-flut-dangerous-event-handler proc argc message block))))
  :enter
    (behavior ((arg0 float))
      (set-forward-vel arg0)
      (set-time! (-> self state-time))
      (logclear! (-> self control status) (cshape-moving-flags onsurf onground tsurf))
      (set! (-> self control unknown-surface00) *flut-air-attack-mods*)
      (target-start-attack)
      (target-danger-set! 'flut-attack #f)
      (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 0.0))
          (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 ()
      (target-danger-set! 'harmless #f)
      (set! (-> self control dynam gravity-max) (-> self control unknown-dynamics00 gravity-max))
      (set! (-> self control dynam gravity-length) (-> self control unknown-dynamics00 gravity-length))
      (set! (-> self control dynam gravity quad) (-> self control unknown-dynamics00 gravity quad)))
  :trans
    (behavior ()
      (let ((s5-0 (new-stack-vector0)))
        (vector-z-quaternion! s5-0 (-> self control unknown-quaternion00))
        (let ((gp-0 (new-stack-vector0))
              (f30-0 (vector-dot s5-0 (-> self control transv))))
          0.0
          (vector-! gp-0 (-> self control transv) (vector-float*! gp-0 s5-0 f30-0))
          (let* ((f0-3 (vector-length gp-0))
                 (f1-0 f0-3))
            (if (< f30-0 0.0) (set! f30-0 0.0))
            (vector+! (-> self control transv)
                      (vector-float*! (-> self control transv) s5-0 f30-0)
                      (vector-float*! gp-0 gp-0 (/ f0-3 f1-0))))))
      (when (logtest? (-> self control status) (cshape-moving-flags onsurf))
        (logior! (-> self control status) (cshape-moving-flags onsurf))
        (remove-exit)
        (go target-flut-air-attack-hit-ground))
      (when (if (and (< (target-move-dist (-> *TARGET-bank* stuck-time)) 4096.0)
                     (and (time-elapsed? (-> self state-time) (seconds 0.5))
                          (not (and *cheat-mode* (cpad-hold? (-> self control unknown-cpad-info00 number) r2)))))
              #t)
        (logior! (-> self control status) (cshape-moving-flags onsurf))
        (go target-flut-hit-ground)))
  :code
    (behavior ((arg0 float))
      (sound-play "flut-hit" :pitch -0.5)
      (ja-channel-push! 1 (seconds 0.05))
      (ja-no-eval :group! eichar-flut-air-attack-ja :num! (seek! (ja-aframe (the-as float 8.0) 0)) :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))
        (suspend)
        (ja :num! (seek! (ja-aframe (the-as float 8.0) 0))))
      (ja-no-eval :group! eichar-flut-air-attack-ja :num! (seek!) :frame-num (ja-aframe (the-as float 8.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))
        (suspend)
        (ja :num! (seek!)))
      (ja :group! eichar-flut-air-attack-loop-ja :num! min)
      (loop
        (suspend)))
  :post target-flut-post)

(defstate target-flut-air-attack-hit-ground (target)
  :event target-flut-standard-event-handler
  :enter
    (behavior ()
      (target-land-effect)
      (cpad-set-buzz! (-> *cpad-list* cpads 0) 1 255 (seconds 0.4))
      (set! (-> self control unknown-dword31) 0)
      (set! (-> self control unknown-dword33) 0)
      (set! (-> self control unknown-surface00) *flut-air-attack-mods*)
      (sound-play "flop-land" :pitch -0.4)
      (effect-control-method-10 (-> self skel effect) 'group-flut-attack-strike-ground (ja-frame-num 0) 0)
      (let ((gp-2 (process-spawn touch-tracker :init touch-tracker-init (-> self control trans) 4096.0 30 :to self)))
        (send-event (ppointer->process gp-2) 'event 'attack 'flut-attack)
        (send-event (ppointer->process gp-2)
                    'function
                    (lambda :behavior target ((arg0 nav-enemy))
                      (seek! (-> arg0 collide-info root-prim local-sphere w) (the-as float 28672.0) (* 286720.0 (seconds-per-frame)))
                      (update-transforms! (-> arg0 collide-info))
                      (none)))))
  :exit
    (-> target-flut-air-attack
        exit)
  :trans
    (-> target-flut-hit-ground
        trans)
  :code
    (behavior ()
      (ja-channel-set! 1)
      (ja-no-eval :group! eichar-flut-air-attack-land-ja :num! (seek! (ja-aframe (the-as float 22.0) 0)) :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))
        (suspend)
        (ja :num! (seek! (ja-aframe (the-as float 22.0) 0))))
      (target-danger-set! 'harmless #f)
      (ja-no-eval :group! eichar-flut-air-attack-land-ja :num! (seek!) :frame-num (ja-aframe (the-as float 22.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))
        (suspend)
        (ja :num! (seek!)))
      (go target-flut-stance))
  :post target-flut-post)

(defstate target-flut-hit (target)
  :event target-flut-standard-event-handler
  :exit
    (behavior ()
      (if (!= (-> self next-state name) 'target-flut-death) (logclear! (-> self state-flags) (state-flags being-attacked dying)))
      (target-exit)
      ((-> target-flut-start exit)))
  :trans
    (behavior ()
      (when (= *cheat-mode* 'debug)
        (when (and (not *pause-lock*) (cpad-hold? (-> self control unknown-cpad-info00 number) r2))
          (pickup-collectable! (-> self fact) (pickup-type eco-green) (the-as float 1.0) (the-as handle #f))
          (go target-flut-stance))))
  :code
    (behavior ((arg0 symbol) (arg1 attack-info))
      (set-time! (-> self state-time))
      (let ((gp-0 (-> self attack-info)))
        (let ((s5-0 (new 'stack-no-clear 'vector)))
          (let ((v1-2 gp-0))
            (set! (-> v1-2 attacker) (the-as handle #f))
            (set! (-> v1-2 mode) 'generic)
            (set! (-> v1-2 shove-back) 10240.0)
            (set! (-> v1-2 shove-up) 9011.2)
            (set! (-> v1-2 angle) #f)
            (set! (-> v1-2 trans quad) (-> self control trans quad))
            (set! (-> v1-2 control) 0.0)
            (set! (-> v1-2 invinc-time) (-> *TARGET-bank* hit-invulnerable-timeout)))
          (case arg0
            (('shove)
             (let ((v1-5 gp-0))
               (set! (-> v1-5 shove-back) (-> *TARGET-bank* smack-surface-dist))
               (set! (-> v1-5 shove-up) (-> *TARGET-bank* smack-surface-height))
               (set! (-> v1-5 angle) 'shove))))
          (combine! gp-0 arg1)
          (when (not (logtest? (-> gp-0 mask) (attack-mask vector)))
            (vector-z-quaternion! (-> gp-0 vector) (-> self control unknown-quaternion00))
            (vector-xz-normalize! (-> gp-0 vector) (- (fabs (-> gp-0 shove-back))))
            (set! (-> gp-0 vector y) (-> gp-0 shove-up)))
          (set! (-> s5-0 quad) (-> gp-0 vector quad))
          (let ((f0-10 (vector-dot (vector-normalize-copy! (new 'stack-no-clear 'vector) s5-0 (the-as float 1.0))
                                   (vector-z-quaternion! (new 'stack-no-clear 'vector) (-> self control unknown-quaternion00)))))
            (if (not (-> self attack-info angle)) (set! (-> self attack-info angle) (if (>= 0.0 f0-10) 'front 'back))))
          (when (= arg0 'attack)
            (logior! (-> self state-flags) (state-flags being-attacked))
            (set-time! (-> self game hit-time))
            (case (-> gp-0 mode)
              (('endlessfall)
               (cond
                 ((= (-> self game mode) 'debug)
                  (let ((s4-1 (new-stack-vector0)))
                    (set! (-> s4-1 quad) (-> self control last-known-safe-ground quad))
                    (ja-channel-set! 0)
                    (suspend-for (seconds 1))
                    (move-to-point! (-> self control) s4-1))
                  (set! (-> (&-> (-> self control) unknown-qword00) 0) (-> self control trans quad))
                  (send-event *camera* 'teleport)
                  (go target-flut-stance))
                 (else
                  (pickup-collectable! (-> self fact) (pickup-type eco-green) (the-as float -1000.0) (the-as handle #f))
                  (go target-flut-death (-> gp-0 mode)))))
              (('water-vol 'sharkey)
               (pickup-collectable! (-> self fact) (pickup-type eco-green) (the-as float -1000.0) (the-as handle #f))
               (if (= (-> self game mode) 'play) (go target-flut-death (-> gp-0 mode))))
              (('death) (pickup-collectable! (-> self fact) (pickup-type eco-green) (the-as float -1000.0) (the-as handle #f)))
              (else
               (pickup-collectable! (-> self fact) (pickup-type eco-green) (- (-> *FACT-bank* health-single-inc)) (the-as handle #f))))
            (target-hit-effect gp-0)
            (sound-play "flut-hit" :pitch -1))
          (set! (-> self control unknown-surface00) *smack-mods*)
          (let ((f30-0 1.0))
            (case (-> gp-0 angle)
              (('shove)
               (when (not (ja-group? eichar-flut-smack-surface-ja))
                 (ja-channel-set! 1)
                 (ja :group! eichar-flut-smack-surface-ja :num! min))
               (sound-play "smack-surface")
               (sound-play "flut-hit" :pitch 1))
              (else
               (when (not (ja-group? eichar-flut-hit-back-ja))
                 (ja-channel-push! 1 (seconds 0.075))
                 (ja :group! eichar-flut-hit-back-ja :num! min))))
            (target-hit-move gp-0 (target-hit-orient gp-0 s5-0) target-flut-falling-anim-trans f30-0)))
        (if (and (= (-> self game mode) 'play) (>= 0.0 (-> self fact health))) (go target-flut-death (-> gp-0 mode))))
      (go target-flut-hit-ground))
  :post target-flut-post)

(defstate target-flut-death (target)
  :event
    (-> target-death
        event)
  :exit
    (behavior ()
      (logclear! (-> self state-flags) (state-flags being-attacked dying))
      (target-exit)
      (remove-setting! 'process-mask)
      (apply-settings *setting-control*))
  :trans
    (-> target-hit
        trans)
  :code
    (behavior ((arg0 symbol))
      (local-vars (v1-104 symbol))
      (logior! (-> self state-flags) (state-flags dying))
      (set! (-> self neck flex-blend) 0.0)
      (target-timed-invulnerable-off self)
      (add-setting! 'process-mask 'set 0.0 (process-mask enemy platform projectile death))
      (apply-settings *setting-control*)
      (set! (-> self control transv quad) (the-as uint128 0))
      (cond
        ((or (= arg0 'none) (= arg0 'water-vol) (= arg0 'sharkey)))
        ((= arg0 'endlessfall)
         (sound-play "death-fall")
         (sound-play "flut-hit" :vol 70 :pitch -1.4)
         (camera-change-to (the-as string cam-endlessfall) 30 #f)
         (set! (-> self control pat-ignore-mask unknown-bit) 1)
         (logclear! (-> self water flags) (water-flags wt04))
         (let ((f30-0 (fmin -4096.0 (- (-> self control ground-impact-vel)))))
           (set! (-> self control unknown-uint20) (the-as uint f30-0))
           (let ((gp-3 (new-stack-vector0)))
             (let ((f0-3 (vector-dot (-> self control dynam gravity-normal) (-> self control transv))))
               0.0
               (vector-! gp-3 (-> self control transv) (vector-float*! gp-3 (-> self control dynam gravity-normal) f0-3)))
             (let* ((f0-4 (vector-length gp-3))
                    (f1-3 f0-4))
               (vector+! (-> self control transv)
                         (vector-float*! (-> self control transv) (-> self control dynam gravity-normal) f30-0)
                         (vector-float*! gp-3 gp-3 (/ f0-4 f1-3))))))
         (suspend-for (seconds 1)
           (target-flut-falling-anim-trans)
           (vector-seek! (-> self draw color-mult) *zero-vector* (seconds-per-frame))
           (let ((s5-2 (new-stack-vector0))
                 (f30-1 (the-as number (vector-dot (-> self control dynam gravity-normal) (-> self control transv)))))
             0.0
             (vector-! s5-2
                       (-> self control transv)
                       (vector-float*! s5-2 (-> self control dynam gravity-normal) (the-as float f30-1)))
             (let* ((f0-10 (vector-length s5-2))
                    (f1-4 f0-10))
               (if (< (the-as float (-> self control unknown-uint20)) (the-as float f30-1)) (set! f30-1 (-> self control unknown-uint20)))
               (vector+! (-> self control transv)
                         (vector-float*! (-> self control transv) (-> self control dynam gravity-normal) (the-as float f30-1))
                         (vector-float*! s5-2 s5-2 (/ f0-10 f1-4)))))
           (target-flut-post-post))
         (camera-change-to (the-as string 'base) 0 #f))
        (else
         (set! (-> self control unknown-surface00) *neutral-mods*)
         (ja-channel-push! 1 (seconds 0.1))
         (ja-no-eval :group! eichar-flut-deatha-ja :num! (seek!) :frame-num 0.0)
         (until (ja-done? 0)
           (compute-alignment! (-> self align))
           (let ((gp-5 (new 'stack-no-clear 'vector)))
             (when (not (logtest? (-> self align flags) (align-flags disabled)))
               (vector-matrix*! gp-5 (the-as vector (-> self align delta)) (-> self control unknown-matrix01))
               (vector-float*! (-> self control transv) gp-5 (-> *display* frames-per-second))))
           (suspend)
           (ja :num! (seek!)))))
      (set! (-> self control transv quad) (the-as uint128 0))
      (initialize! (-> self game) 'dead (the-as game-save #f) (the-as string #f))
      (set-time! (-> self state-time))
      (until v1-104
        (suspend)
        (set! v1-104 (and (time-elapsed? (-> self state-time) (seconds 1)) (not (movie?)))))
      (go target-flut-stance))
  :post target-no-stick-post)

(defstate target-flut-get-on (target)
  :event target-generic-event-handler
  :exit
    (-> target-flut-start
        exit)
  :code
    (behavior ((arg0 handle))
      (set! (-> self control transv quad) (the-as uint128 0))
      (set! (-> self alt-cam-pos quad) (-> (&-> (-> self control) unknown-qword00) 0))
      (logior! (-> self state-flags) (state-flags use-alt-cam-pos))
      (set-time! (-> self state-time))
      (let ((gp-0 (new 'stack-no-clear 'vector)))
        (set! (-> gp-0 quad) (-> self control trans quad))
        (let ((s5-0 (new 'stack-no-clear 'vector)))
          (set! (-> s5-0 quad) (-> self control trans quad))
          (quaternion-copy! (-> self control unknown-quaternion02) (-> self control quat))
          (quaternion-copy! (-> self control unknown-quaternion03) (-> self control unknown-quaternion00))
          (set! (-> self control unknown-uint20) (the-as uint (-> self control unknown-vector11 y)))
          (let* ((s3-0 (handle->process arg0))
                 (s4-1 (if (and (nonzero? s3-0) (type-type? (-> s3-0 type) process-drawable)) s3-0)))
            (when s4-1
              (set! (-> s5-0 quad) (-> (the-as process-drawable s4-1) root trans quad))
              (quaternion-copy! (-> self control unknown-quaternion03) (-> (the-as process-drawable s4-1) root quat))
              (send-event s4-1 'trans (-> self flut flut-trans))
              (quaternion-copy! (the-as quaternion (-> self flut flut-quat)) (-> (the-as process-drawable s4-1) root quat))
              (set! (-> self flut flut-scale quad) (-> (the-as process-drawable s4-1) root scale quad))
              (set! (-> self control unknown-int21) (the-as int (-> self flut flut-trans y)))))
          (set! (-> self control unknown-vector102 quad) (-> gp-0 quad))
          (set! (-> self control unknown-vector103 quad) (-> s5-0 quad))))
      (let ((gp-1 #f))
        (sound-play "uppercut")
        (ja-channel-push! 1 (seconds 0.05))
        (ja-no-eval :group! eichar-flut-get-on-ja :num! (seek! (ja-aframe (the-as float 24.0) 0)) :frame-num 0.0)
        (until (ja-done? 0)
          (when (and (not gp-1) (= (-> self skel root-channel 0) (-> self skel channel)))
            (send-event (ppointer->process (-> self manipy)) 'anim-mode 'clone-anim)
            (set! gp-1 #t))
          (set! (-> self control transv quad) (the-as uint128 0))
          (suspend)
          (ja :num! (seek! (ja-aframe (the-as float 24.0) 0)))))
      (sound-play "flut-coo")
      (logclear! (-> self state-flags) (state-flags use-alt-cam-pos))
      (set! (-> self control transv quad) (the-as uint128 0))
      (quaternion-copy! (-> self control quat) (-> self control unknown-quaternion00))
      (rot->dir-targ! (-> self control))
      (go target-flut-stance))
  :post
    (behavior ()
      (let ((gp-0 (new 'stack-no-clear 'vector))
            (f30-0 (fmin 1.0 (* 0.0044444446 (the float (- (current-time) (-> self state-time)))))))
        (vector-lerp! gp-0 (-> self control unknown-vector102) (-> self control unknown-vector103) f30-0)
        (set! (-> gp-0 y)
              (lerp (-> self control unknown-vector102 y)
                    (-> self control unknown-vector103 y)
                    (fmax 0.0 (fmin 1.0 (* 0.006666667 (the float (+ (- (the-as int (-> self state-time))) (current-time))))))))
        (move-to-point! (-> self control) gp-0)
        (quaternion-slerp! (-> self control unknown-quaternion00)
                           (-> self control unknown-quaternion02)
                           (-> self control unknown-quaternion03)
                           f30-0))
      (target-no-move-post)))

(defstate target-flut-get-off (target)
  :event target-generic-event-handler
  :exit
    (-> target-flut-start
        exit)
  :code
    (behavior ((arg0 handle))
      (set-forward-vel (the-as float 0.0))
      (let ((s5-0 0))
        (while (not (logtest? (-> self control status) (cshape-moving-flags onsurf)))
          (target-flut-falling-anim-trans)
          (+! s5-0 (- (current-time) (-> *display* old-base-frame-counter)))
          (suspend)))
      (go target-flut-get-off-jump arg0))
  :post
    (behavior ()
      (target-no-stick-post)
      (target-flut-post-post)))

(defstate target-flut-get-off-jump (target)
  :event target-generic-event-handler
  :exit
    (-> target-flut-start
        exit)
  :code
    (behavior ((arg0 handle))
      (set-time! (-> self state-time))
      (set! (-> self control transv quad) (the-as uint128 0))
      (let ((gp-0 (new 'stack-no-clear 'vector)))
        (set! (-> gp-0 quad) (-> self control trans quad))
        (let ((s4-0 (new 'stack-no-clear 'vector)))
          (set! (-> s4-0 quad) (-> self control trans quad))
          (quaternion-copy! (-> self control unknown-quaternion02) (-> self control quat))
          (quaternion-copy! (-> self control unknown-quaternion03) (-> self control unknown-quaternion00))
          (set! (-> self control unknown-uint20) (the-as uint (-> self control unknown-vector11 y)))
          (let* ((s2-0 (handle->process arg0))
                 (s3-0 (if (and (nonzero? s2-0) (type-type? (-> s2-0 type) process-drawable)) s2-0)))
            (when s3-0
              (set! (-> s4-0 quad) (-> (the-as process-drawable s3-0) root trans quad))
              (set-yaw-angle-clear-roll-pitch! (-> (the-as process-drawable s3-0) root) (quaternion-y-angle (-> self control quat)))
              (quaternion-copy! (-> self control unknown-quaternion03) (-> (the-as process-drawable s3-0) root quat))
              (send-event s3-0 'trans (-> self flut flut-trans))
              (quaternion-copy! (the-as quaternion (-> self flut flut-quat)) (-> (the-as process-drawable s3-0) root quat))
              (set! (-> self flut flut-scale quad) (-> (the-as process-drawable s3-0) root scale quad))
              (set! (-> self control unknown-int21) (the-as int (-> self flut flut-trans y)))))
          (set! (-> self control unknown-vector102 quad) (-> gp-0 quad))
          (set! (-> self control unknown-vector103 quad) (-> s4-0 quad)))
        (sound-play "flut-coo" :vol 90 :pitch -0.5)
        (ja-channel-push! 1 (seconds 0.05))
        (ja-no-eval :group! eichar-flut-get-off-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (suspend)
          (ja :num! (seek!)))
        (send-event (handle->process arg0) 'draw)
        (set-yaw-angle-clear-roll-pitch! (-> self control) (quaternion-y-angle (-> self control unknown-quaternion03)))
        (rot->dir-targ! (-> self control))
        (ja-post)
        (vector<-cspace! gp-0 (joint-node eichar-lod0-jg main))
        (+! (-> gp-0 y) -5896.192)
        (move-to-point! (-> self control) gp-0))
      (send-event *camera* 'ease-in)
      (ja-channel-set! 0)
      (go target-flut-get-off-hit-ground #f))
  :post
    (behavior ()
      (let ((gp-0 (new 'stack-no-clear 'vector))
            (f30-0 (fmax 0.0 (fmin 1.0 (* 0.006666667 (the float (- (current-time) (-> self state-time))))))))
        (fmax 0.0 (fmin 1.0 (* 0.006666667 (the float (- (current-time) (-> self state-time))))))
        (vector-lerp! gp-0 (-> self control unknown-vector102) (-> self control unknown-vector103) f30-0)
        (set! (-> gp-0 y)
              (lerp (-> self control unknown-vector102 y)
                    (-> self control unknown-vector103 y)
                    (fmax 0.0 (fmin 1.0 (* 0.0044444446 (the float (+ (- (seconds -0.5) (-> self state-time)) (current-time))))))))
        (move-to-point! (-> self control) gp-0)
        (quaternion-slerp! (-> self control unknown-quaternion00)
                           (-> self control unknown-quaternion02)
                           (-> self control unknown-quaternion03)
                           f30-0))
      (vector+! (-> self flut flut-trans) (-> self control trans) (-> self control unknown-vector12))
      (quaternion-copy! (the-as quaternion (-> self flut flut-quat)) (-> self control quat))
      (set! (-> self flut flut-scale quad) (-> self control scale quad))
      (target-no-move-post)))

(defstate target-flut-get-off-hit-ground (target)
  :event target-standard-event-handler
  :enter
    (-> target-hit-ground
        enter)
  :trans
    (behavior ()
      (logior! (-> self control status) (cshape-moving-flags onsurf onground tsurf))
      ((-> target-hit-ground trans)))
  :code
    (behavior ((arg0 symbol))
      (ja-channel-set! 1)
      (ja-no-eval :group! eichar-jump-land-ja :num! (seek!) :frame-num (ja-aframe (the-as float 42.0) 0))
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!)))
      (go target-stance))
  :post target-post)

(defstate target-flut-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-flut-stance))
           (('clone-anim) (go target-flut-clone-anim (process->handle (the-as process (-> block param 0)))))
           (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)))
  :exit
    (behavior ()
      (logclear! (-> self state-flags) (state-flags invulnerable grabbed))
      (target-exit)
      ((-> target-flut-start exit)))
  :code
    (-> target-flut-stance
        code)
  :post
    (behavior ()
      (target-no-stick-post)
      (target-flut-post-post)))

(defstate target-flut-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-flut-grab event) proc argc message block))
  :enter
    (-> target-clone-anim
        enter)
  :exit
    (behavior ()
      (send-event (ppointer->process (-> self sidekick)) 'matrix #f)
      ((-> target-clone-anim exit))
      ((-> target-flut-start exit)))
  :code
    (behavior ((arg0 handle))
      (send-event (ppointer->process (-> self sidekick)) 'matrix 'play-anim)
      (clone-anim arg0 33 #t "")
      (go target-flut-stance))
  :post
    (behavior ()
      (target-no-ja-move-post)
      (target-flut-post-post)))
