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

;; name: race-manager.gc
;; name in dgo: race-manager
;; dgos: WASLEAPR, DESRALLY, DESTRACK

(deftype race-manager-stack-var0 (structure)
  "stack slot 16 in race-state::initialize"
  ((mat  matrix :inline :offset 0)
   (vec0 vector :inline :offset 64)
   (vec1 vector :inline :offset 80)
   (word int32          :offset 96)
   )
  )

(deftype race-manager-stack-var1 (structure)
  ((params traffic-object-spawn-params :inline :offset 0)
   (vec0 vector :inline :offset 128)
   (vec1 vector :inline :offset 144)
   (vec2 vector :inline :offset 160)
   )
  )

(declare-type turbo-pickup process-drawable)
(define-extern race-turbo-pickup-spawn (function process vector turbo-pickup))
(define-extern race-vehicle-entity-hack (function none))

;; DECOMP BEGINS

(defun race-find-ground ((arg0 vector) (arg1 vector))
  (let ((s5-0 (new 'stack-no-clear 'collide-query)))
    (vector-copy! (-> s5-0 start-pos) arg1)
    (vector-reset! (-> s5-0 move-dist))
    (set! (-> s5-0 move-dist y) -409600.0)
    (let ((v1-3 s5-0))
      (set! (-> v1-3 radius) 2048.0)
      (set! (-> v1-3 collide-with) (collide-spec backgnd))
      (set! (-> v1-3 ignore-process0) #f)
      (set! (-> v1-3 ignore-process1) #f)
      (set! (-> v1-3 ignore-pat)
            (new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1 :noendlessfall #x1 :board #x1)
            )
      (set! (-> v1-3 action-mask) (collide-action solid))
      )
    (let ((f0-2 (fill-and-probe-using-line-sphere *collide-cache* s5-0)))
      (when (>= f0-2 0.0)
        (vector+*! arg0 (-> s5-0 start-pos) (-> s5-0 move-dist) f0-2)
        #t
        )
      )
    )
  )

(defmethod init-by-mesh! ((this race-info))
  (let ((v1-0 (the-as entity-race-mesh (entity-by-name (-> this race-mesh-name)))))
    (cond
      (v1-0
        (let ((s5-0 (-> v1-0 race-mesh)))
          (set! (-> this mesh) s5-0)
          (when s5-0
            (let ((s4-0 (-> s5-0 edges 0)))
              (vector-average! (-> this start-sphere) (-> s4-0 left) (-> s4-0 right))
              (+! (-> this start-sphere y) 204800.0)
              (race-find-ground (-> this start-sphere) (-> this start-sphere))
              (set! (-> this start-sphere r) (* 0.5 (vector-vector-distance (-> s4-0 left) (-> s4-0 right))))
              (let ((v1-5 (new 'stack-no-clear 'vector)))
                (vector-! v1-5 (-> s4-0 right) (-> s4-0 left))
                (set-vector! (-> this start-dir) (-> v1-5 z) 0.0 (- (-> v1-5 x)) 1.0)
                )
              )
            (vector-normalize! (-> this start-dir) 1.0)
            (let* ((a0-8 (+ (-> s5-0 edge-count) -1))
                   (s4-1 (-> s5-0 edges a0-8))
                   )
              (vector-average! (-> this finish-sphere) (-> s4-1 left) (-> s4-1 right))
              (set! (-> this finish-sphere r) (* 0.75 (vector-vector-distance (-> s4-1 left) (-> s4-1 right))))
              (let ((v1-11 (new 'stack-no-clear 'vector)))
                (vector-! v1-11 (-> s4-1 right) (-> s4-1 left))
                (set-vector! (-> this finish-dir) (-> v1-11 z) 0.0 (- (-> v1-11 x)) 1.0)
                )
              )
            (vector-normalize! (-> this finish-dir) 1.0)
            (let ((f0-16 (vector-vector-xz-distance-squared (-> this start-sphere) (-> this finish-sphere)))
                  (f1-1 409600.0)
                  )
              (when (< f0-16 (* f1-1 f1-1))
                (logior! (-> s5-0 flags) (race-mesh-flag rmf0))
                (vector-copy! (-> this finish-dir) (-> this start-dir))
                (set! (-> this finish-sphere quad) (-> this start-sphere quad))
                )
              )
            )
          )
        )
      (else
        (set! (-> this mesh) #f)
        )
      )
    )
  0
  (none)
  )

(defmethod begin-lap ((this racer-state) (arg0 race-state))
  (format #t "begin-lap racer ~d~%" (-> this rank))
  (set! (-> this lap-start) (-> arg0 current-time))
  (logior! (-> this flags) (racer-state-flags rsf0))
  0
  (none)
  )

(defmethod end-lap ((this racer-state) (arg0 race-state))
  (+! (-> this lap-count) 1)
  (format #t "end-lap ~d racer ~d~%" (-> this lap-count) (-> this rank))
  (let ((v1-2 4)
        (a0-2 3)
        )
    (while (>= a0-2 0)
      (set! (-> this lap-time-array v1-2) (-> this lap-time-array a0-2))
      (+! a0-2 -1)
      (+! v1-2 -1)
      )
    )
  (let ((v1-5 (- (-> arg0 current-time) (-> this lap-start))))
    (set! (-> this best-lap-time) (the-as uint (min (the-as int (-> this best-lap-time)) (the-as int v1-5))))
    (set! (-> this lap-time-array 0) (the-as float v1-5))
    )
  (when (= (-> this lap-count) (-> arg0 info lap-count))
    (logior! (-> this flags) (racer-state-flags rsf1))
    (set! (-> this finish-time) (-> arg0 current-time))
    (set! (-> this finish-count) (-> arg0 finished-count))
    (+! (-> arg0 finished-count) 1)
    (send-event (handle->process (-> this racer)) 'race-finished (-> arg0 info safe-paths))
    (let ((s4-0 (handle->process (-> this racer))))
      (cond
        ((zero? (-> this finish-count))
         (let ((v1-28 (-> this rider)))
           (cond
             ((zero? v1-28)
              (format #t "racer-state::end-lap: play speech race-jak-win~%")
              (speech-control-method-12 *speech-control* (the-as process-drawable s4-0) (speech-type race-jak-win))
              )
             ((= v1-28 1)
              (format #t "racer-state::end-lap: play speech race-daxter-win~%")
              (speech-control-method-12 *speech-control* (the-as process-drawable s4-0) (speech-type race-daxter-win))
              )
             ((= v1-28 2)
              (format #t "racer-state::end-lap: play speech race-errol-win~%")
              (speech-control-method-12 *speech-control* (the-as process-drawable s4-0) (speech-type race-errol-win))
              )
             )
           )
         )
        (else
          (case (-> this rider)
            ((2)
             (format #t "racer-state::end-lap: play speech race-errol-lose~%")
             (speech-control-method-12 *speech-control* (the-as process-drawable s4-0) (speech-type race-errol-lose))
             )
            )
          )
        )
      )
    )
  (when (and (> (-> this lap-count) 0) (= (-> this lap-count) (+ (-> arg0 info lap-count) -1)))
    (let ((s5-1 (handle->process (-> this racer)))
          (v1-47 (-> this rider))
          )
      (cond
        ((zero? v1-47)
         (format #t "racer-state::end-lap: play speech race-jak-last-lap~%")
         (speech-control-method-12 *speech-control* (the-as process-drawable s5-1) (speech-type race-jak-last-lap))
         )
        ((= v1-47 1)
         (format #t "racer-state::end-lap: play speech race-daxter-last-lap~%")
         (speech-control-method-12 *speech-control* (the-as process-drawable s5-1) (speech-type race-daxter-last-lap))
         )
        ((= v1-47 2)
         (format #t "racer-state::end-lap: play speech race-errol-last-lap~%")
         (speech-control-method-12 *speech-control* (the-as process-drawable s5-1) (speech-type race-errol-last-lap))
         )
        )
      )
    )
  0
  (none)
  )

(defmethod update-lap-distance ((this racer-state) (arg0 race-state))
  (let ((s5-0 (new 'stack-no-clear 'matrix3)))
    (-> arg0 info)
    (let ((v1-2 (handle->process (-> this racer))))
      (cond
        (v1-2
          (if (focus-test? (the-as process-focusable v1-2) dead inactive)
              (logior! (-> this flags) (racer-state-flags rsf2))
              )
          (set! (-> s5-0 vector 0 quad) (-> (the-as process-focusable v1-2) root trans quad))
          (when (not (logtest? (-> this flags) (racer-state-flags rsf1 rsf2)))
            (let ((s3-0 (new 'stack-no-clear 'race-mesh-slice-query)))
              (set! (-> s3-0 search-sphere quad) (-> s5-0 vector 0 quad))
              (set! (-> s3-0 search-sphere r) 0.0)
              (race-mesh-method-13 (-> arg0 info mesh) (the-as race-mesh-slice-query (&-> s3-0 slice-id)))
              (set! (-> this lap-distance-prev) (-> this lap-distance))
              (cond
                ((>= (-> s3-0 slice-id) 0)
                 (set! (-> this lap-distance) (-> s3-0 lap-dist))
                 (if (not (logtest? (-> this flags) (racer-state-flags rsf6)))
                     (set! (-> this lap-distance-prev) (-> this lap-distance))
                     )
                 (logior! (-> this flags) (racer-state-flags rsf6))
                 )
                (else
                  (logclear! (-> this flags) (racer-state-flags rsf6))
                  )
                )
              (cond
                ((logtest? (-> arg0 info mesh flags) (race-mesh-flag rmf0))
                 (when (>= (-> s3-0 slice-id) 0)
                   (let ((v1-29 (min 3 (the int (* 4.0 (-> s3-0 lap-dist))))))
                     (when (= v1-29 (logand (+ (-> this lap-quadrant) 1) 3))
                       (set! (-> this lap-quadrant) v1-29)
                       (when (zero? v1-29)
                         (if (logtest? (-> this flags) (racer-state-flags rsf0))
                             (end-lap this arg0)
                             (begin-race arg0)
                             )
                         (begin-lap this arg0)
                         )
                       )
                     )
                   )
                 )
                ((logtest? (-> this flags) (racer-state-flags rsf0))
                 (let ((v1-39 (new 'stack-no-clear 'inline-array 'vector 1)))
                   (vector-! (-> v1-39 0) (-> this position) (the-as vector (-> arg0 info finish-sphere)))
                   (let ((f0-7 (vector-length-squared (-> v1-39 0)))
                         (f1-1 (-> arg0 info finish-sphere r))
                         )
                     (if (and (< f0-7 (* f1-1 f1-1)) (< 0.0 (vector-dot (-> v1-39 0) (-> arg0 info finish-dir))))
                         (end-lap this arg0)
                         )
                     )
                   )
                 )
                (else
                  (when (< 0.0 (-> this lap-distance))
                    (begin-race arg0)
                    (begin-lap this arg0)
                    )
                  )
                )
              )
            (let ((f0-10 (-> arg0 info ai-max-speed-factor)))
              (if (< (+ (-> arg0 target-pos) (-> this target-pos-offset)) (-> this pos))
                  (set! f0-10 (-> arg0 info ai-min-speed-factor))
                  )
              (seek! (-> this speed-factor) f0-10 (* 0.2 (seconds-per-frame)))
              )
            0
            )
          (if (logtest? (-> this flags) (racer-state-flags rsf1))
              (seek! (-> this speed-factor) 0.9 (* 0.2 (seconds-per-frame)))
              )
          (when (logtest? (-> this flags) (racer-state-flags rsf0))
            (dotimes (s3-1 (-> arg0 info decision-point-count))
              (let ((v1-70 (-> arg0 info decision-point-array s3-1)))
                (if (and (< (-> this lap-distance-prev) (-> v1-70 pos)) (>= (-> this lap-distance) (-> v1-70 pos)))
                    (send-event (handle->process (-> this racer)) 'race-decision-point v1-70)
                    )
                )
              )
            (set! (-> this pos) (+ (-> this lap-distance) (the float (-> this lap-count))))
            )
          (vector-copy! (-> this position) (-> s5-0 vector 0))
          )
        (else
          (logior! (-> this flags) (racer-state-flags rsf2))
          )
        )
      )
    )
  (when (logtest? (-> this flags) (racer-state-flags rsf7))
    )
  0
  (none)
  )

(defmethod print-laps ((this racer-state) (arg0 race-state) (arg1 string))
  (let ((s4-0 (- (-> arg0 current-time) (-> this lap-start))))
    (format arg1 "lap count ~d~%" (-> this lap-count))
    (format arg1 "best lap ")
    (print-time arg1 (the-as time-frame (-> this best-lap-time)))
    (format arg1 "~%~%")
    (when (logtest? (-> this flags) (racer-state-flags rsf0))
      (format arg1 "this lap ")
      (print-time arg1 (the-as time-frame s4-0))
      )
    )
  (format arg1 "~%")
  (let ((s4-2 (min 5 (-> this lap-count))))
    (dotimes (s3-0 s4-2)
      (format arg1 "lap ~d " s3-0)
      (print-time arg1 (the-as time-frame (-> this lap-time-array s3-0)))
      (format arg1 "~%")
      )
    )
  0
  (none)
  )

(defmethod init-racer! ((this racer-state) (arg0 process-drawable))
  (set! (-> this racer) (process->handle arg0))
  (vector-copy! (-> this position) (-> arg0 root trans))
  (set! (-> this flags) (racer-state-flags rsf7))
  (set! (-> this lap-count) 0)
  (set! (-> this lap-distance) 0.0)
  (set! (-> this lap-quadrant) 3)
  (set! (-> this finish-time) (the-as uint 0))
  (set! (-> this pos) 0.0)
  (set! (-> this target-pos-offset) 0.0)
  (set! (-> this speed-factor) 1.0)
  (set! (-> this finish-count) -1)
  (set! (-> this best-lap-time) (the-as uint #x2dc6c0))
  0
  (none)
  )

(defmethod init-racers! ((this race-state) (arg0 process-drawable) (arg1 int))
  (when (< arg1 10)
    (let ((s4-0 (-> this racer-array arg1)))
      (let ((s3-0 (-> this info racer-array arg1)))
        (init-racer! s4-0 arg0)
        (set! (-> s4-0 rider) (-> s3-0 rider))
        (set! (-> s4-0 target-pos-offset)
              (* (-> this info ai-spread-factor) (+ (the float (-> s3-0 seek-offset)) (* -3.33 (-> this suck-factor))))
              )
        )
      (let* ((v1-12 (-> s4-0 rider))
             (a2-1 (cond
                     ((or (zero? v1-12) (= v1-12 1))
                      30
                      )
                     ((= v1-12 2)
                      31
                      )
                     (else
                       29
                       )
                     )
                   )
             )
        (add-icon! *minimap* arg0 (the-as uint a2-1) (the-as int #f) (the-as vector #t) 0)
        )
      )
    )
  0
  (none)
  )

(defmethod get-racer-count ((this race-state))
  (let ((gp-0 0))
    (dotimes (s4-0 (-> this racer-count))
      (if (as-type (handle->process (-> this racer-array s4-0 racer)) process-focusable)
          (+! gp-0 1)
          )
      )
    gp-0
    )
  )

(defmethod begin-race ((this race-state))
  (format #t "begin-race~%")
  (when (= (logand (-> this flags) (race-flag rf1)) (race-flag rf0))
    (logior! (-> this flags) (race-flag rf1))
    (send-event (handle->process (-> this manager)) 'begin-race)
    (remove-setting! 'allow-progress)
    (set! (-> this race-start-time) (-> this current-time))
    (let ((s5-0 (handle->process (-> this manager))))
      (set! (-> this hud-timer)
            (ppointer->handle (process-spawn hud-race-timer :init hud-init-by-other :name "hud-race-timer" :to s5-0))
            )
      (if (not (logtest? (-> this info flags) (racer-info-flag rif4)))
          (set! (-> this hud-position)
                (ppointer->handle
                  (process-spawn hud-race-position :init hud-init-by-other :name "hud-race-position" :to s5-0)
                  )
                )
          )
      (if (< 1 (-> this info lap-count))
          (set! (-> this hud-lap-counter)
                (ppointer->handle
                  (process-spawn hud-race-lap-counter :init hud-init-by-other :name "hud-race-lap-counter" :to s5-0)
                  )
                )
          )
      )
    (set-setting! 'race-minimap #f 0.0 (-> this info map-index))
    (dotimes (s5-1 (-> this racer-count))
      (let ((v1-44 (-> this racer-array s5-1)))
        (send-event (handle->process (-> v1-44 racer)) 'begin-race s5-1)
        )
      )
    (send-event (handle->process (-> this race-signal)) 'count-go)
    (when (nonzero? (-> this info go-speech))
      (format #t "playing speech ~d~%" (-> this info go-speech))
      (talker-spawn-func
        (-> *talker-speech* (-> this info go-speech))
        *entity-pool*
        (target-pos 0)
        (the-as region #f)
        )
      )
    )
  0
  (none)
  )

(defmethod update-rankings ((this race-state))
  (let ((v1-0 (new 'stack-no-clear 'array 'float 10)))
    (dotimes (a0-1 (-> this racer-count))
      (let ((a1-3 (-> this racer-array a0-1)))
        (cond
          ((logtest? (-> a1-3 flags) (racer-state-flags rsf1))
           (set! (-> v1-0 a0-1) (the float (- 1000 (-> a1-3 finish-count))))
           )
          ((logtest? (-> a1-3 flags) (racer-state-flags rsf0))
           (set! (-> v1-0 a0-1) (+ (the float (-> a1-3 lap-count)) (-> a1-3 lap-distance)))
           )
          (else
            (set! (-> v1-0 a0-1) 0.0)
            )
          )
        )
      )
    (let ((a0-4 0)
          (a1-16 1)
          )
      (while (< a1-16 (-> this racer-count))
        (let ((a2-7 (-> this rankings a0-4))
              (a3-1 (-> this rankings a1-16))
              )
          (when (< (-> v1-0 a2-7) (-> v1-0 a3-1))
            (set! (-> this rankings a0-4) a3-1)
            (set! (-> this rankings a1-16) a2-7)
            )
          )
        (+! a0-4 1)
        (+! a1-16 1)
        )
      )
    )
  (dotimes (s5-0 (-> this racer-count))
    (let* ((v1-3 (-> this rankings s5-0))
           (s4-0 (-> this racer-array v1-3))
           )
      (if (and (zero? s5-0) (nonzero? (-> s4-0 rank)))
          (send-event (handle->process (-> s4-0 racer)) 'race-pass)
          )
      (if (and (nonzero? s5-0) (zero? (-> s4-0 rank)))
          (send-event (handle->process (-> s4-0 racer)) 'race-got-passed)
          )
      (set! (-> s4-0 rank) s5-0)
      )
    )
  0
  (none)
  )

(defmethod debug-print-rankings ((this race-state))
  (dotimes (s5-0 (-> this racer-count))
    (let* ((s4-0 (-> this rankings s5-0))
           (s3-0 (-> this racer-array s4-0))
           )
      (when (not (logtest? (-> s3-0 flags) (racer-state-flags rsf2)))
        (if (= s4-0 (-> this i-player))
            (format *stdebug* ">>>")
            (format *stdebug* "   ")
            )
        (cond
          ((logtest? (-> s3-0 flags) (racer-state-flags rsf1))
           (format *stdebug* " #~d  finished " (+ s4-0 1))
           (cond
             ((zero? s5-0)
              (let ((a1-3 (- (-> s3-0 finish-time) (-> this race-start-time))))
                (print-time *stdebug* (the-as time-frame a1-3))
                )
              )
             (else
               (format *stdebug* "+")
               (let ((a1-7 (- (- (-> s3-0 finish-time) (-> this race-start-time))
                              (- (-> this racer-array (-> this rankings 0) finish-time) (-> this race-start-time))
                              )
                           )
                     )
                 (print-time *stdebug* (the-as time-frame a1-7))
                 )
               )
             )
           (format *stdebug* "~%")
           )
          (else
            (format *stdebug* " #~d  lap ~d  ~f~%" (+ s4-0 1) (+ (-> s3-0 lap-count) 1) (-> s3-0 lap-distance))
            )
          )
        )
      )
    )
  0
  (none)
  )

(defmethod update-racers ((this race-state))
  (let ((s5-0 0))
    (dotimes (s4-0 (-> this racer-count))
      (let ((s3-0 (-> this racer-array s4-0)))
        (update-lap-distance s3-0 this)
        (if (not (logtest? (-> s3-0 flags) (racer-state-flags rsf1 rsf2)))
            (+! s5-0 1)
            )
        )
      0
      )
    (if (zero? s5-0)
        (set! (-> this state) (race-state-enum rs8))
        )
    )
  0
  (none)
  )

(defmethod setup-race ((this race-state))
  (set-setting! 'allow-progress #f 0.0 0)
  (send-event (handle->process (-> this arrow)) 'leave)
  (send-event (handle->process (-> this race-signal)) 'ready)
  (let ((v1-14 (new 'stack-no-clear 'matrix)))
    (vector-reset! (-> v1-14 fvec))
    (vector-reset! (-> v1-14 trans))
    (let ((a0-17 (-> this racer-array (-> this i-player))))
      (let ((a3-1 (handle->process (-> a0-17 racer))))
        (if a3-1
            (vector-copy! (-> v1-14 rvec) (-> (the-as process-drawable a3-1) root trans))
            )
        )
      (vector-copy! (-> v1-14 uvec) (-> a0-17 start-position))
      )
    (cubic-curve-method-9
      (-> this player-intro-curve)
      (-> v1-14 rvec)
      (-> v1-14 fvec)
      (-> v1-14 uvec)
      (-> v1-14 trans)
      )
    )
  (let ((a0-21 (-> this info hatch-actor-name)))
    (when a0-21
      (let ((a0-22 (process-by-name a0-21 *active-pool*)))
        (send-event a0-22 'open)
        )
      )
    )
  (set! (-> this countdown-start-time) (-> this current-time))
  0
  (none)
  )

(defmethod update ((this race-state))
  (set! (-> this current-time) (the-as uint (current-time)))
  (case (-> this state)
    (((race-state-enum rs0))
     (let ((v1-3 (the-as object #t)))
       (when (= (logand (-> this flags) (race-flag rf4)) (race-flag rf0))
         (dotimes (s5-0 (-> this racer-count))
           (let ((a0-7 (-> this racer-array s5-0)))
             (set! v1-3 (and v1-3 (send-event (handle->process (-> a0-7 racer)) 'test-ready)))
             )
           )
         )
       (when v1-3
         (setup-race this)
         (set! (-> this state) (race-state-enum rs5))
         )
       )
     )
    (((race-state-enum rs1))
     (let ((f30-0 (* 0.0033333334 (the float (- (-> this current-time) (-> this countdown-start-time)))))
           (s5-1 (as-type (handle->process (-> this racer-array (-> this i-player) racer)) process-focusable))
           )
       (cond
         ((< f30-0 1.0)
          (when s5-1
            (cubic-curve-method-10 (-> this player-intro-curve) (-> (the-as process-drawable s5-1) root trans) f30-0)
            (cubic-curve-method-11 (-> this player-intro-curve) (-> (the-as process-drawable s5-1) root transv) f30-0)
            (when (< 0.4 f30-0)
              (if (-> this info start-camera)
                  (set-setting! 'entity-name (-> this info start-camera) 0.0 0)
                  )
              )
            )
          )
         (else
           (set! (-> this state) (race-state-enum rs2))
           )
         )
       )
     )
    (((race-state-enum rs2))
     (let ((s5-2 (as-type (handle->process (-> this racer-array (-> this i-player) racer)) process-focusable)))
       (when s5-2
         (cubic-curve-method-10 (-> this player-intro-curve) (-> (the-as process-drawable s5-2) root trans) 1.0)
         (vector-reset! (-> (the-as process-drawable s5-2) root transv))
         )
       )
     (let ((a0-34 (-> this info hatch-actor-name)))
       (when a0-34
         (let ((a0-35 (process-by-name a0-34 *active-pool*)))
           (send-event a0-35 'close)
           )
         )
       )
     (set! (-> this countdown-start-time) (-> this current-time))
     (set! (-> this state) (if (-> this info countdown-scene)
                               (race-state-enum rs3)
                               (race-state-enum rs5)
                               )
           )
     )
    (((race-state-enum rs3))
     (when (>= (the-as uint (- (current-time) (the-as int (-> this countdown-start-time)))) (the-as uint 300))
       (set! (-> this state) (race-state-enum rs4))
       (set! (-> this scene-player)
             (ppointer->handle
               (process-spawn scene-player :init scene-player-init (-> this info countdown-scene) #t #f :name "scene-player")
               )
             )
       )
     )
    (((race-state-enum rs4))
     (cond
       ((handle->process (-> this scene-player))
        (let ((s5-4 (-> this info)))
          (dotimes (s4-2 (-> s5-4 racer-count))
            (let ((v1-79 (-> this racer-array s4-2)))
              (if (logtest? (-> s5-4 racer-array s4-2 flags) (racer-info-flag rif0))
                  (send-event (handle->process (-> v1-79 racer)) 'hide)
                  )
              )
            )
          )
        )
       (else
         (let ((s5-5 (-> this info)))
           (dotimes (s4-3 (-> s5-5 racer-count))
             (let ((v1-89 (-> this racer-array s4-3)))
               (if (logtest? (-> s5-5 racer-array s4-3 flags) (racer-info-flag rif0))
                   (send-event (handle->process (-> v1-89 racer)) 'unhide)
                   )
               )
             )
           )
         (set! (-> this state) (race-state-enum rs5))
         )
       )
     )
    (((race-state-enum rs5))
     (set! (-> this i-countdown) 4)
     (set! (-> this state) (race-state-enum rs6))
     (set! (-> this countdown-start-time) (-> this current-time))
     (remove-setting! 'entity-name)
     )
    (((race-state-enum rs6))
     (let* ((f0-3 0.2)
            (v1-105 (+ (the int (* 300.0 f0-3)) (- (-> this countdown-start-time) (-> this current-time))))
            )
       (cond
         ((>= v1-105 (the int (* 225.0 f0-3)))
          )
         ((>= v1-105 (the int (* 150.0 f0-3)))
          (when (!= (-> this i-countdown) 3)
            (set! (-> this i-countdown) 3)
            (send-event (handle->process (-> this race-signal)) 'count-3)
            )
          )
         ((>= v1-105 (the int (* 75.0 f0-3)))
          (when (!= (-> this i-countdown) 2)
            (set! (-> this i-countdown) 2)
            (send-event (handle->process (-> this race-signal)) 'count-2)
            )
          )
         ((< (the int (* 0.0 f0-3)) v1-105)
          (when (!= (-> this i-countdown) 1)
            (set! (-> this i-countdown) 1)
            (send-event (handle->process (-> this race-signal)) 'count-1)
            )
          )
         (else
           (set! (-> this i-countdown) 0)
           (set! (-> this state) (race-state-enum rs7))
           (begin-race this)
           )
         )
       )
     (update-racers this)
     )
    (((race-state-enum rs7))
     (update-racers this)
     (update-rankings this)
     )
    (((race-state-enum rs8))
     )
    (else
      )
    )
  (dotimes (s5-6 (-> this info turbo-pad-count))
    (let ((s4-4 (-> this info turbo-pad-array s5-6)))
      (if (not (handle->process (-> s4-4 handle)))
          (set! (-> s4-4 handle)
                (process->handle (race-turbo-pickup-spawn (handle->process (-> this manager)) (-> s4-4 position)))
                )
          )
      )
    )
  0
  (none)
  )

(defmethod race-state-method-15 ((this race-state))
  (when (= (level-status? *level* 'lracelit #f) 'active)
    (let ((gp-1 (-> this info)))
      (handle->process (-> this manager))
      (let ((s5-1 (new 'stack-no-clear 'matrix)))
        (vector-float*! (-> s5-1 fvec) (-> gp-1 start-dir) -1.0)
        (forward-up-nopitch->quaternion
          (the-as quaternion (-> s5-1 uvec))
          (-> s5-1 fvec)
          (new 'static 'vector :y 1.0 :w 1.0)
          )
        (vector+*! (-> s5-1 rvec) (the-as vector (-> gp-1 start-sphere)) (-> gp-1 start-dir) 49152.0)
        (+! (-> s5-1 rvec y) 22528.0)
        )
      )
    )
  0
  (none)
  )

;; WARN: Return type mismatch symbol vs none.
(defmethod deactivate-race ((this race-state))
  (dotimes (s5-0 (-> this info racer-count))
    (let ((v1-3 (-> this racer-array s5-0)))
      (send-event (handle->process (-> v1-3 racer)) 'race-deactivate)
      )
    )
  (none)
  )

(defmethod initialize ((this race-state) (arg0 process) (arg1 race-info))
  (let ((s3-0 (-> this flags)))
    (mem-set32! (the-as pointer this) 328 0)
    (set! (-> this flags) s3-0)
    )
  (set! (-> this info) arg1)
  (set! (-> this manager) (process->handle arg0))
  (set! (-> this scene-player) (the-as handle #f))
  (set! (-> this hud-timer) (the-as handle #f))
  (set! (-> this hud-lap-counter) (the-as handle #f))
  (set! (-> this hud-turbo-counter) (the-as handle #f))
  (set! (-> this hud-position) (the-as handle #f))
  (set! (-> this arrow) (the-as handle #f))
  (set! (-> this race-signal) (the-as handle #f))
  (set! (-> this state) (race-state-enum rs0))
  (set! (-> this racer-count) (-> arg1 racer-count))
  (set! (-> this finished-count) 0)
  (set! (-> this i-player) -1)
  (set! (-> this player-win?) #f)
  (set! (-> this new-score?) #f)
  (dotimes (v1-5 (-> arg1 racer-count))
    (let ((a0-7 (-> arg1 racer-array v1-5 rider)))
      (if (or (zero? a0-7) (= a0-7 1))
          (set! (-> this i-player) v1-5)
          )
      )
    )
  (let ((v1-8 (new 'stack-no-clear 'race-manager-stack-var0)))
    (set! (-> v1-8 vec1 z) 61440.0)
    (set! (-> v1-8 word) 1)
    (set! (-> v1-8 vec0 z) (/ (-> v1-8 vec1 z) -2))
    (set! (-> v1-8 vec0 w) -20480.0)
    (set! (-> v1-8 vec1 x) (/ (-> v1-8 vec1 z) (the float (max 1 (+ (-> v1-8 word) -1)))))
    (set! (-> v1-8 vec1 y) -40960.0)
    (set! (-> v1-8 mat rvec quad) (-> arg1 start-sphere quad))
    (vector-copy! (-> v1-8 mat uvec) (-> arg1 start-dir))
    (set-vector! (-> v1-8 mat fvec) (-> v1-8 mat uvec z) 0.0 (- (-> v1-8 mat uvec x)) 1.0)
    (dotimes (a0-22 (-> arg1 racer-count))
      (cond
        (#t
          (let ((a1-12 a0-22))
            (let ((a2-2 (logand a0-22 1)))
              (set! (-> v1-8 vec0 x) (+ (-> v1-8 vec0 z) (* (-> v1-8 vec1 x) (the float a2-2))))
              )
            (set! (-> v1-8 vec0 y) (+ (-> v1-8 vec0 w) (* (-> v1-8 vec1 y) (the float a1-12))))
            )
          )
        (else
          (let ((a1-15 (/ a0-22 (-> v1-8 word))))
            (let ((a2-5 (- a0-22 (* a1-15 (-> v1-8 word)))))
              (set! (-> v1-8 vec0 x) (+ (-> v1-8 vec0 z) (* (-> v1-8 vec1 x) (the float a2-5))))
              )
            (set! (-> v1-8 vec0 y) (+ (-> v1-8 vec0 w) (* (-> v1-8 vec1 y) (the float a1-15))))
            )
          )
        )
      (let ((a1-20 (-> this racer-array a0-22)))
        (-> arg1 racer-array a0-22)
        (vector-copy! (-> v1-8 mat trans) (-> v1-8 mat rvec))
        (vector+*! (-> v1-8 mat trans) (-> v1-8 mat trans) (-> v1-8 mat uvec) (-> v1-8 vec0 y))
        (vector+*! (-> v1-8 mat trans) (-> v1-8 mat trans) (-> v1-8 mat fvec) (-> v1-8 vec0 x))
        (vector-copy! (-> a1-20 start-position) (-> v1-8 mat trans))
        (set! (-> a1-20 rank) a0-22)
        (set! (-> a1-20 speed-factor) 1.0)
        (set! (-> a1-20 racer) (the-as handle #f))
        )
      (set! (-> this rankings a0-22) a0-22)
      )
    )
  (dotimes (v1-11 (-> this info turbo-pad-count))
    (set! (-> this info turbo-pad-array v1-11 handle) (the-as handle #f))
    )
  (let ((v1-17 (-> *game-info* sub-task-list (-> arg1 task-node))))
    (set! (-> this suck-factor) 0.0)
    (if (not (logtest? (-> arg1 flags) (racer-info-flag rif3)))
        (set! (-> this suck-factor) (fmax 0.0 (fmin 1.0 (* 0.3333 (+ -2.0 (the float (-> v1-17 death-count)))))))
        )
    (format
      #t
      "race-state::initialize: death-count ~d, suck-factor ~f~%"
      (-> v1-17 death-count)
      (-> this suck-factor)
      )
    )
  (logior! (-> this flags) (race-flag rf16))
  0
  (none)
  )

(define *race-state* (new 'static 'race-state))

(define *race-rigid-body-queue* (new 'static 'rigid-body-queue))

(defmethod update ((this race-manager))
  (when *debug-segment*
    (if *display-race-mesh*
        (debug-draw-edges (-> this race-state info mesh))
        )
    (let ((s5-0 *display-race-marks*))
      (when (logtest? s5-0 (race-marks-controls rmc2040))
        (let ((a0-4 (the-as entity-race-mesh (entity-by-name (-> *race-info-array* *select-race* race-mesh-name)))))
          (when a0-4
            (let ((s4-0 (-> a0-4 race-mesh)))
              (when s4-0
                (let ((s3-0 8))
                  (dotimes (s2-0 8)
                    (if (logtest? s5-0 s3-0)
                        (debug-draw-path-from-history s4-0 s2-0 0)
                        )
                    (set! s3-0 (* s3-0 2))
                    )
                  )
                )
              )
            )
          )
        )
      )
    )
  (let ((v1-22 (new 'stack-no-clear 'inline-array 'vector 5)))
    (let ((a0-7 (-> this race-state info)))
      (vector-copy! (-> v1-22 0) (-> a0-7 start-sphere))
      (vector-copy! (-> v1-22 1) (-> a0-7 start-dir))
      )
    (set! (-> v1-22 2 y) 0.0)
    (set! (-> v1-22 2 x) (- (-> v1-22 1 z)))
    (set! (-> v1-22 2 z) (-> v1-22 1 x))
    (vector-float*! (-> v1-22 3) (-> v1-22 2) (-> v1-22 0 w))
    (vector+! (-> v1-22 4) (-> v1-22 0) (-> v1-22 3))
    (vector-! (-> v1-22 5) (-> v1-22 0) (-> v1-22 3))
    )
  0
  (update (-> this race-state))
  0
  )

(defmethod race-manager-method-22 ((this race-manager))
  0
  (none)
  )

(defmethod initialize-race-state ((this race-manager))
  (let ((s5-0 (-> this race-state info)))
    (init-by-mesh! s5-0)
    (initialize (-> this race-state) this s5-0)
    )
  (let ((v1-5 *game-info*))
    (set! (-> v1-5 race-position) 0)
    (set! (-> v1-5 race-current-lap-count) 0)
    (set! (-> v1-5 race-total-lap-count) 0)
    (set! (-> v1-5 race-timer) 0)
    (set! (-> v1-5 race-number-turbos) 0)
    )
  0
  0
  (none)
  )

;; ERROR: Unsupported inline assembly instruction kind - [mfc0 v1, Count]
(defmethod initialize-state ((this race-manager))
  (local-vars (v1-0 int))
  (.mfc0 v1-0 Count)
  (let* ((gp-0 (-> this race-state))
         (s5-0 (-> gp-0 info))
         )
    (if (or (logtest? (-> s5-0 flags) (racer-info-flag rif0))
            (logtest? (continue-flags race) (-> *game-info* last-continue flags))
            )
        (logior! (-> gp-0 flags) (race-flag rf2))
        )
    (let ((s4-0 (new 'stack-no-clear 'race-manager-stack-var1)))
      (vector-copy! (-> s4-0 vec0) (-> gp-0 info start-sphere))
      (vector-copy! (-> s4-0 vec1) (-> gp-0 info start-dir))
      (set-vector! (-> s4-0 vec2) (-> s4-0 vec1 z) 0.0 (- (-> s4-0 vec1 x)) 1.0)
      (set! (-> s4-0 params object-type) (traffic-type vehicle-task))
      (set! (-> s4-0 params behavior) (the-as uint 10))
      (set! (-> s4-0 params id) (the-as uint 0))
      (set! (-> s4-0 params nav-mesh) #f)
      (set! (-> s4-0 params nav-branch) #f)
      (set! (-> s4-0 params proc) #f)
      (set! (-> s4-0 params handle) (the-as handle #f))
      (set! (-> s4-0 params user-data) (the-as uint 0))
      (set! (-> s4-0 params flags) (traffic-spawn-flags tsf6))
      (set! (-> s4-0 params guard-type) (the-as uint 11))
      (set! (-> s4-0 params entity) #f)
      (vector-reset! (-> s4-0 params velocity))
      (forward-up-nopitch->quaternion (-> s4-0 params rotation) (-> s4-0 vec1) (new 'static 'vector :y 1.0 :w 1.0))
      (set! (-> gp-0 race-signal) (the-as handle #f))
      (cond
        ((and *debug-segment* *target* *race-record-path*)
         )
        (else
          (dotimes (s3-0 (-> s5-0 racer-count))
            (let ((v1-23 (-> gp-0 racer-array s3-0))
                  (s2-0 (-> s5-0 racer-array s3-0))
                  )
              (vector-copy! (-> s4-0 params position) (-> v1-23 start-position))
              (set! (-> s4-0 params id) (the-as uint s3-0))
              (set! (-> s4-0 params user-data) (-> s2-0 rider))
              (logior! (-> s4-0 params flags) (traffic-spawn-flags tsf1))
              (logclear! (-> s4-0 params flags) (traffic-spawn-flags tsf5))
              (vector-reset! (-> s4-0 params velocity))
              (let ((v1-32 (-> s2-0 rider)))
                (when (or (zero? v1-32) (= v1-32 1))
                  (logclear! (-> s4-0 params flags) (traffic-spawn-flags tsf1))
                  (logior! (-> s4-0 params flags) (traffic-spawn-flags tsf5))
                  )
                )
              (when (not (and (logtest? (-> gp-0 flags) (race-flag rf8)) (logtest? (-> s2-0 flags) (racer-info-flag rif0))))
                (let ((s1-0 (vehicle-spawn (the-as vehicle-type (-> s2-0 vehicle)) (-> s4-0 params))))
                  (when s1-0
                    (init-racers! gp-0 s1-0 s3-0)
                    (when (and (= s3-0 (-> gp-0 i-player)) (logtest? (-> gp-0 flags) (race-flag rf2)))
                      (let ((v1-51 'pilot))
                        (if (= (-> s2-0 rider) 1)
                            (set! v1-51 'pilot-daxter)
                            )
                        (send-event *target* 'change-mode v1-51 s1-0 0 #t)
                        )
                      )
                    )
                  (if (not s1-0)
                      (format 0 "failed to spawn racebike~%")
                      )
                  )
                )
              )
            )
          )
        )
      )
    )
  0
  0
  (none)
  )

(defmethod save-score ((this race-manager) (arg0 int))
  (local-vars (sv-16 uint) (sv-20 float) (sv-24 symbol) (sv-32 int))
  (set! sv-16 (-> this race-state info score))
  (set! sv-20 (the float arg0))
  (set! sv-24 (the-as symbol #f))
  (set! sv-32 -1)
  (when (nonzero? sv-16)
    (let ((gp-0 (game-info-method-29 *game-info* (the-as int sv-16)))
          (s5-0 (get-highscore-rank *game-info* (the-as int sv-16) sv-20))
          )
      (let ((s4-0 (* (the-as uint (max 0 (- s5-0 gp-0))) (the-as uint (if (= sv-16 3)
                                                                          6
                                                                          3
                                                                          )
                                                                 )
                     )
                  )
            )
        (when (> s4-0 0)
          (set! (-> this finish-sound-id) (the-as sound-id 1))
          (set! sv-24 #t)
          (case s5-0
            ((3)
             (talker-spawn-func (-> *talker-speech* 51) *entity-pool* (target-pos 0) (the-as region #f))
             )
            ((2)
             (talker-spawn-func (-> *talker-speech* 52) *entity-pool* (target-pos 0) (the-as region #f))
             )
            ((1)
             (talker-spawn-func (-> *talker-speech* 53) *entity-pool* (target-pos 0) (the-as region #f))
             )
            )
          )
        (set! sv-32 (game-info-method-27 *game-info* (the-as game-score sv-16) sv-20))
        (give *game-info* 'skill (the float s4-0) (the-as handle #f))
        )
      (if (and (= s5-0 3) (= gp-0 3) (zero? sv-32))
          (set! sv-24 #t)
          )
      )
    )
  sv-24
  )

(defmethod stop-speech ((this race-manager))
  (set-action!
    *gui-control*
    (gui-action stop)
    (the-as sound-id 1)
    (gui-channel guard)
    (gui-action none)
    (the-as string #f)
    (the-as (function gui-connection symbol) #f)
    (the-as process #f)
    )
  (set-action!
    *gui-control*
    (gui-action stop)
    (the-as sound-id 1)
    (gui-channel background)
    (gui-action none)
    (the-as string #f)
    (the-as (function gui-connection symbol) #f)
    (the-as process #f)
    )
  0
  (none)
  )

(defmethod draw-message-continue ((this race-manager))
  (let ((s5-0 (get-status *gui-control* (-> this message-id))))
    (case s5-0
      (((gui-status ready))
       (set-action!
         *gui-control*
         (gui-action play)
         (-> this message-id)
         (gui-channel none)
         (gui-action none)
         (the-as string #f)
         (the-as (function gui-connection symbol) #f)
         (the-as process #f)
         )
       )
      (((gui-status hide))
       (set-action!
         *gui-control*
         (gui-action hidden)
         (-> this message-id)
         (gui-channel none)
         (gui-action none)
         (the-as string #f)
         (the-as (function gui-connection symbol) #f)
         (the-as process #f)
         )
       )
      )
    (when (= s5-0 (gui-status active))
      (let ((gp-1
              (new 'stack 'font-context *font-default-matrix* 70 20 0.0 (font-color orange) (font-flags shadow kerning))
              )
            )
        (set-scale! gp-1 0.7)
        (set-width! gp-1 225)
        (set-height! gp-1 70)
        (set! (-> gp-1 origin x) (the float (- 256 (the int (/ (-> gp-1 width) 2)))))
        (set! (-> gp-1 origin y) 320.0)
        (set! (-> gp-1 flags) (font-flags shadow kerning middle middle-vert large))
        (let ((s5-1 print-game-text))
          (format (clear *temp-string*) (lookup-text! *common-text* (text-id text-007c) #f) 1)
          (s5-1 *temp-string* gp-1 #f 44 (bucket-id hud-draw-hud-alpha))
          )
        )
      )
    )
  0
  (none)
  )

(defmethod draw-message-retry ((this race-manager))
  (let ((s5-0 (get-status *gui-control* (-> this message-id))))
    (case s5-0
      (((gui-status ready))
       (set-action!
         *gui-control*
         (gui-action play)
         (-> this message-id)
         (gui-channel none)
         (gui-action none)
         (the-as string #f)
         (the-as (function gui-connection symbol) #f)
         (the-as process #f)
         )
       )
      (((gui-status hide))
       (set-action!
         *gui-control*
         (gui-action hidden)
         (-> this message-id)
         (gui-channel none)
         (gui-action none)
         (the-as string #f)
         (the-as (function gui-connection symbol) #f)
         (the-as process #f)
         )
       )
      )
    (when (= s5-0 (gui-status active))
      (let ((gp-1
              (new 'stack 'font-context *font-default-matrix* 70 20 0.0 (font-color orange) (font-flags shadow kerning))
              )
            )
        (set-scale! gp-1 0.7)
        (set-width! gp-1 240)
        (set-height! gp-1 35)
        (set! (-> gp-1 origin x) (the float (- 256 (the int (/ (-> gp-1 width) 2)))))
        (set! (-> gp-1 origin y) 320.0)
        (set! (-> gp-1 flags) (font-flags shadow kerning middle middle-vert large))
        (let ((s5-1 print-game-text))
          (format (clear *temp-string*) (lookup-text! *common-text* (text-id text-008b) #f) 1)
          (s5-1 *temp-string* gp-1 #f 44 (bucket-id hud-draw-hud-alpha))
          )
        (+! (-> gp-1 origin y) 35.0)
        (let ((s5-2 print-game-text))
          (format (clear *temp-string*) (lookup-text! *common-text* (text-id text-0081) #f) 1)
          (s5-2 *temp-string* gp-1 #f 44 (bucket-id hud-draw-hud-alpha))
          )
        )
      )
    )
  0
  (none)
  )

(defbehavior race-manager-event-handler race-manager ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  (local-vars (v0-0 object))
  (case arg2
    (('die)
     (go-virtual die)
     )
    (('force-start)
     (set! v0-0 (logior (-> self race-state flags) (race-flag rf4)))
     (set! (-> self race-state flags) (the-as race-flag v0-0))
     v0-0
     )
    (('begin-race)
     (send-event (ppointer->process (-> self parent)) 'fail-on-death #t)
     )
    (('win)
     0
     )
    (('lose)
     0
     )
    (('show-stats)
     (set! v0-0 #t)
     (set! (-> self show-stats?) (the-as symbol v0-0))
     v0-0
     )
    (('kill-npc-racers)
     (let ((gp-0 (-> self race-state info)))
       (dotimes (s5-0 (-> gp-0 racer-count))
         (let ((v1-16 (-> self race-state racer-array s5-0)))
           (if (!= s5-0 (-> self race-state i-player))
               (send-event (handle->process (-> v1-16 racer)) 'go-die)
               )
           )
         )
       )
     #f
     )
    )
  )

(defstate idle (race-manager)
  :virtual #t
  :event race-manager-event-handler
  :code (behavior ()
    (while (not (and *target* (or (not (focus-test? *target* teleporting)) (focus-test? *target* pilot))))
      (suspend)
      )
    (initialize-race-state self)
    (cond
      ((logtest? (-> self race-state info flags) (racer-info-flag rif5))
       (while (!= (get-racer-count (-> self race-state)) (-> self race-state racer-count))
         (update self)
         (suspend)
         )
       )
      (else
        (initialize-state self)
        )
      )
    (suspend)
    (let ((gp-1 (-> self race-state info)))
      (when (and (-> gp-1 countdown-scene) (not (logtest? (-> self race-state flags) (race-flag rf2))))
        (dotimes (s5-0 (-> gp-1 racer-count))
          (let ((v1-28 (-> self race-state racer-array s5-0)))
            (if (and (logtest? (-> gp-1 racer-array s5-0 flags) (racer-info-flag rif0))
                     (!= s5-0 (-> self race-state i-player))
                     )
                (send-event (handle->process (-> v1-28 racer)) 'hide)
                )
            )
          )
        )
      )
    (when (and *debug-segment* *target* *race-record-path*)
      (until #f
        (update self)
        (suspend)
        )
      #f
      )
    (go-virtual active)
    )
  )

(defstate active (race-manager)
  :virtual #t
  :event race-manager-event-handler
  :code sleep-code
  :post (behavior ()
    (update self)
    (let ((s5-0 (-> self race-state racer-array (-> self race-state i-player)))
          (gp-0 (-> self race-state))
          )
      (set! (-> gp-0 target-pos) (-> s5-0 pos))
      (let ((v1-5 *game-info*))
        (set! (-> v1-5 race-position) (-> s5-0 rank))
        (set! (-> v1-5 race-current-lap-count) (min (+ (-> s5-0 lap-count) 1) (-> self race-state info lap-count)))
        (set! (-> v1-5 race-total-lap-count) (-> self race-state info lap-count))
        (let ((a0-12 (-> gp-0 current-time)))
          (if (logtest? (-> s5-0 flags) (racer-state-flags rsf1))
              (set! a0-12 (-> s5-0 finish-time))
              )
          (let ((a0-13 (the-as int (- a0-12 (-> gp-0 race-start-time)))))
            (if (= (logand (-> gp-0 flags) (race-flag rf1)) (race-flag rf0))
                (set! a0-13 0)
                )
            (set! (-> v1-5 race-timer) (the-as time-frame a0-13))
            )
          )
        )
      (when (logtest? (-> gp-0 flags) (race-flag rf1))
        (cond
          ((logtest? (-> s5-0 flags) (racer-state-flags rsf6))
           (set-time! (-> self player-on-track-time))
           )
          (else
            (when (time-elapsed? (-> self player-on-track-time) (seconds 0.5))
              (let ((v1-16 (handle->process (-> s5-0 racer))))
                (when v1-16
                  (if (logtest? (-> (the-as rigid-body-object v1-16) flags) (rigid-body-object-flag on-flight-level))
                      (go-virtual fail)
                      )
                  )
                )
              )
            )
          )
        )
      (if (or (logtest? (-> s5-0 flags) (racer-state-flags rsf2)) (not *target*) (focus-test? *target* dead))
          (go-virtual fail)
          )
      (when (logtest? (-> s5-0 flags) (racer-state-flags rsf1))
        (when (not (logtest? (-> s5-0 flags) (racer-state-flags rsf5)))
          (logior! (-> s5-0 flags) (racer-state-flags rsf5))
          (set! (-> gp-0 new-score?) (save-score self (the-as int (- (-> s5-0 finish-time) (-> gp-0 race-start-time)))))
          )
        (send-event (ppointer->process (-> self parent)) 'allow-fail #f)
        (set! (-> self message-id)
              (add-process *gui-control* self (gui-channel hud-lower-center) (gui-action play) "fail" 81920.0 0)
              )
        (set! (-> self show-stats?) #f)
        (set! (-> gp-0 player-win?) (if (logtest? (-> gp-0 info flags) (racer-info-flag rif6))
                                        (-> gp-0 new-score?)
                                        (zero? (-> s5-0 finish-count))
                                        )
              )
        (if (-> gp-0 player-win?)
            (go-virtual win)
            (go-virtual lose)
            )
        )
      )
    )
  )

(defstate win (race-manager)
  :virtual #t
  :event race-manager-event-handler
  :code (behavior ()
    (if (zero? (-> self finish-sound-id))
        (set! (-> self finish-sound-id)
              (add-process *gui-control* *target* (gui-channel background) (gui-action play) "miss001" -99.0 0)
              )
        )
    (send-event (ppointer->process (-> self parent)) 'race-win)
    (send-event (handle->process (-> self race-state hud-timer)) 'force-hide)
    (send-event (handle->process (-> self race-state hud-lap-counter)) 'force-hide)
    (send-event (handle->process (-> self race-state hud-turbo-counter)) 'force-hide)
    (while (not (-> self show-stats?))
      (suspend)
      )
    (process-spawn hud-race-final-stats :init hud-init-by-other :name "hud-race-final-stats" :to self)
    (set-time! (-> self state-time))
    (when (logtest? (-> self race-state info flags) (racer-info-flag rif1))
      (send-event (ppointer->process (-> self parent)) 'complete)
      (sleep-code)
      )
    (until #f
      (cond
        ((logtest? (-> self race-state info flags) (racer-info-flag rif2))
         (draw-message-retry self)
         (when (time-elapsed? (-> self state-time) (seconds 0.5))
           (cond
             ((cpad-pressed? 0 confirm)
              (stop-speech self)
              (send-event (ppointer->process (-> self parent)) 'allow-fail #t)
              (send-event (ppointer->process (-> self parent)) 'restart)
              (sleep-code)
              )
             ((cpad-pressed? 0 triangle)
              (stop-speech self)
              (send-event (ppointer->process (-> self parent)) 'allow-fail #t)
              (send-event (ppointer->process (-> self parent)) 'quit)
              (sleep-code)
              )
             )
           )
         )
        (else
          (when (time-elapsed? (-> self state-time) (seconds 1.5))
            (draw-message-continue self)
            (when (cpad-pressed? 0 confirm)
              (stop-speech self)
              (send-event (ppointer->process (-> self parent)) 'complete)
              (sleep-code)
              )
            )
          )
        )
      (suspend)
      )
    #f
    )
  :post (behavior ()
    (update self)
    )
  )

(defstate lose (race-manager)
  :virtual #t
  :event race-manager-event-handler
  :code (behavior ()
    (if (zero? (-> self finish-sound-id))
        (set! (-> self finish-sound-id)
              (add-process *gui-control* *target* (gui-channel background) (gui-action play) "lose1" -99.0 0)
              )
        )
    (send-event (ppointer->process (-> self parent)) 'race-lose)
    (send-event (handle->process (-> self race-state hud-timer)) 'force-hide)
    (send-event (handle->process (-> self race-state hud-lap-counter)) 'force-hide)
    (send-event (handle->process (-> self race-state hud-turbo-counter)) 'force-hide)
    (while (not (-> self show-stats?))
      (suspend)
      )
    (process-spawn hud-race-final-stats :init hud-init-by-other :name "hud-race-final-stats" :to self)
    (set-time! (-> self state-time))
    (until #f
      (draw-message-retry self)
      (-> self race-state info)
      (when (time-elapsed? (-> self state-time) (seconds 0.5))
        (cond
          ((cpad-pressed? 0 confirm)
           (stop-speech self)
           (send-event (ppointer->process (-> self parent)) 'allow-fail #t)
           (send-event (ppointer->process (-> self parent)) 'restart)
           (sleep-code)
           )
          ((cpad-pressed? 0 triangle)
           (stop-speech self)
           (send-event (ppointer->process (-> self parent)) 'allow-fail #t)
           (send-event (ppointer->process (-> self parent)) 'quit)
           (sleep-code)
           )
          )
        )
      (suspend)
      )
    #f
    )
  :post (behavior ()
    (update self)
    )
  )

(defstate fail (race-manager)
  :virtual #t
  :event race-manager-event-handler
  :code (behavior ()
    (send-event (handle->process (-> self race-state hud-timer)) 'force-hide)
    (send-event (handle->process (-> self race-state hud-lap-counter)) 'force-hide)
    (send-event (handle->process (-> self race-state hud-turbo-counter)) 'force-hide)
    (send-event (ppointer->process (-> self parent)) 'fail)
    (set-time! (-> self state-time))
    (until #f
      (suspend)
      )
    #f
    )
  )

(defstate die (race-manager)
  :virtual #t
  :code (behavior ()
    '()
    )
  )

(defmethod deactivate ((this race-manager))
  "Make a process dead, clean it up, remove it from the active pool, and return to dead pool."
  (deactivate-race (-> this race-state))
  (send-event *traffic-manager* 'restore-default-settings)
  (call-parent-method this)
  (none)
  )

;; WARN: Return type mismatch object vs none.
(defbehavior race-manager-init-by-other race-manager ((arg0 race-info) (arg1 symbol))
  (stack-size-set! (-> self main-thread) 1024)
  (set! (-> self entity) #f)
  (race-vehicle-entity-hack)
  (set! (-> self race-state) *race-state*)
  (set! (-> self race-state info) arg0)
  (set! (-> self race-state flags) (race-flag rf0))
  (set! *race-manager* (the-as (pointer race-manager) (process->ppointer self)))
  (set! (-> arg0 manager) (process->handle self))
  (set! (-> self finish-sound-id) (new 'static 'sound-id))
  (set! (-> self show-stats?) #f)
  (if arg1
      (logior! (-> self race-state flags) (race-flag rf8))
      )
  (go-virtual idle)
  (none)
  )

;; ERROR: Unsupported inline assembly instruction kind - [mfc0 s5, Count]
;; ERROR: Unsupported inline assembly instruction kind - [mfc0 v1, Count]
(defun race-start ((arg0 int) (arg1 process) (arg2 symbol))
  (local-vars (v1-11 int) (s5-0 int))
  (let ((s2-0 (-> *race-info-array* arg0))
        (gp-0 (the-as process #f))
        )
    (.mfc0 s5-0 Count)
    (when (not (handle->process (-> s2-0 manager)))
      (format #t "starting race-manager~%")
      (if (not arg1)
          (set! arg1 (the-as process *entity-pool*))
          )
      (let ((v1-9 (process-spawn race-manager s2-0 arg2 :name "race-manager" :to (the-as process-tree arg1))))
        (when v1-9
          (set! gp-0 (-> v1-9 0))
          (.mfc0 v1-11 Count)
          (format #t "race-manager started in ~f ms~%" (* 0.0000033333333 (the float (- v1-11 s5-0))))
          )
        )
      )
    gp-0
    )
  )

;; WARN: Return type mismatch symbol vs none.
(defun race-kill ()
  (kill-by-type race-manager *active-pool*)
  (none)
  )

(defun race-vehicle-entity-hack ()
  (with-pp
    (set! (-> pp level) (-> *traffic-info* race-vehicle-level))
    0
    (none)
    )
  )

(defun race-level-activate ((arg0 level))
  (format 0 "race-level-activate~%")
  (set! (-> *traffic-info* race-vehicle-level) arg0)
  0
  (none)
  )

(defun race-level-deactivate ()
  (let ((v1-0 *traffic-info*))
    (set! (-> v1-0 race-vehicle-level) (the-as level #f))
    )
  0
  (none)
  )
