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

;; name: underb-master.gc
;; name in dgo: underb-master
;; dgos: UNB

(defenum under-locking-mode
  :type int64
  (want-mech)
  (want-fill)
  (airlock-wait)
  (want-drain)
  (drain)
  (want-exit-mech)
  )

;; DECOMP BEGINS

(deftype under-warp (process-drawable)
  ((interp  float)
   )
  (:state-methods
    idle
    die-fast
    )
  (:methods
    (under-warp-method-22 (_type_) none)
    )
  )


(defskelgroup skel-under-warp under-warp under-warp-lod0-jg under-warp-idle-ja
              ((under-warp-lod0-mg (meters 999999)))
              :bounds (static-spherem 0 0 0 8)
              )

(defstate idle (under-warp)
  :virtual #t
  :event (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
    (case message
      (('die-fast)
       (set-under-fog-interp! 0.0)
       (go-virtual die-fast)
       )
      )
    )
  :code (behavior ()
    (until #f
      (let ((v1-2 (-> self skel root-channel 1))
            (f0-0 (-> self interp))
            )
        (set! (-> v1-2 frame-interp 1) f0-0)
        (set! (-> v1-2 frame-interp 0) f0-0)
        )
      (ja :num! (loop!))
      (ja :chan 1 :num! (chan 0))
      (ja-no-eval :group! under-warp-idle-ja :num! (seek!) :frame-num 0.0)
      (until (ja-done? 0)
        (suspend)
        (ja :num! (seek!))
        )
      )
    #f
    )
  :post (behavior ()
    (under-warp-method-22 self)
    (ja-post)
    )
  )

(defstate die-fast (under-warp)
  :virtual #t
  :code nothing
  )

(defmethod under-warp-method-22 ((this under-warp))
  (rlet ((acc :class vf)
         (vf0 :class vf)
         (vf4 :class vf)
         (vf5 :class vf)
         (vf6 :class vf)
         (vf7 :class vf)
         )
    (init-vf0-vector)
    (let ((s3-0 (camera-matrix))
          (s5-0 (new 'stack-no-clear 'vector))
          (gp-0 (new 'stack-no-clear 'vector))
          (f30-0 4096.0)
          )
      ;; og:preserve-this changed for PC port: resize warp effect based on aspect ratio
      (let ((f0-4 (* 0.00013563369 (tan (* 0.5 (-> *math-camera* fov))) f30-0)))
        (set-vector! (-> this root scale) (* f0-4 (if (-> *pc-settings* use-vis?) 1.0 (-> *pc-settings* aspect-ratio-scale))) f0-4 f0-4 1.0)
        )
      (set! (-> gp-0 quad) (-> (camera-pos) quad))
      (vector-normalize-copy! s5-0 (-> s3-0 vector 2) 1.0)
      (matrix->quaternion (-> this root quat) s3-0)
      (let ((v1-10 (-> this root trans)))
        (let ((a0-5 f30-0))
          (.mov vf7 a0-5)
          )
        (.lvf vf5 (&-> s5-0 quad))
        (.lvf vf4 (&-> gp-0 quad))
        (.add.x.vf.w vf6 vf0 vf0)
        (.mul.x.vf.xyz acc vf5 vf7)
        (.add.mul.w.vf.xyz vf6 vf4 vf0 acc)
        (.svf (&-> v1-10 quad) vf6)
        )
      )
    0
    (none)
    )
  )

;; WARN: Return type mismatch object vs none.
(defbehavior under-warp-init-by-other under-warp ((arg0 vector) (arg1 quaternion) (arg2 entity-actor))
  (set! (-> self level) (the-as level arg2))
  (set! (-> self root) (new 'process 'trsqv))
  (set! (-> self root trans quad) (-> arg0 quad))
  (quaternion-copy! (-> self root quat) arg1)
  (initialize-skeleton
    self
    (the-as skeleton-group (art-group-get-by-name *level* "skel-under-warp" (the-as (pointer uint32) #f)))
    (the-as pair 0)
    )
  (set! (-> self interp) 0.5)
  (ja-channel-push! 2 (seconds 0.3))
  (ja-no-eval :group! under-warp-idle-ja :num! (loop!))
  (let ((gp-2 (-> self skel root-channel 1)))
    (let ((f0-2 (-> self interp)))
      (set! (-> gp-2 frame-interp 1) f0-2)
      (set! (-> gp-2 frame-interp 0) f0-2)
      )
    (joint-control-channel-group! gp-2 (the-as art-joint-anim under-warp-none-ja) num-func-identity)
    (set! (-> gp-2 frame-num) 0.0)
    )
  (logior! (-> self skel status) (joint-control-status blend-shape))
  (go-virtual idle)
  (none)
  )

(deftype underb-master (process)
  ((warp-handle            handle)
   (tank-handle            handle)
   (underwater-time        time-frame)
   (last-air-beep-time     time-frame)
   (ambient-sound-id       sound-id)
   (air-supply             float)
   (air-charge-up?         symbol)
   (under-water-pitch-mod  float)
   (big-room-entered       symbol)
   (big-room-timer         time-frame)
   (under-plat-player-on   symbol)
   (under-plat-is-up       symbol)
   )
  (:state-methods
    idle
    big-room-player-under
    big-room-player-plat
    underb-master-state-17
    big-room-player-above
    big-room-player-falling
    big-room-player-exiting
    big-room-player-done
    )
  (:methods
    (under-warp-check (_type_) symbol)
    (spawn-air-tank-hud (_type_ symbol) none)
    )
  )


(define *underb-master* (the-as (pointer underb-master) #f))

(defmethod deactivate ((this underb-master))
  "Make a process dead, clean it up, remove it from the active pool, and return to dead pool."
  (sound-stop (-> this ambient-sound-id))
  (send-event (handle->process (-> this warp-handle)) 'die-fast)
  (set! *underb-master* (the-as (pointer underb-master) #f))
  ((method-of-type process deactivate) this)
  (none)
  )

;; WARN: disable def twice: 121. This may happen when a cond (no else) is nested inside of another conditional, but it should be rare.
(defbehavior underb-master-event-handler underb-master ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  (local-vars (v0-0 object))
  (case arg2
    (('query)
     (case (-> arg3 param 0)
       (('mech)
        (not (-> *setting-control* user-current pilot-exit))
        )
       (('bubbler)
        (and (handle->process (-> self warp-handle))
             (or (and (-> self next-state) (= (-> self next-state name) 'idle)) (not (under-warp-check self)))
             )
        )
       )
     )
    (('request)
     (case (-> arg3 param 0)
       (('mech)
        (cond
          ((-> arg3 param 1)
           (cond
             ((-> *setting-control* user-current pilot-exit)
              (let ((a1-2 *target*))
                (when (and a1-2 (focus-test? a1-2 mech))
                  (set-setting! 'pilot-exit #f 0.0 0)
                  (apply-settings *setting-control*)
                  #t
                  )
                )
              )
             (else
               #t
               )
             )
           )
          ((-> *setting-control* user-current pilot-exit)
           #t
           )
          (else
            (remove-setting! 'pilot-exit)
            (apply-settings *setting-control*)
            (not (-> *setting-control* user-current pilot-exit))
            )
          )
        )
       (('under-warp)
        (cond
          ((-> arg3 param 1)
           (set-under-fog-interp! 1.0)
           (when (not (handle->process (-> self warp-handle)))
             (let ((s2-0 (camera-matrix))
                   (s3-0 (new 'stack-no-clear 'vector))
                   (gp-0 (new 'stack-no-clear 'vector))
                   (s5-0 (new 'stack-no-clear 'quaternion))
                   )
               (set! (-> gp-0 quad) (-> (camera-pos) quad))
               (vector-normalize-copy! s3-0 (-> s2-0 vector 2) 1.0)
               (matrix->quaternion s5-0 s2-0)
               (set! (-> self warp-handle)
                     (ppointer->handle (process-spawn under-warp gp-0 s5-0 (-> self level) :to *display-pool*))
                     )
               )
             (set! v0-0 (sound-play "mech-under-amb"))
             (set! (-> self ambient-sound-id) (the-as sound-id v0-0))
             v0-0
             )
           )
          (else
            (set-under-fog-interp! 0.0)
            (let ((a0-41 (handle->process (-> self warp-handle))))
              (when a0-41
                (send-event a0-41 'die-fast)
                (set! (-> self warp-handle) (the-as handle #f))
                (sound-stop (-> self ambient-sound-id))
                (set! (-> self ambient-sound-id) (new 'static 'sound-id))
                0
                )
              )
            )
          )
        )
       (('big-room)
        (case (-> arg3 param 1)
          (('status)
           (cond
             ((-> arg3 param 2)
              (set! v0-0 #t)
              (set! (-> self big-room-entered) (the-as symbol v0-0))
              v0-0
              )
             (else
               (set! (-> self big-room-entered) #f)
               #f
               )
             )
           )
          (('under-plat)
           (case (-> arg3 param 2)
             (('player)
              (cond
                ((-> arg3 param 3)
                 (set! v0-0 #t)
                 (set! (-> self under-plat-player-on) (the-as symbol v0-0))
                 v0-0
                 )
                (else
                  (set! (-> self under-plat-player-on) #f)
                  #f
                  )
                )
              )
             (('up)
              (cond
                ((-> arg3 param 3)
                 (set! v0-0 #t)
                 (set! (-> self under-plat-is-up) (the-as symbol v0-0))
                 v0-0
                 )
                (else
                  (set! (-> self under-plat-is-up) #f)
                  #f
                  )
                )
              )
             )
           )
          )
        )
       )
     )
    (('bubbler)
     (set! v0-0 #t)
     (set! (-> self air-charge-up?) (the-as symbol v0-0))
     v0-0
     )
    )
  )

(defmethod under-warp-check ((this underb-master))
  "Used to check whether the underwater warp effect should be drawn."
  (let ((target-pos (target-pos 0))
        (tpos-offset (new 'stack-no-clear 'vector))
        (a1-0 (new 'stack-no-clear 'vector))
        (v1-0 (new 'stack-no-clear 'vector))
        )
    (set! (-> tpos-offset x) (+ -827392.0 (-> target-pos x)))
    (set! (-> tpos-offset y) 0.0)
    (set! (-> tpos-offset z) (+ -7671808.0 (-> target-pos z)))
    (set! (-> a1-0 x) -94208.0)
    (set! (-> a1-0 y) 0.0)
    (set! (-> a1-0 z) -143360.0)
    (vector-cross! v1-0 tpos-offset a1-0)
    (< (-> v1-0 y) 0.0)
    )
  )

(defmethod spawn-air-tank-hud ((this underb-master) (arg0 symbol))
  "Spawns or hides the air tank HUD bar."
  (cond
    (arg0
      (if (not (handle->process (-> this tank-handle)))
          (set! (-> this tank-handle)
                (ppointer->handle (process-spawn hud-mech-air-tank :init hud-init-by-other :to this))
                )
          )
      )
    (else
      (send-event (handle->process (-> this tank-handle)) 'hide-and-die)
      (set! (-> this tank-handle) (the-as handle #f))
      )
    )
  (none)
  )

(defbehavior underb-master-post underb-master ()
  #t
  (let ((gp-0 *target*))
    (let ((f30-0 0.0))
      (when (and gp-0 (not (-> *setting-control* user-current pilot-exit)))
        (let ((s5-0 (new 'stack-no-clear 'water-info)))
          (water-info-init! (-> gp-0 control) s5-0 (collide-action solid semi-solid))
          (let ((v1-7 (-> s5-0 flags)))
            (if (logtest? (water-flags touch-water) v1-7)
                (set! f30-0 (lerp-scale 0.0 1.0 (- (-> gp-0 control trans y) (-> s5-0 trans y)) -4096.0 -20480.0))
                )
            )
          )
        )
      (when (!= f30-0 (-> self under-water-pitch-mod))
        (set! (-> self under-water-pitch-mod) f30-0)
        (if (= f30-0 0.0)
            (remove-setting! 'under-water-pitch-mod)
            (set-setting! 'under-water-pitch-mod 'abs f30-0 0)
            )
        )
      )
    (if (or (not gp-0) (not (logtest? (-> gp-0 water flags) (water-flags under-water))))
        (set! (-> self air-charge-up?) #t)
        (set-time! (-> self underwater-time))
        )
    )
  (cond
    ((-> self air-charge-up?)
     (set! (-> self air-supply) (seek-with-smooth (-> self air-supply) 1.0 (* 2.0 (seconds-per-frame)) 0.125 0.01))
     (when (= (-> self air-supply) 1.0)
       (set! (-> self air-charge-up?) #f)
       (set! (-> self air-supply) 1.01)
       (set! (-> self last-air-beep-time) 0)
       0
       )
     )
    (else
      (seek! (-> self air-supply) 0.0 (* 0.04 (seconds-per-frame)))
      (cond
        ((= (-> self air-supply) 0.0)
         (send-event *target* 'attack #f (static-attack-info ((id (new-attack-id)) (mode 'air))))
         )
        (else
          (when (>= 0.4 (-> self air-supply))
            (let ((v1-39 (the int (lerp-scale 90.0 300.0 (-> self air-supply) 0.0 0.4))))
              (when (time-elapsed? (-> self last-air-beep-time) v1-39)
                (set-time! (-> self last-air-beep-time))
                (sound-play "oxygen-warning")
                )
              )
            )
          )
        )
      )
    )
  (set! (-> *game-info* air-supply) (fmin 1.0 (-> self air-supply)))
  (if (or (and *target* (not (logtest? (focus-status mech) (-> *target* focus-status))))
          (and (>= (-> self air-supply) 1.0) (time-elapsed? (-> self underwater-time) (seconds 3)))
          )
      (spawn-air-tank-hud self #f)
      (spawn-air-tank-hud self #t)
      )
  (none)
  )

(defstate idle (underb-master)
  :virtual #t
  :event underb-master-event-handler
  :enter (behavior ()
    0
    )
  :trans (behavior ()
    (if (-> self big-room-entered)
        (go-virtual big-room-player-under)
        )
    )
  :code sleep-code
  :post underb-master-post
  )

(defstate big-room-player-under (underb-master)
  :virtual #t
  :event underb-master-event-handler
  :enter (behavior ()
    0
    )
  :trans (behavior ()
    (if (-> self under-plat-player-on)
        (go-virtual big-room-player-plat)
        )
    (if (not (-> self big-room-entered))
        (go-virtual idle)
        )
    )
  :code sleep-code
  :post underb-master-post
  )

(defstate big-room-player-plat (underb-master)
  :virtual #t
  :event underb-master-event-handler
  :enter (behavior ()
    (set-setting! 'entity-name "camera-239" 0.0 0)
    (send-event (ppointer->process *underb-master*) 'request 'under-warp #f)
    )
  :exit (behavior ()
    (remove-setting! 'entity-name)
    )
  :trans (behavior ()
    (let ((gp-0 (target-pos 0)))
      (if (or (and (-> self under-plat-is-up) (-> self under-plat-player-on)) (< -245760.0 (-> gp-0 y)))
          (go-virtual big-room-player-above)
          )
      (if (and (not (-> self under-plat-player-on)) (< (-> gp-0 y) -245760.0))
          (go-virtual big-room-player-falling)
          )
      )
    )
  :code sleep-code
  :post underb-master-post
  )

(defstate big-room-player-above (underb-master)
  :virtual #t
  :event underb-master-event-handler
  :enter (behavior ()
    (persist-with-delay *setting-control* 'interp-time (seconds 0.05) 'interp-time 'abs 600.0 0)
    (remove-setting! 'mode-name)
    )
  :trans (behavior ()
    (if (< (-> (target-pos 0) y) -245760.0)
        (go-virtual big-room-player-falling)
        )
    )
  :code sleep-code
  :post underb-master-post
  )

(defstate big-room-player-falling (underb-master)
  :virtual #t
  :event underb-master-event-handler
  :enter (behavior ()
    (set-setting! 'mode-name 'cam-endlessfall 0.0 0)
    )
  :exit (behavior ()
    (send-event (ppointer->process *underb-master*) 'request 'under-warp #t)
    (persist-with-delay *setting-control* 'interp-time (seconds 0.05) 'interp-time 'abs 0.0 0)
    (remove-setting! 'mode-name)
    )
  :trans (behavior ()
    (cond
      ((not *target*)
       (go-virtual idle)
       )
      ((under-warp-check self)
       (if (< (-> (target-pos 0) y) -258048.0)
           (go-virtual big-room-player-exiting)
           )
       )
      (else
        (if (< (-> (target-pos 0) y) -278528.0)
            (go-virtual big-room-player-under)
            )
        )
      )
    )
  :code sleep-code
  :post underb-master-post
  )

(defstate big-room-player-exiting (underb-master)
  :virtual #t
  :event underb-master-event-handler
  :enter (behavior ()
    (persist-with-delay *setting-control* 'interp-time (seconds 0.05) 'interp-time 'abs 0.0 0)
    (set-setting! 'entity-name "camera-244" 0.0 0)
    (set-time! (-> self big-room-timer))
    (send-event (ppointer->process *underb-master*) 'request 'under-warp #t)
    )
  :exit (behavior ()
    (persist-with-delay *setting-control* 'interp-time (seconds 0.05) 'interp-time 'abs 600.0 0)
    (remove-setting! 'entity-name)
    )
  :trans (behavior ()
    (if (time-elapsed? (-> self big-room-timer) (seconds 1))
        (go-virtual idle)
        )
    )
  :code sleep-code
  :post underb-master-post
  )

(defstate big-room-player-done (underb-master)
  :virtual #t
  :event underb-master-event-handler
  :enter (behavior ()
    (go-virtual idle)
    )
  :code sleep-code
  :post underb-master-post
  )

;; WARN: Return type mismatch object vs none.
(defbehavior underb-master-init-by-other underb-master ((arg0 level))
  (set! *underb-master* (the-as (pointer underb-master) (process->ppointer self)))
  (set! (-> self warp-handle) (the-as handle #f))
  (set! (-> self tank-handle) (the-as handle #f))
  (set! (-> self level) arg0)
  (set! (-> self air-supply) 1.0)
  (set! (-> self air-charge-up?) #f)
  (set! (-> self ambient-sound-id) (new 'static 'sound-id))
  (set! (-> self big-room-entered) #f)
  (set! (-> self under-plat-player-on) #f)
  (set! (-> self under-plat-is-up) #f)
  (go-virtual idle)
  (none)
  )

(defun underb-login ((arg0 level))
  (set! *nav-network* (new 'loading-level 'nav-network))
  (nav-network-method-9 *nav-network*)
  0
  (none)
  )

(defun underb-deactivate ((arg0 level))
  (set! *nav-network* (the-as nav-network 0))
  0
  (none)
  )

(defun underb-activate ((arg0 level))
  (nav-network-method-10 *nav-network* arg0 *under-adjacency*)
  (let ((v1-3 (process-spawn underb-master arg0 :to *entity-pool*)))
    (if v1-3
        (set! (-> v1-3 0 level) arg0)
        )
    )
  0
  (none)
  )

(deftype under-locking (process-drawable)
  ((id                   int8)
   (up-y                 float)
   (down-y               float)
   (mode                 under-locking-mode)
   (which-reminder?      symbol)
   (spooled-sound-id     sound-id)
   (draining-part        sparticle-launch-control)
   (actor-group          (pointer actor-group))
   (spooled-sound-delay  int32)
   (last-reminder-time   time-frame  :offset 256)
   )
  (:state-methods
    startup
    active
    filling
    draining
    )
  )


;; WARN: Return type mismatch process-drawable vs under-locking.
(defmethod relocate ((this under-locking) (offset int))
  (if (nonzero? (-> this draining-part))
      (&+! (-> this draining-part) offset)
      )
  (the-as under-locking ((method-of-type process-drawable relocate) this offset))
  )

(defmethod deactivate ((this under-locking))
  "Make a process dead, clean it up, remove it from the active pool, and return to dead pool."
  (if (nonzero? (-> this draining-part))
      (kill-and-free-particles (-> this draining-part))
      )
  ((method-of-type process-drawable deactivate) this)
  (none)
  )

(defstate startup (under-locking)
  :virtual #t
  :event (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
    (case message
      (('test)
       #f
       )
      )
    )
  :enter (behavior ()
    (set-time! (-> self state-time))
    )
  :trans (behavior ()
    (let ((v1-0 (-> self actor-group)))
      (cond
        ((and v1-0
              (let ((a0-2 (-> v1-0 0 data 0 actor)))
                (if a0-2
                    (-> a0-2 extra process)
                    )
                )
              (let ((a0-5 (-> v1-0 0 data 1 actor)))
                (if a0-5
                    (-> a0-5 extra process)
                    )
                )
              (let ((a1-2 (-> v1-0 0 data 2 actor)))
                (if a1-2
                    (-> a1-2 extra process)
                    )
                )
              )
         (when (time-elapsed? (-> self state-time) (seconds 0.1))
           (let ((a0-13 (-> v1-0 0 data 0 actor)))
             (if a0-13
                 (-> a0-13 extra process)
                 )
             )
           (let ((v1-2 (-> v1-0 0 data 1 actor)))
             (if v1-2
                 (-> v1-2 extra process)
                 )
             )
           (let ((a1-6 *target*))
             (cond
               ((and a1-6 (focus-test? a1-6 mech))
                (set! (-> self mode) (under-locking-mode want-drain))
                (let ((a1-8 (new 'stack-no-clear 'event-message-block)))
                  (set! (-> a1-8 from) (process->ppointer self))
                  (set! (-> a1-8 num-params) 1)
                  (set! (-> a1-8 message) 'move-to-y)
                  (set! (-> a1-8 param 0) (the-as uint (-> self up-y)))
                  (let ((t9-0 send-event-function)
                        (v1-13 (-> self actor-group 0 data 2 actor))
                        )
                    (t9-0
                      (if v1-13
                          (-> v1-13 extra process)
                          )
                      a1-8
                      )
                    )
                  )
                )
               (else
                 (set! (-> self mode) (under-locking-mode want-mech))
                 (let ((a1-9 (new 'stack-no-clear 'event-message-block)))
                   (set! (-> a1-9 from) (process->ppointer self))
                   (set! (-> a1-9 num-params) 1)
                   (set! (-> a1-9 message) 'move-to-y)
                   (set! (-> a1-9 param 0) (the-as uint (-> self down-y)))
                   (let ((t9-1 send-event-function)
                         (v1-22 (-> self actor-group 0 data 2 actor))
                         )
                     (t9-1
                       (if v1-22
                           (-> v1-22 extra process)
                           )
                       a1-9
                       )
                     )
                   )
                 )
               )
             )
           (go-virtual active)
           )
         )
        (else
          (set-time! (-> self state-time))
          )
        )
      )
    )
  :code sleep-code
  )

(defstate active (under-locking)
  :virtual #t
  :event (behavior ((proc process) (argc int) (message symbol) (block event-message-block))
    (case message
      (('test)
       (let ((v1-1 (-> self mode)))
         (cond
           ((-> block param 0)
            (when (or (= v1-1 (under-locking-mode want-mech)) (= v1-1 (under-locking-mode want-exit-mech)))
              (let ((a0-4 *target*))
                (and a0-4 (not (logtest? (focus-status mech) (-> a0-4 focus-status))))
                )
              )
            )
           (else
             (or (= v1-1 (under-locking-mode airlock-wait)) (= v1-1 (under-locking-mode want-drain)))
             )
           )
         )
       )
      )
    )
  :trans (behavior ()
    (case (-> self mode)
      (((under-locking-mode want-mech))
       (let ((v1-1 *target*)
             (a0-1 (-> self actor-group))
             )
         (when (and v1-1 a0-1)
           (if (and (-> a0-1 0 data 0 actor)
                    (focus-test? v1-1 mech)
                    (send-event (ppointer->process *underb-master*) 'request 'mech #t)
                    )
               (set! (-> self mode) (under-locking-mode want-fill))
               )
           )
         )
       )
      (((under-locking-mode want-fill))
       (if (not (logtest? (-> self actor-group 0 data 0 actor extra perm status) (entity-perm-status subtask-complete)))
           (go-virtual filling)
           )
       )
      (((under-locking-mode airlock-wait))
       (let ((a1-2 (new 'stack-no-clear 'event-message-block)))
         (set! (-> a1-2 from) (process->ppointer self))
         (set! (-> a1-2 num-params) 0)
         (set! (-> a1-2 message) 'front)
         (let ((t9-2 send-event-function)
               (v1-24 (-> self actor-group 0 data 1 actor))
               )
           (if (not (t9-2
                      (if v1-24
                          (-> v1-24 extra process)
                          )
                      a1-2
                      )
                    )
               (set! (-> self mode) (under-locking-mode want-drain))
               )
           )
         )
       )
      (((under-locking-mode want-drain))
       (if (>= 20480.0 (vector-vector-xz-distance (target-pos 0) (-> self root trans)))
           (set! (-> self mode) (under-locking-mode drain))
           )
       )
      (((under-locking-mode drain))
       (go-virtual draining)
       )
      (((under-locking-mode want-exit-mech))
       (let ((a1-4 *target*))
         (when (or (not a1-4) (not (logtest? (focus-status mech) (-> a1-4 focus-status))))
           (set! (-> self mode) (under-locking-mode want-mech))
           0
           )
         )
       (when (time-elapsed? (-> self last-reminder-time) (seconds 9))
         (set-time! (-> self last-reminder-time))
         (add-process
           *gui-control*
           self
           (gui-channel ashelin)
           (gui-action play)
           (if (-> self which-reminder?)
               "cityv193"
               "cityv192"
               )
           -99.0
           0
           )
         (set! (-> self which-reminder?) (not (-> self which-reminder?)))
         )
       )
      )
    )
  :code sleep-code
  )

(defstate filling (under-locking)
  :virtual #t
  :event (-> (method-of-type under-locking active) event)
  :enter (behavior ()
    (set! (-> self spooled-sound-id)
          (add-process *gui-control* self (gui-channel ashelin) (gui-action queue) "wtrfill" -99.0 0)
          )
    (set! (-> self state-time) 0)
    (set! (-> self spooled-sound-delay) (if (= (-> self id) 1)
                                            120
                                            0
                                            )
          )
    )
  :trans (behavior ()
    (when (and (zero? (-> self state-time))
               (= (get-status *gui-control* (-> self spooled-sound-id)) (gui-status ready))
               )
      (set-time! (-> self state-time))
      (set-time! (-> self last-reminder-time))
      )
    (when (nonzero? (-> self state-time))
      (when (and (>= (-> self spooled-sound-delay) 0) (time-elapsed? (-> self state-time) (-> self spooled-sound-delay)))
        (set-action!
          *gui-control*
          (gui-action play)
          (-> self spooled-sound-id)
          (gui-channel none)
          (gui-action none)
          (the-as string #f)
          (the-as (function gui-connection symbol) #f)
          (the-as process #f)
          )
        (set! (-> self spooled-sound-delay) -1)
        )
      (let* ((v1-21 (-> self actor-group 0 data 2 actor))
             (gp-0 (if v1-21
                       (-> v1-21 extra process)
                       )
                   )
             )
        (when gp-0
          (let ((f0-0 (-> (the-as water-anim gp-0) root trans y)))
            (when (!= f0-0 (-> self up-y))
              (let ((f0-4 (seek f0-0 (-> self up-y) (* 12288.0 (seconds-per-frame)))))
                (send-event gp-0 'move-to-y f0-4)
                )
              )
            )
          (if (time-elapsed? (-> self state-time) (seconds 2))
              (spawn (-> self part) (-> self root trans))
              )
          )
        )
      )
    )
  :code (behavior ()
    (while (zero? (-> self state-time))
      (suspend)
      )
    (until #f
      (let* ((v1-4 (-> self actor-group 0 data 2 actor))
             (gp-0 (if v1-4
                       (-> v1-4 extra process)
                       )
                   )
             )
        (when gp-0
          (if (< (- (-> (camera-pos) y) (-> (the-as water-anim gp-0) root trans y)) 22528.0)
              (goto cfg-11)
              )
          )
        )
      (suspend)
      )
    #f
    (label cfg-11)
    (let ((a3-1 (res-lump-struct (-> self entity) 'camera-name structure)))
      (if a3-1
          (set-setting! 'entity-name a3-1 0.0 0)
          )
      )
    (until #f
      (let* ((a0-2 (-> self actor-group 0 data 2 actor))
             (v1-19 (if a0-2
                        (-> a0-2 extra process)
                        )
                    )
             )
        (when v1-19
          (when (= (-> (the-as water-anim v1-19) root trans y) (-> self up-y))
            (persist-with-delay *setting-control* 'interp-time (seconds 0.05) 'interp-time 'abs 0.0 0)
            (remove-setting! 'entity-name)
            (send-event (ppointer->process *underb-master*) 'request 'under-warp #t)
            (set! (-> self mode) (under-locking-mode airlock-wait))
            (go-virtual active)
            )
          )
        )
      (suspend)
      )
    #f
    )
  )

(defstate draining (under-locking)
  :virtual #t
  :event (-> (method-of-type under-locking active) event)
  :enter (behavior ()
    (set! (-> self spooled-sound-id)
          (add-process *gui-control* self (gui-channel ashelin) (gui-action queue) "wtrdrain" -99.0 0)
          )
    (set! (-> self state-time) 0)
    0
    )
  :trans (behavior ()
    (when (and (zero? (-> self state-time))
               (= (get-status *gui-control* (-> self spooled-sound-id)) (gui-status ready))
               )
      (set-time! (-> self state-time))
      (set-time! (-> self last-reminder-time))
      (set-action!
        *gui-control*
        (gui-action play)
        (-> self spooled-sound-id)
        (gui-channel none)
        (gui-action none)
        (the-as string #f)
        (the-as (function gui-connection symbol) #f)
        (the-as process #f)
        )
      )
    (when (nonzero? (-> self state-time))
      (let* ((v1-14 (-> self actor-group 0 data 2 actor))
             (gp-0 (if v1-14
                       (-> v1-14 extra process)
                       )
                   )
             )
        (when gp-0
          (let ((f0-0 (-> (the-as water-anim gp-0) root trans y)))
            (when (!= f0-0 (-> self down-y))
              (let ((f0-4 (seek f0-0 (-> self down-y) (* 12288.0 (seconds-per-frame)))))
                (send-event gp-0 'move-to-y f0-4)
                )
              )
            )
          (if (not (time-elapsed? (-> self state-time) (seconds 1)))
              (spawn (-> self draining-part) (-> self root trans))
              )
          )
        )
      )
    )
  :code (behavior ()
    (while (zero? (-> self state-time))
      (suspend)
      )
    (let ((a3-1 (res-lump-struct (-> self entity) 'camera-name structure)))
      (if a3-1
          (set-setting! 'entity-name a3-1 0.0 0)
          )
      )
    (send-event (ppointer->process *underb-master*) 'request 'under-warp #f)
    (until #f
      (let* ((a0-3 (-> self actor-group 0 data 2 actor))
             (v1-15 (if a0-3
                        (-> a0-3 extra process)
                        )
                    )
             )
        (when v1-15
          (if (< (-> (the-as water-anim v1-15) root trans y) (+ 10240.0 (-> (target-pos 0) y)))
              (goto cfg-17)
              )
          )
        )
      (suspend)
      )
    #f
    (label cfg-17)
    (remove-setting! 'entity-name)
    (until #f
      (let* ((a0-8 (-> self actor-group 0 data 2 actor))
             (v1-26 (if a0-8
                        (-> a0-8 extra process)
                        )
                    )
             )
        (when v1-26
          (when (= (-> (the-as water-anim v1-26) root trans y) (-> self down-y))
            (set! (-> self mode) (under-locking-mode want-exit-mech))
            (send-event (ppointer->process *underb-master*) 'request 'mech #f)
            (set! (-> self which-reminder?) #f)
            (go-virtual active)
            )
          )
        )
      (suspend)
      )
    #f
    )
  )

;; WARN: Return type mismatch object vs none.
(defmethod init-from-entity! ((this under-locking) (arg0 entity-actor))
  "Typically the method that does the initial setup on the process, potentially using the [[entity-actor]] provided as part of that.
   This commonly includes things such as:
   - stack size
   - collision information
   - loading the skeleton group / bones
   - sounds"
  (local-vars (sv-16 res-tag))
  (set! (-> this which-reminder?) #f)
  (set! (-> this spooled-sound-id) (new 'static 'sound-id))
  (set! (-> this root) (new 'process 'trsqv))
  (process-drawable-from-entity! this arg0)
  (set! (-> this id) (res-lump-value arg0 'extra-id int :time -1000000000.0))
  (let ((f0-0 (-> this root trans y)))
    (set! (-> this up-y) (+ 49152.0 f0-0))
    (set! (-> this down-y) (+ f0-0 (if (= (-> this id) 2)
                                       -16384.0
                                       -20480.0
                                       )
                              )
          )
    )
  (set! sv-16 (new 'static 'res-tag))
  (let ((a0-6 (res-lump-data (-> this entity) 'actor-groups pointer :tag-ptr (& sv-16))))
    (if (and a0-6 (nonzero? (-> sv-16 elt-count)))
        (set! (-> this actor-group) (the-as (pointer actor-group) a0-6))
        (set! (-> this actor-group) (the-as (pointer actor-group) #f))
        )
    )
  (set! (-> this part) (create-launch-control (-> *part-group-id-table* 498) this))
  (set! (-> this draining-part) (create-launch-control (-> *part-group-id-table* 499) this))
  (go (method-of-object this startup))
  (none)
  )

(deftype water-anim-under (water-anim)
  ()
  )


(define ripple-for-water-anim-under (new 'static 'ripple-wave-set
                                      :count 3
                                      :converted #f
                                      :normal-scale 1.0
                                      :wave (new 'static 'inline-array ripple-wave 4
                                        (new 'static 'ripple-wave :scale 40.0 :xdiv 1 :speed 1.5)
                                        (new 'static 'ripple-wave :scale 40.0 :xdiv -1 :zdiv 1 :speed 1.5)
                                        (new 'static 'ripple-wave :scale 20.0 :xdiv 5 :zdiv 3 :speed 0.75)
                                        (new 'static 'ripple-wave)
                                        )
                                      )
        )

(defmethod init-water! ((this water-anim-under))
  "Initialize a [[water-anim]]'s default settings, this may include applying a [[riple-control]]"
  (let ((t9-0 (method-of-type water-anim init-water!)))
    (t9-0 this)
    )
  (let ((v1-2 (new 'process 'ripple-control)))
    (set! (-> this draw ripple) v1-2)
    (set-vector! (-> this draw color-mult) 0.01 0.45 0.5 0.75)
    (set! (-> v1-2 global-scale) 3072.0)
    (set! (-> v1-2 close-fade-dist) 163840.0)
    (set! (-> v1-2 far-fade-dist) 245760.0)
    (set! (-> v1-2 waveform) ripple-for-water-anim-under)
    )
  0
  (none)
  )
