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

;; name: target-swim.gc
;; name in dgo: target-swim
;; dgos: ENGINE, GAME

;; DECOMP BEGINS

(defstate target-wade-stance (target)
  :event target-standard-event-handler
  :enter (behavior ()
    (set-time! (-> self state-time))
    (set! (-> self control mod-surface) *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? (water-flags wading) (-> self water flags)))
               (time-elapsed? (-> self water wade-time) (seconds 0.05))
               )
      (if (logtest? (water-flags swimming) (-> self water flags))
          (go target-swim-stance)
          (go target-stance)
          )
      )
    (if (and (cpad-hold? (-> self control cpad number) l1) (can-duck?))
        (go target-duck-stance #f)
        )
    (if (!= (-> *cpad-list* cpads (-> self control cpad number) stick0-speed) 0.0)
        (go target-wade-walk)
        )
    ;; og:preserve-this - High FPS Fix - https://github.com/open-goal/jak-project/pull/3178
    (if (and (recently-pressed? x)
             (can-jump? #f)
             )
        (target-jump-go)
        )
    (when (and (cpad-pressed? (-> self control cpad number) circle) (can-feet? #t))
      (sound-play "swim-stroke")
      (spawn-ripples (-> self water) 1.4 (-> self control trans) 0 (-> self control transv) #f)
      (go target-attack)
      )
    (if (and (cpad-pressed? (-> self control cpad number) square) (can-hands? #t))
        (go target-running-attack)
        )
    (if (and (using-gun? self) (let ((v1-79 (ja-group)))
                                 (and v1-79 (= v1-79 jakb-stance-loop-ja))
                                 )
             )
        (go target-gun-stance)
        )
    )
  :code (-> target-stance code)
  :post target-post
  )

(defstate target-wade-walk (target)
  :event target-standard-event-handler
  :enter (behavior ()
    ((-> target-wade-stance enter))
    )
  :exit (-> target-wade-stance exit)
  :trans (behavior ()
    ((-> self state-hook))
    (when (and (not (logtest? (water-flags wading) (-> self water flags)))
               (time-elapsed? (-> self water wade-time) (seconds 0.1))
               )
      (if (logtest? (water-flags swimming) (-> self water flags))
          (go target-swim-stance)
          (go target-stance)
          )
      )
    (if (= (-> *cpad-list* cpads (-> self control cpad number) stick0-speed) 0.0)
        (go target-wade-stance)
        )
    (if (and (cpad-hold? (-> self control cpad number) l1) (can-duck?))
        (go target-duck-walk #f)
        )
    ;; og:preserve-this - High FPS Fix - https://github.com/open-goal/jak-project/pull/3178
    (if (and (recently-pressed? x)
             (can-jump? #f)
             )
        (target-jump-go)
        )
    (when (and (cpad-pressed? (-> self control cpad number) circle) (can-feet? #t))
      (sound-play "swim-stroke")
      (spawn-ripples (-> self water) 1.4 (-> self control trans) 0 (-> self control transv) #f)
      (go target-attack)
      )
    (if (and (cpad-pressed? (-> self control cpad number) square) (can-hands? #t))
        (go target-running-attack)
        )
    )
  :code (behavior ()
    (let ((gp-0 105)
          (f30-0 0.0)
          )
      (let ((v1-2 (ja-group)))
        (cond
          ((and v1-2 (or (= v1-2 jakb-walk-ja) (= v1-2 jakb-run-ja)))
           (set! gp-0 15)
           (set! f30-0 (ja-frame-num 0))
           )
          ((let ((v1-9 (ja-group)))
             (and v1-9 (or (= v1-9 jakb-jump-ja) (= v1-9 jakb-jump-loop-ja)))
             )
           (set! gp-0 30)
           )
          ((let ((v1-16 (ja-group)))
             (and v1-16 (= v1-16 jakb-swim-walk-ja))
             )
           (set! gp-0 120)
           )
          )
        )
      (cond
        ((and (= (ja-group-size) 6) (let ((v1-25 (ja-group)))
                                      (and v1-25 (= v1-25 jakb-wade-shallow-walk-ja))
                                      )
              )
         )
        (else
          (ja-channel-push! 6 (the-as time-frame gp-0))
          (ja :group! jakb-wade-shallow-walk-ja
              :num! (identity f30-0)
              :dist (-> *TARGET-bank* wade-shallow-walk-cycle-dist)
              )
          (ja :chan 1
              :group! jakb-wade-deep-walk-ja
              :num! (identity f30-0)
              :dist (-> *TARGET-bank* wade-deep-walk-cycle-dist)
              )
          (let ((gp-3 (-> self skel root-channel 2)))
            (let ((f0-2 0.0))
              (set! (-> gp-3 frame-interp 1) f0-2)
              (set! (-> gp-3 frame-interp 0) f0-2)
              )
            (set! (-> gp-3 dist) (-> *TARGET-bank* walk-cycle-dist))
            (joint-control-channel-group-eval! gp-3 (the-as art-joint-anim jakb-walk-ja) num-func-identity)
            (set! (-> gp-3 frame-num) f30-0)
            )
          (let ((gp-4 (-> self skel root-channel 3)))
            (let ((f0-4 0.0))
              (set! (-> gp-4 frame-interp 1) f0-4)
              (set! (-> gp-4 frame-interp 0) f0-4)
              )
            (set! (-> gp-4 dist) (-> *TARGET-bank* walk-down-cycle-dist))
            (joint-control-channel-group-eval! gp-4 (the-as art-joint-anim jakb-walk-down-ja) num-func-identity)
            (set! (-> gp-4 frame-num) f30-0)
            )
          (let ((gp-5 (-> self skel root-channel 4)))
            (let ((f0-6 0.0))
              (set! (-> gp-5 frame-interp 1) f0-6)
              (set! (-> gp-5 frame-interp 0) f0-6)
              )
            (set! (-> gp-5 dist) (-> *TARGET-bank* walk-side-cycle-dist))
            (joint-control-channel-group-eval! gp-5 (the-as art-joint-anim jakb-walk-left-ja) num-func-identity)
            (set! (-> gp-5 frame-num) f30-0)
            )
          )
        )
      )
    (set! (-> self skel root-channel 2 command) (joint-control-command push))
    (set! (-> self skel root-channel 5 command) (joint-control-command stack))
    (let ((f28-0 0.0)
          (f26-0 0.0)
          (f30-1 (lerp-scale 1.0 0.0 (-> self control ctrl-xz-vel) 16384.0 32768.0))
          (gp-6 0)
          )
      (until #f
        (let ((f0-10 (fmax -1.0 (fmin 1.0 (* 2.0 (-> self control local-slope-z)))))
              (f24-0 (fmax -1.0 (fmin 1.0 (* 1.6 (-> self control local-slope-x)))))
              )
          (let ((f1-4 (fabs (- f0-10 f28-0))))
            (set! f28-0 (seek f28-0 f0-10 (fmax 0.05 (fmin 0.2 (/ f1-4 4)))))
            )
          (let ((f0-14 (fabs (- f24-0 f26-0))))
            (set! f26-0 (seek f26-0 f24-0 (fmax 0.05 (fmin 0.2 (/ f0-14 4)))))
            )
          )
        (ja :chan 3 :group! jakb-walk-down-ja :dist (-> *TARGET-bank* walk-down-cycle-dist))
        (cond
          ((>= f28-0 0.0)
           (let ((v1-83 (-> self skel root-channel 3)))
             (let ((f0-20 (fabs f28-0)))
               (set! (-> v1-83 frame-interp 1) f0-20)
               (set! (-> v1-83 frame-interp 0) f0-20)
               )
             (set! (-> v1-83 dist) (-> *TARGET-bank* walk-up-cycle-dist))
             (set! (-> v1-83 frame-group) (the-as art-joint-anim jakb-walk-up-ja))
             )
           )
          (else
            (let ((v1-86 (-> self skel root-channel 3)))
              (let ((f0-22 (fabs f28-0)))
                (set! (-> v1-86 frame-interp 1) f0-22)
                (set! (-> v1-86 frame-interp 0) f0-22)
                )
              (set! (-> v1-86 dist) (-> *TARGET-bank* walk-down-cycle-dist))
              (set! (-> v1-86 frame-group) (the-as art-joint-anim jakb-walk-down-ja))
              )
            )
          )
        (cond
          ((>= f26-0 0.0)
           (let ((v1-89 (-> self skel root-channel 4)))
             (let ((f0-25 (fabs f26-0)))
               (set! (-> v1-89 frame-interp 1) f0-25)
               (set! (-> v1-89 frame-interp 0) f0-25)
               )
             (set! (-> v1-89 dist) (-> *TARGET-bank* walk-side-cycle-dist))
             (set! (-> v1-89 frame-group) (the-as art-joint-anim jakb-walk-right-ja))
             )
           )
          (else
            (let ((v1-92 (-> self skel root-channel 4)))
              (let ((f0-27 (fabs f26-0)))
                (set! (-> v1-92 frame-interp 1) f0-27)
                (set! (-> v1-92 frame-interp 0) f0-27)
                )
              (set! (-> v1-92 dist) (-> *TARGET-bank* walk-side-cycle-dist))
              (set! (-> v1-92 frame-group) (the-as art-joint-anim jakb-walk-left-ja))
              )
            )
          )
        (let* ((f0-30 (- (-> self water height) (-> self control trans y)))
               (f24-1
                 (lerp-scale
                   0.0
                   1.0
                   f0-30
                   (lerp (-> self water wade-height) (-> self water swim-height) 0.25)
                   (lerp (-> self water wade-height) (-> self water swim-height) 0.75)
                   )
                 )
               )
          (let ((v1-100 (-> self skel effect)))
            (set! (-> v1-100 channel-offset) (if (< 0.5 f24-1)
                                                 1
                                                 0
                                                 )
                  )
            )
          0
          (set! f30-1
                (seek f30-1 (lerp-scale 1.0 0.0 (-> self control ctrl-xz-vel) 16384.0 32768.0) (* 4.0 (seconds-per-frame)))
                )
          (ja :chan 1 :frame-interp0 f24-1 :frame-interp1 f24-1)
          (ja :num! (loop!
                     (/ (-> self control ctrl-xz-vel)
                        (* 60.0
                           (/ (* (current-cycle-distance (-> self skel)) (-> self control scale x)) (-> *TARGET-bank* run-cycle-length))
                           )
                        )
                     )
              )
          (let ((s5-3 (-> self skel root-channel 5))
                (f0-44 (lerp f30-1 0.0 f24-1))
                )
            (set! (-> s5-3 frame-interp 1) f0-44)
            (set! (-> s5-3 frame-interp 0) f0-44)
            )
          )
        (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)
             (spawn-ripples
               (-> self water)
               0.2
               (vector<-cspace! (new 'stack-no-clear 'vector) (joint-node jakb-lod0-jg Rtoes))
               0
               (vector-float*! (new 'stack-no-clear 'vector) (-> self control transv) 2.5)
               #f
               )
             (set! gp-6 (the-as int (current-time)))
             )
            ((46 47 48 49)
             (spawn-ripples
               (-> self water)
               0.2
               (vector<-cspace! (new 'stack-no-clear 'vector) (joint-node jakb-lod0-jg Ltoes))
               0
               (vector-float*! (new 'stack-no-clear 'vector) (-> self control transv) 2.5)
               #f
               )
             (set! gp-6 (the-as int (current-time)))
             )
            )
          )
        (suspend)
        )
      )
    #f
    )
  :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 quat-for-control))))
    (let ((v1-2 (vector-z-quaternion! (new 'stack-no-clear 'vector) (-> self control dir-targ)))
          (f0-1 (fmin 1.0 (* arg0 (/ (-> self control ctrl-xz-vel) (-> self control current-surface target-speed)))))
          )
      (seek!
        (-> self control unknown-float43)
        (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 quat-for-control))))
      (forward-up-nopitch->quaternion (-> self control override-quat) gp-0 a2-2)
      )
    )
  (quaternion-rotate-x!
    (-> self control override-quat)
    (-> self control override-quat)
    (if (>= (-> self control unknown-float43) 0.0)
        16384.0
        -16384.0
        )
    )
  (set! (-> self control override-quat-alpha) (fabs (-> self control unknown-float43)))
  (if (and (-> self next-state) (= (-> self next-state name) 'target-swim-down))
      (seek! (-> self control unknown-float001) -6144.0 (* 4096.0 (seconds-per-frame)))
      (seek! (-> self control unknown-float001) 0.0 (* 2048.0 (seconds-per-frame)))
      )
  (set! (-> self control draw-offset y) (-> self control unknown-float001))
  )

(defstate target-swim-stance (target)
  :event target-standard-event-handler
  :enter (behavior ()
    (set-time! (-> self state-time))
    (set! (-> self control mod-surface) *swim-mods*)
    (logior! (-> self water flags) (water-flags swim-ground))
    (logior! (-> self state-flags) (state-flags lleg-no-ik rleg-no-ik))
    )
  :exit (behavior ()
    (target-state-hook-exit)
    (set! (-> self control mod-surface target-speed) 28672.0)
    (target-exit)
    (when (not (and (-> self next-state) (let ((v1-6 (-> self next-state name)))
                                           (or (= v1-6 'target-swim-stance)
                                               (= v1-6 'target-swim-walk)
                                               (= v1-6 'target-swim-down)
                                               (= v1-6 'target-swim-up)
                                               )
                                           )
                    )
               )
      (quaternion-identity! (-> self control override-quat))
      (set! (-> self control override-quat-alpha) 0.0)
      )
    (when (not (and (-> self next-state) (let ((v1-14 (-> self next-state name)))
                                           (or (= v1-14 'target-swim-stance) (= v1-14 'target-swim-walk))
                                           )
                    )
               )
      (let ((v1-15 (the-as sound-rpc-set-param (get-sound-buffer-entry))))
        (set! (-> v1-15 command) (sound-command set-param))
        (set! (-> v1-15 id) (-> self control board-jump-and-swim-sound))
        (set! (-> v1-15 params volume) -4)
        (set! (-> v1-15 auto-time) 960)
        (set! (-> v1-15 auto-from) 2)
        (set! (-> v1-15 params mask) (the-as uint 17))
        (-> v1-15 id)
        )
      )
    )
  :trans (behavior ()
    ((-> self state-hook))
    (if (and (logtest? (-> self control status) (collide-status on-surface))
             (not (logtest? (-> self control status) (collide-status on-water)))
             )
        (set-zero! (-> self water bob))
        )
    (when (and (not (logtest? (water-flags swimming) (-> self water flags)))
               (time-elapsed? (-> self state-time) (seconds 0.1))
               )
      (if (logtest? (water-flags wading) (-> self water flags))
          (go target-wade-stance)
          (go target-stance)
          )
      )
    ;; og:preserve-this - High FPS Fix - https://github.com/open-goal/jak-project/pull/3178
    (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 - https://github.com/open-goal/jak-project/pull/3178
    (when (and (recently-pressed? circle square)
               (< (-> *TARGET-bank* min-dive-depth) (target-height-above-ground))
               )
      (spawn-ripples (-> self water) 0.7 (-> self control trans) 1 *null-vector* #t)
      (set! (-> self control unknown-float43) 0.0)
      (go target-swim-down)
      )
    (if (and (!= (-> *cpad-list* cpads (-> self control cpad number) stick0-speed) 0.0)
             (let ((gp-0 (ja-group)))
               (ja-aframe-num 0)
               (if (or (and (= gp-0 jakb-swim-up-ja) #t) (and (= gp-0 jakb-swim-down-to-up-ja) #t))
                   #f
                   #t
                   )
               )
             )
        (go target-swim-walk)
        )
    (target-swim-tilt 0.0 2.0 0.0 1.0)
    (sound-play "swim-bubbles" :id (-> self control board-jump-and-swim-sound))
    )
  :code (behavior ()
    (let ((v1-2 (ja-group)))
      (cond
        ((and v1-2 (or (= v1-2 jakb-swim-up-ja) (= v1-2 jakb-swim-down-to-up-ja)))
         (ja-channel-push! 1 (seconds 0.075))
         (ja-no-eval :group! jakb-swim-up-to-stance-ja
                     :num! (seek! max (if (= (-> *cpad-list* cpads (-> self control cpad 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 frames num-frames) -1)))
             (let ((v1-38 (if (= (-> *cpad-list* cpads (-> self control cpad number) stick0-speed) 0.0)
                              1.0
                              2.0
                              )
                          )
                   )
               (set! (-> a0-9 param 1) v1-38)
               )
             (joint-control-channel-group-eval! a0-9 (the-as art-joint-anim #f) num-func-seek!)
             )
           )
         )
        (else
          (let ((v1-43 (ja-group)))
            (if (and v1-43 (= v1-43 jakb-swim-walk-ja))
                (ja-channel-push! 1 (seconds 0.83))
                (ja-channel-push! 1 (seconds 0.15))
                )
            )
          )
        )
      )
    (until #f
      (ja :group! jakb-swim-stance-ja :num! min)
      (until (and (ja-done? 0) (= (-> self skel root-channel 0) (-> self skel channel)))
        (can-play-stance-amibent?)
        (suspend)
        (if (= (-> self skel root-channel 0) (-> self skel channel))
            (ja :num! (seek!))
            )
        )
      )
    #f
    )
  :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-word04) (the-as uint (current-time)))
    (logior! (-> self state-flags) (state-flags lleg-no-ik rleg-no-ik))
    )
  :exit (-> target-swim-stance exit)
  :trans (behavior ()
    ((-> self state-hook))
    (if (and (logtest? (-> self control status) (collide-status on-surface))
             (not (logtest? (-> self control status) (collide-status on-water)))
             )
        (set-zero! (-> self water bob))
        )
    (when (and (not (logtest? (water-flags swimming) (-> self water flags)))
               (time-elapsed? (-> self water swim-time) (seconds 0.1))
               )
      (if (logtest? (water-flags wading) (-> self water flags))
          (go target-wade-stance)
          (go target-stance)
          )
      )
    ;; og:preserve-this - High FPS Fix - https://github.com/open-goal/jak-project/pull/3178
    (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 - https://github.com/open-goal/jak-project/pull/3178
    (when (and (recently-pressed? circle square)
               (< (-> *TARGET-bank* min-dive-depth) (target-height-above-ground))
               )
      (spawn-ripples (-> self water) 0.7 (-> self control trans) 1 *null-vector* #t)
      (set! (-> self control unknown-float43) 0.0)
      (go target-swim-down)
      )
    (cond
      ((= (-> *cpad-list* cpads (-> self control cpad number) stick0-speed) 0.0)
       (if (>= (the-as uint (- (current-time) (the-as int (-> self control unknown-word04)))) (the-as uint 15))
           (go target-swim-stance)
           )
       )
      (else
        (set! (-> self control unknown-word04) (the-as uint (current-time)))
        )
      )
    (target-swim-tilt 0.0 2.0 0.0 1.0)
    (sound-play "swim-bubbles" :id (-> self control board-jump-and-swim-sound))
    )
  :code (behavior ()
    (let ((v1-2 (ja-group)))
      (cond
        ((and v1-2 (or (= v1-2 jakb-swim-up-ja) (= v1-2 jakb-swim-down-to-up-ja) (= v1-2 jakb-swim-up-to-stance-ja)))
         (ja-channel-push! 1 (seconds 0.3))
         )
        ((let ((v1-8 (ja-group)))
           (and v1-8 (= v1-8 jakb-swim-up-to-stance-ja))
           )
         (ja-channel-push! 1 (seconds 0.15))
         (ja-no-eval :group! jakb-swim-walk-ja :num! (seek!) :frame-num (ja-aframe 19.0 0))
         (until (ja-done? 0)
           (compute-alignment! (-> self align))
           (if (not (logtest? (-> self align flags) (align-flags disabled)))
               (set! (-> self control mod-surface target-speed)
                     (* (-> self align delta trans z) (-> self control current-surface alignv) (-> self clock frames-per-second))
                     )
               )
           (suspend)
           (ja :num! (seek!))
           )
         )
        (else
          (ja-channel-push! 1 (seconds 0.15))
          )
        )
      )
    (until #f
      (ja-no-eval :group! jakb-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 mod-surface target-speed)
                  (* (-> self align delta trans z) (-> self control current-surface alignv) (-> self clock frames-per-second))
                  )
            )
        (suspend)
        (ja :num! (seek!))
        )
      )
    #f
    )
  :post target-swim-post
  )

(defstate target-swim-down (target)
  :event (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
    (local-vars (t0-7 symbol))
    (case message
      (('attack 'attack-invinc 'attack-or-shove)
       (let ((v1-1 (the-as attack-info (-> block param 1))))
         (set! t0-7 (or (not (logtest? (-> v1-1 mask) (attack-mask mode)))
                        (case (-> v1-1 mode)
                          (('bot 'lava 'melt 'dark-eco-pool)
                           #f
                           )
                          (('drown-death 'sharkey 'instant-death 'crush 'death 'grenade 'endlessfall)
                           (set! t0-7 'drown-death)
                           (set! (-> v1-1 mode) t0-7)
                           t0-7
                           )
                          (else
                            #t
                            )
                          )
                        )
               )
         (when t0-7
           (if (not (logtest? (attack-mask damage) (-> v1-1 mask)))
               (set! (-> v1-1 damage) (-> *FACT-bank* health-single-inc))
               )
           (if (!= (-> v1-1 mode) 'drown-death)
               (set! (-> v1-1 mode) 'damage)
               )
           (if (and (= (-> self game mode) 'play)
                    (>= 0.0 (- (-> (the-as fact-info-target (-> self fact)) health) (-> v1-1 damage)))
                    )
               (set! (-> v1-1 mode) 'drown-death)
               )
           (logior! (-> v1-1 mask) (attack-mask mode))
           (set! (-> self control unknown-word04) (the-as uint #t))
           )
         )
       )
      (('slide)
       )
      )
    (target-standard-event-handler proc argc message block)
    )
  :enter (behavior ()
    (set-time! (-> self state-time))
    (logior! (-> self state-flags) (state-flags lleg-no-ik rleg-no-ik))
    (logclear! (-> self water flags) (water-flags swim-ground))
    (set! (-> self control mod-surface) *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-word04) (the-as uint #f))
    (set! (-> self neck flex-blend) 0.0)
    )
  :exit (behavior ()
    (set! (-> self control dynam gravity-max) (-> self control standard-dynamics gravity-max))
    (set! (-> self control dynam gravity-length) (-> self control standard-dynamics gravity-length))
    (target-exit)
    (when (not (and (-> self next-state) (let ((v1-11 (-> self next-state name)))
                                           (or (= v1-11 'target-swim-stance)
                                               (= v1-11 'target-swim-walk)
                                               (= v1-11 'target-swim-down)
                                               (= v1-11 'target-swim-up)
                                               )
                                           )
                    )
               )
      (quaternion-identity! (-> self control override-quat))
      (set! (-> self control override-quat-alpha) 0.0)
      )
    (when (not (and (-> self next-state) (let ((v1-19 (-> self next-state name)))
                                           (or (= v1-19 'target-swim-down) (= v1-19 'target-swim-up))
                                           )
                    )
               )
      (let ((v1-21 (the-as sound-rpc-set-param (get-sound-buffer-entry))))
        (set! (-> v1-21 command) (sound-command set-param))
        (set! (-> v1-21 id) (-> self control bubbles-sound))
        (set! (-> v1-21 params volume) -4)
        (set! (-> v1-21 auto-time) 960)
        (set! (-> v1-21 auto-from) 2)
        (set! (-> v1-21 params mask) (the-as uint 17))
        (-> v1-21 id)
        )
      )
    (set! (-> self neck flex-blend) 1.0)
    )
  :trans (behavior ()
    (if (time-elapsed? (-> self water swim-time) (seconds 0.5))
        (go target-stance)
        )
    (cond
      ((time-elapsed? (-> self control last-time-on-surface) (seconds 0.1))
       (set! (-> self control mod-surface) *dive-mods*)
       (if (and (-> self next-state) (= (-> self next-state name) 'target-swim-down))
           (target-swim-tilt -0.9 1.0 0.0 0.5)
           )
       )
      (else
        (set! (-> self control mod-surface) *dive-bottom-mods*)
        (if (and (-> self next-state) (let ((v1-18 (-> self next-state name)))
                                        (or (= v1-18 'target-swim-down) (= v1-18 'target-swim-stance))
                                        )
                 )
            (target-swim-tilt 0.0 2.0 -1.0 1.0)
            )
        )
      )
    )
  :code (behavior ()
    (let ((gp-0 60)
          (s5-0 3000)
          (f30-0 0.0)
          )
      (let ((v1-2 (ja-group)))
        (set! f30-0 (cond
                      ((and v1-2 (or (= v1-2 jakb-swim-stance-ja)
                                     (= v1-2 jakb-swim-walk-ja)
                                     (= v1-2 jakb-swim-up-to-stance-ja)
                                     (= v1-2 jakb-swim-up-ja)
                                     (= v1-2 jakb-swim-down-to-up-ja)
                                     )
                            )
                       (let ((t9-0 ja-channel-push!)
                             (a0-16 1)
                             (v1-7 (ja-group))
                             )
                         (t9-0 a0-16 (the-as time-frame (if (and v1-7 (= v1-7 jakb-swim-down-to-up-ja))
                                                            105
                                                            22
                                                            )
                                             )
                               )
                         )
                       (ja-no-eval :group! jakb-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) 1.0 1.0 1.0)
                         (if (= (ja-aframe-num 0) 73.0)
                             (spawn-ripples (-> self water) 0.7 (-> self control trans) 1 *null-vector* #f)
                             )
                         (suspend)
                         (ja :num! (seek!))
                         )
                       (ja :group! jakb-swim-down-ja :num! min)
                       f30-0
                       )
                      (else
                        (let ((v1-50 (ja-group)))
                          (cond
                            ((and v1-50 (or (= v1-50 jakb-flop-down-ja)
                                            (= v1-50 jakb-moving-flop-down-ja)
                                            (= v1-50 jakb-flop-down-loop-ja)
                                            (= v1-50 jakb-moving-flop-down-loop-ja)
                                            )
                                  )
                             (ja-channel-push! 1 (seconds 0.075))
                             (set! gp-0 120)
                             (ja :group! jakb-swim-down-ja :num! (identity (ja-aframe 124.0 0)))
                             -16384.0
                             )
                            (else
                              (ja-channel-push! 1 (seconds 0.075))
                              (ja :group! jakb-swim-down-ja :num! min)
                              f30-0
                              )
                            )
                          )
                        )
                      )
              )
        )
      (until #f
        (when (and (!= (-> self tobot?) 'tobot) (time-elapsed? (-> self state-time) (seconds 0.05)))
          (if (and (or (not (cpad-hold? (-> self control cpad number) circle square)) (-> self control unknown-spool-anim00))
                   (time-elapsed? (-> self state-time) gp-0)
                   )
              (go target-swim-up)
              )
          (if (or (time-elapsed? (-> self control unknown-time-frame27) s5-0)
                  (and (logtest? (-> self control status) (collide-status on-surface))
                       (and (< (-> self water swim-depth) 8192.0) (time-elapsed? (-> self state-time) gp-0))
                       )
                  )
              (go target-swim-up)
              )
          )
        (if (time-elapsed? (-> self state-time) (seconds 0.5))
            (sound-play "water-bubbles" :id (-> self control bubbles-sound))
            )
        (let ((s4-3 (new-stack-vector0))
              (f0-13 (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) f0-13))
          (let* ((f28-0 (vector-length s4-3))
                 (f26-0 f28-0)
                 (f24-0 (+ f0-13 f30-0))
                 )
            (set! f30-0 (seek f30-0 0.0 (* 32768.0 (seconds-per-frame))))
            (vector+!
              (-> self control transv)
              (vector-float*! (-> self control transv) (-> self control dynam gravity-normal) f24-0)
              (vector-float*! s4-3 s4-3 (/ f28-0 f26-0))
              )
            )
          )
        (suspend)
        (ja :num! (loop! (lerp-scale 0.4 1.0 (vector-length (-> self control transv)) 0.0 16384.0)))
        )
      )
    #f
    )
  :post target-swim-post
  )

(defstate target-swim-up (target)
  :event (-> target-swim-down event)
  :enter (behavior ()
    ((-> target-swim-down enter))
    )
  :exit (-> target-swim-down exit)
  :trans (behavior ()
    (if (and (cpad-pressed? (-> self control cpad number) x)
             (not (logtest? (-> self state-flags) (state-flags prevent-jump)))
             (not (logtest? (water-flags head-under-water bouncing) (-> self water flags)))
             )
        (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 ((id (new-attack-id)) (mode 'drown-death))))
        )
    (if (and (cpad-pressed? (-> self control cpad number) circle square)
             (or (not (time-elapsed? (-> self control unknown-time-frame27) (seconds 10)))
                 (logtest? (-> self control status) (collide-status touch-ceiling))
                 )
             (and (< (-> *TARGET-bank* min-dive-depth) (target-height-above-ground))
                  (time-elapsed? (-> self state-time) (seconds 0.05))
                  )
             )
        (go target-swim-down)
        )
    (sound-play "water-bubbles" :id (-> self control bubbles-sound))
    ((-> target-swim-down trans))
    )
  :code (behavior ()
    (ja-channel-push! 1 (seconds 0.1))
    (let ((f30-0 1.0))
      (let ((s5-0 #t)
            (gp-0 #f)
            )
        (ja-no-eval :group! jakb-swim-down-to-up-ja :num! (seek!) :frame-num 0.0)
        (until (ja-done? 0)
          (target-swim-tilt
            (if (< 8192.0 (-> self water swim-depth))
                0.5
                0.0
                )
            1.0
            0.0
            0.1
            )
          (when (and (not gp-0)
                     (or (>= (ja-aframe-num 0) 240.0) (not (logtest? (water-flags head-under-water) (-> self water flags))))
                     )
            (set! gp-0 #t)
            (sound-play "swim-surface")
            (spawn-ripples (-> self water) 0.2 (-> self control trans) 1 (-> self control transv) #t)
            )
          (if (and (not (logtest? (-> self water flags) (water-flags under-water)))
                   (and (or (>= (ja-aframe-num 0) 222.0)
                            (and (!= (-> *cpad-list* cpads (-> self control cpad number) stick0-speed) 0.0) (>= (ja-aframe-num 0) 200.0))
                            )
                        (!= (-> self tobot?) 'tobot)
                        )
                   )
              (goto cfg-51)
              )
          (compute-alignment! (-> self align))
          (when (not (logtest? (-> self water flags) (water-flags under-water)))
            (logior! (-> self water flags) (water-flags swim-ground))
            (set! s5-0 #f)
            )
          (if s5-0
              (align! (-> self align) (align-opts adjust-y-vel) 1.0 1.0 1.0)
              )
          (suspend)
          (ja :num! (seek!))
          )
        )
      (ja :group! jakb-swim-up-ja :num! min)
      (until #f
        (target-swim-tilt
          (if (< 8192.0 (-> self water swim-depth))
              0.3
              0.0
              )
          1.0
          0.0
          0.1
          )
        (if (and (not (logtest? (-> self water flags) (water-flags under-water))) (!= (-> self tobot?) 'tobot))
            (goto cfg-51)
            )
        (if (cpad-pressed? (-> self control cpad number) x)
            (set! f30-0 2.0)
            )
        (compute-alignment! (-> self align))
        (when (logtest? (-> self water flags) (water-flags under-water))
          (align! (-> self align) (align-opts adjust-y-vel) 1.0 1.0 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 1.0 (seconds-per-frame)))
        )
      )
    #f
    (label cfg-51)
    (logior! (-> self water flags) (water-flags swim-ground))
    (set-time! (-> self water swim-time))
    (start-bobbing! (-> self water) -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 jump-out))
       (logclear! (-> self control status) (collide-status on-surface on-ground touch-surface))
       )
      (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 jump-out))
    )
  :code (behavior ((arg0 float) (arg1 float))
    (die-on-next-update! (-> self water bob))
    (ja-channel-push! 1 (seconds 0.05))
    (ja :group! jakb-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 ((f0-7 (fmax 0.0 (- (-> self water bob-offset)))))
      (let ((v1-36 (new-stack-vector0)))
        (let ((f1-5 (vector-dot (-> self control dynam gravity-normal) (-> self control transv))))
          0.0
          (vector-! v1-36 (-> self control transv) (vector-float*! v1-36 (-> self control dynam gravity-normal) f1-5))
          )
        (let* ((f1-6 (vector-length v1-36))
               (f2-2 f1-6)
               (f3-0 0.4096)
               )
          (vector+!
            (-> self control transv)
            (vector-float*! (-> self control transv) (-> self control dynam gravity-normal) f3-0)
            (vector-float*! v1-36 v1-36 (/ f1-6 f2-2))
            )
          )
        )
      (go target-swim-jump-jump (+ f0-7 arg0) (+ f0-7 arg1) (the-as surface #f))
      )
    )
  :post target-swim-post
  )
