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

;; name: game-info.gc
;; name in dgo: game-info
;; dgos: ENGINE, GAME

;; initialize was manually fixed.

(define-extern demo? (function symbol))
(define-extern task-resolution-close! (function game-task symbol))
(define-extern *lightning-darkjak-pill* lightning-spec)
(define-extern lightning-probe-callback (function lightning-tracker none))
(define-extern process-drawable-shock-effect (function process-drawable lightning-spec (function lightning-tracker none) sparticle-launcher int int float object)) ;; guess

;; DECOMP BEGINS

(defmethod debug-draw ((this border-plane))
  (let* ((v1-0 (-> this action))
         (plane-color (if (= v1-0 'load)
                          (the-as uint #x8000ff00)
                          (the-as uint #x800000ff)
                          )
                      )
         )
    (add-debug-text-sphere
      #t
      (bucket-id debug-no-zbuf1)
      (-> this trans)
      (meters 0.2)
      (symbol->string (-> this name))
      (the-as rgba plane-color)
      )
    (add-debug-vector
      #t
      (bucket-id debug-no-zbuf1)
      (-> this trans)
      (-> this normal)
      (meters 2)
      (the-as rgba plane-color)
      )
    )
  0
  )

(defmethod point-past-plane? ((this border-plane) (arg0 vector))
  (>= (vector-dot (vector-! (new 'stack-no-clear 'vector) arg0 (-> this trans)) (-> this normal)) 0.0)
  )

(defmethod task-complete? ((this game-info) (arg0 game-task))
  (logtest? (-> this task-perm-list data arg0 status) (entity-perm-status complete))
  )

(defmethod subtask-index-by-name ((this game-info) (arg0 string))
  (let ((subtasks (-> *game-info* sub-task-list)))
    (dotimes (i (-> subtasks length))
      (when (nonzero? i)
        (let ((v1-4 (-> subtasks i)))
          (if (string= arg0 (-> v1-4 name))
              (return i)
              )
          )
        )
      )
    )
  0
  )

(defmethod set-subtask-hook! ((this game-info) (arg0 game-task-node) (arg1 int) (arg2 function))
  (let ((subtask (-> this sub-task-list arg0)))
    (if (and subtask (-> subtask info))
        (set! (-> subtask info hooks arg1) arg2)
        )
    )
  arg2
  )

(define *default-continue*
  (new 'static 'continue-point
    :name "default"
    :level #f
    :flags (continue-flags change-continue)
    :trans (new 'static 'vector :w 1.0)
    :quat (new 'static 'vector :w 1.0)
    :camera-trans (new 'static 'vector :w 1.0)
    :on-goto #f
    :vis-nick #f
    :want (new 'static 'inline-array level-buffer-state 6
      (new 'static 'level-buffer-state :name #f :display? #f :force-vis? #f :force-inside? #f)
      (new 'static 'level-buffer-state :name #f :display? #f :force-vis? #f :force-inside? #f)
      (new 'static 'level-buffer-state :name #f :display? #f :force-vis? #f :force-inside? #f)
      (new 'static 'level-buffer-state :name #f :display? #f :force-vis? #f :force-inside? #f)
      (new 'static 'level-buffer-state :name #f :display? #f :force-vis? #f :force-inside? #f)
      (new 'static 'level-buffer-state :name #f :display? #f :force-vis? #f :force-inside? #f)
      )
    :want-sound (new 'static 'array symbol 3 #f #f #f)
    )
  )

(defmethod continue-point-method-10 ((this continue-point) (arg0 load-state))
  (let ((v1-0 (lookup-level-info (-> this vis-nick))))
    (set! (-> this vis-nick) (if v1-0
                                (-> v1-0 name)
                                )
          )
    )
  (dotimes (s4-0 6)
    (mem-copy! (the-as pointer (-> this want s4-0)) (the-as pointer (-> arg0 want s4-0)) 16)
    )
  (dotimes (v1-7 3)
    (set! (-> this want-sound v1-7) (-> arg0 want-sound v1-7))
    )
  (set! (-> this camera-trans quad) (-> *camera-combiner* trans quad))
  (when *camera-combiner*
    (let ((a0-10 (-> *camera-combiner* inv-camera-rot))
          (v1-14 (-> this camera-rot))
          )
      (set! (-> v1-14 0 x) (-> a0-10 vector 0 x))
      (set! (-> v1-14 0 y) (-> a0-10 vector 0 y))
      (set! (-> v1-14 0 z) (-> a0-10 vector 0 z))
      (set! (-> v1-14 1 x) (-> a0-10 vector 1 x))
      (set! (-> v1-14 1 y) (-> a0-10 vector 1 y))
      (set! (-> v1-14 1 z) (-> a0-10 vector 1 z))
      (set! (-> v1-14 2 x) (-> a0-10 vector 2 x))
      (set! (-> v1-14 2 y) (-> a0-10 vector 2 y))
      (set! (-> v1-14 2 z) (-> a0-10 vector 2 z))
      )
    )
  (add-borrow-levels arg0)
  this
  )

(defmethod move-camera! ((this continue-point))
  (set! (-> *camera-combiner* trans quad) (-> this camera-trans quad))
  (let ((gp-0 (-> *camera-combiner* inv-camera-rot))
        (s5-0 (-> this camera-rot))
        )
    (matrix-identity! gp-0)
    (set! (-> gp-0 vector 0 x) (-> s5-0 0 x))
    (set! (-> gp-0 vector 0 y) (-> s5-0 0 y))
    (set! (-> gp-0 vector 0 z) (-> s5-0 0 z))
    (set! (-> gp-0 vector 1 x) (-> s5-0 1 x))
    (set! (-> gp-0 vector 1 y) (-> s5-0 1 y))
    (set! (-> gp-0 vector 1 z) (-> s5-0 1 z))
    (set! (-> gp-0 vector 2 x) (-> s5-0 2 x))
    (set! (-> gp-0 vector 2 y) (-> s5-0 2 y))
    (set! (-> gp-0 vector 2 z) (-> s5-0 2 z))
    )
  (send-event *camera* 'change-target *target*)
  (cam-master-activate-slave #t)
  0
  (none)
  )

(defmethod get-current-continue-forced ((this game-info))
  (cond
    ((and (= (-> this mode) 'play) (-> this current-continue))
     (-> this current-continue)
     )
    (else
      (let ((dfault *default-continue*))
        (position-in-front-of-camera! (-> dfault trans) 40960.0 4096.0)
        (quaternion-identity! (the-as quaternion (-> dfault quat)))
        (continue-point-method-10 dfault *load-state*)
        dfault
        )
      )
    )
  )

(defmethod get-continue-by-name ((this game-info) (arg0 string))
  (if (not arg0)
      (return (the-as continue-point #f))
      )
  (let ((s5-0 *level-load-list*))
    (while (not (null? s5-0))
      (let ((continues (-> (the-as level-load-info (-> (the-as symbol (car s5-0)) value)) continues)))
        (while (not (null? continues))
          (let ((cont (the-as continue-point (car continues))))
            (if (string= arg0 (-> cont name))
                (return cont)
                )
            )
          (set! continues (cdr continues))
          )
        )
      (set! s5-0 (cdr s5-0))
      )
    )
  (the-as continue-point #f)
  )

;; WARN: Using new Jak 2 rtype-of
(defmethod set-continue! ((this game-info) (arg0 basic) (arg1 symbol))
  (let ((s5-0 (-> this current-continue)))
    (if (null? arg0)
        (set! arg0 (the-as basic #f))
        )
    (case (rtype-of arg0)
      ((string)
       (let ((v1-7 (get-continue-by-name this (the-as string arg0))))
         (if v1-7
             (set! (-> this current-continue) v1-7)
             )
         )
       )
      ((continue-point)
       (set! (-> this current-continue) (the-as continue-point arg0))
       )
      (else
        (let ((dfault *default-continue*))
          (position-in-front-of-camera! (-> dfault trans) 40960.0 4096.0)
          (quaternion-identity! (the-as quaternion (-> dfault quat)))
          (let ((v1-9 (lookup-level-info (-> *load-state* vis-nick))))
            (set! (-> dfault vis-nick) (if v1-9
                                           (-> v1-9 name)
                                           )
                  )
            )
          (dotimes (s2-0 6)
            (mem-copy! (the-as pointer (-> dfault want s2-0)) (the-as pointer (-> *load-state* want s2-0)) 16)
            )
          (dotimes (v1-16 3)
            (set! (-> dfault want-sound v1-16) (-> *load-state* want-sound v1-16))
            )
          (set! (-> this current-continue) dfault)
          )
        )
      )
    (if (and (logtest? (-> this current-continue flags) (continue-flags change-continue))
             (and (!= (-> this current-continue) *default-continue*) (not arg1))
             )
        (set! (-> this current-continue) s5-0)
        )
    (when (!= s5-0 (-> this current-continue))
      (set! (-> this continue-deaths) 0)
      (set! (-> this continue-time) (-> *display* game-clock frame-counter))
      )
    )
  (-> this current-continue)
  )

(defmethod task-perm-by-index ((this game-info) (arg0 int))
  (-> this task-perm-list data arg0)
  )

(defmethod calculate-percentage ((this game-info))
  (let ((story-total 0)
        (story-complete 0)
        )
    0.0
    (let ((story-min (game-task fortress-escape))
          (story-max (game-task nest-boss))
          )
      (while (>= (the-as uint story-max) (the-as uint story-min))
        (when (not (or (= story-min (game-task city-blue-gun-training)) (= story-min (game-task city-dark-gun-training))))
          (+! story-total 1)
          (if (task-complete? this story-min)
              (+! story-complete 1)
              )
          )
        (+! story-min 1)
        )
      )
    (let ((percent (/ (* 100.0 (the float story-complete)) (the float story-total))))
      (when (= story-complete story-total)
        (let ((bbush-min (game-task city-burning-bush-ring-1))
              (bbush-max (game-task stadium-burning-bush-race-class1-r))
              )
          (while (>= (the-as uint bbush-max) (the-as uint bbush-min))
            (if (task-complete? this bbush-min)
                (set! percent (+ 1.0 percent))
                )
            (+! bbush-min 1)
            )
          )
        )
      percent
      )
    )
  )

(defun task-level->string ((arg0 int))
  (symbol->string (-> *task-level* arg0))
  )

(defun level-name->task-level ((arg0 symbol))
  (let ((v1-0 (lookup-level-info arg0)))
    (if v1-0
        (the-as int (-> v1-0 task-level))
        0
        )
    )
  )

(defmethod initialize! ((this game-info) (arg0 symbol) (arg1 game-save) (arg2 string))
  (local-vars (v0-3 int) (sv-96 game-task-node-info) (sv-112 symbol))
  (case arg0
    (('dead 'life)
     (+! (-> this total-deaths) 1)
     (+! (-> this continue-deaths) 1)
     (+! (-> this task-deaths) 1)
     (when *target*
       (let ((s4-1 (-> *target* current-level info)))
         (set! (-> this deaths-per-level (-> s4-1 task-level))
               (the-as uint (seekl (the-as int (-> this deaths-per-level (-> s4-1 task-level))) 255 1))
               )
         )
       )
     (case (-> this mode)
       (('play)
        (set! arg0 'life)
        )
       (else
         (set! this this)
         (goto cfg-131)
         )
       )
     )
    (('try)
     (+! (-> this total-trys) 1)
     )
    )
  (case arg0
    (('dead 'life 'try)
     (let ((s2-0 (level-get-target-inside *level*)))
       (when s2-0
         (let ((s1-0 (-> *game-info* sub-task-list)))
           (dotimes (s0-0 (-> s1-0 length))
             (when (nonzero? s0-0)
               (set! sv-96 (-> s1-0 s0-0))
               (if (open? sv-96)
                   (set! v0-3 (when (and (= (-> s2-0 info taskname) (-> sv-96 level))
                                         (and (or (not (-> sv-96 info)) (handle->process (-> sv-96 info manager)))
                                              (>= (- (-> *display* game-clock frame-counter) (-> this death-time)) (seconds 2))
                                              )
                                         )
                                (format #t "death count inc for ~S~%" (-> sv-96 name))
                                (set! v0-3 (seekl (the-as int (-> sv-96 death-count)) #xffff 1))
                                (set! (-> sv-96 death-count) (the-as uint v0-3))
                                v0-3
                                )
                         )
                   )
               )
             )
           )
         )
       )
     (set! (-> this death-time) (-> *display* game-clock frame-counter))
     )
    )
  (kill-current-talker (the-as symbol '()) '() 'die)
  (case arg0
    (('game)
     (+! (-> this task-counter) 1)
     (reset! (-> *display* total-game-clock))
     (set! (-> this features) (game-feature sidekick))
     (set! (-> this debug-features) (game-feature))
     (set! (-> this secrets) (game-secrets))
     (set! (-> this purchase-secrets) (game-secrets))
     (set-continue!
       this
       (cond
         (arg2
           (empty)
           arg2
           )
         ((demo?)
          "demo-start"
          )
         (*debug-segment*
           "game-start"
           )
         (else
           "title-start"
           )
         )
       #f
       )
     (set! (-> this auto-save-count) 0)
     (set! (-> *setting-control* user-default auto-save) #f)
     (set! (-> this money) 0.0)
     (set! (-> this money-total) 0.0)
     (set! (-> this fuel) 0.0)
     (set! (-> this buzzer-total) 0.0)
     (set! (-> this eco-pill-dark) 0.0)
     (set! (-> this eco-pill-dark-total) 0.0)
     (set! (-> this gem) 0.0)
     (set! (-> this gem-total) 0.0)
     (set! (-> this skill) 0.0)
     (set! (-> this skill-total) 0.0)
     (set! (-> this karma) 0.0)
     (set! (-> this perm-list length) 0)
     (dotimes (v1-69 (-> this unknown-pad6 allocated-length))
       (set! (-> this unknown-pad6 v1-69) (the-as uint 0))
       )
     (set! (-> this death-movie-tick) (rand-vu-int-count 10))
     (set! (-> this gun-type) (pickup-type eco-red))
     (set! (-> this gun-ammo 0) (-> *FACT-bank* ammo-yellow-start))
     (set! (-> this gun-ammo 1) (-> *FACT-bank* ammo-red-start))
     (set! (-> this gun-ammo 2) (-> *FACT-bank* ammo-blue-start))
     (set! (-> this gun-ammo 3) (-> *FACT-bank* ammo-dark-start))
     (set! (-> this shield) 100.0)
     (set! (-> this score) 0.0)
     (set! (-> this score-owner) (the-as handle #f))
     (set! (-> this goal) 0.0)
     (set! (-> this miss) 0.0)
     (set! (-> this miss-max) 0.0)
     (set! (-> this timer) 0)
     (set! (-> this timer-flash) #f)
     (set! (-> this timer-owner) (the-as handle #f))
     (set! (-> this counter) 0.0)
     (set! (-> this counter-flash) #f)
     (set! (-> this wanted-flash) #f)
     (set! (-> this distance) 0.0)
     (set! (-> this attack-id) (the-as uint 2))
     (set! (-> this total-trys) 0)
     (set! (-> this total-deaths) 0)
     (set! (-> this continue-deaths) 0)
     (set! (-> this task-deaths) 0)
     (set! (-> this death-pos length) 0)
     (set! (-> this game-start-time) (-> *display* game-clock frame-counter))
     (set! (-> this task-pickup-time) (-> *display* game-clock frame-counter))
     (set! (-> this continue-time) (-> *display* game-clock frame-counter))
     (set! (-> this death-time) (-> *display* game-clock frame-counter))
     (set! (-> this hit-time) (-> *display* game-clock frame-counter))
     (dotimes (v1-95 110)
       (set! (-> this unknown-array1 0) 0)
       (set! (-> this task-close-times 0) 0)
       (nop!)
       )
     (dotimes (v1-98 32)
       (set! (-> this money-per-level v1-98) (the-as uint 0))
       (set! (-> this deaths-per-level v1-98) (the-as uint 0))
       (set! (-> this task-enter-times v1-98) 0)
       (set! (-> this task-in-times v1-98) 0)
       (set! (-> this level-opened v1-98) (the-as uint 0))
       (nop!)
       )
     (let ((v1-102 (-> *game-info* sub-task-list)))
       (dotimes (a0-41 (-> v1-102 length))
         (when (nonzero? a0-41)
           (let ((a1-16 (-> v1-102 a0-41)))
             (set! (-> a1-16 death-count) (the-as uint 0))
             (set! (-> a1-16 gem-count) (the-as uint 0))
             (set! (-> a1-16 skill-count) (the-as uint 0))
             (set! (-> a1-16 close-time) 0)
             )
           0
           )
         )
       )
     (dotimes (v1-105 (-> this game-score length))
       (set! (-> this game-score v1-105) 0.0)
       )
     (dotimes (s3-1 19)
       (case s3-1
         ((4 5 6 7 10 11 12 13 15 14 16 17 18)
          (let ((v1-112 (get-game-score-ref this s3-1))
                (a0-62 (-> *highscore-info-array* s3-1))
                )
            (set! (-> v1-112 0) (-> a0-62 gold-score))
            (set! (-> v1-112 1) (-> a0-62 silver-score))
            (set! (-> v1-112 2) (-> a0-62 bronze-score))
            )
          )
         )
       )
     (initialize *bigmap*)
     )
    )
  (case arg0
    (('game 'try 'life)
     (case (-> this mode)
       (('play)
        (set! *display-profile* #f)
        (set! *display-entity-errors* #f)
        )
       )
     (set! (-> this life-max) (-> *GAME-bank* life-max-default))
     (set! (-> this life) (-> *GAME-bank* life-start-default))
     (set! (-> this gun-ammo 0)
           (fmax (-> this gun-ammo 0) (* (you-suck-scale *game-info* #f) (-> *FACT-bank* ammo-yellow-start)))
           )
     (set! (-> this gun-ammo 1)
           (fmax (-> this gun-ammo 1) (* (you-suck-scale *game-info* #f) (-> *FACT-bank* ammo-red-start)))
           )
     (set! (-> this gun-ammo 2)
           (fmax (-> this gun-ammo 2) (* (you-suck-scale *game-info* #f) (-> *FACT-bank* ammo-blue-start)))
           )
     (set! (-> this gun-ammo 3)
           (fmax (-> this gun-ammo 3) (* (you-suck-scale *game-info* #f) (-> *FACT-bank* ammo-dark-start)))
           )
     )
    )
  (let ((v1-135 (-> this mode)))
    (cond
      ((= v1-135 'movie)
       (task-node-reset arg0)
       (update-task-masks arg0)
       )
      ((= v1-135 'debug)
       (reset-actors arg0)
       (if arg1
           (load-game this arg1)
           )
       )
      ((= v1-135 'play)
       (when *target*
         (set-setting *setting-control* *target* 'allow-pause #f 0 0)
         (set-setting *setting-control* *target* 'allow-progress #f 0 0)
         (set-setting *setting-control* *target* 'allow-continue #f 0 0)
         (apply-settings *setting-control*)
         )
       (send-event (handle->process (-> *game-info* auto-save-proc)) 'die)
       (set! (-> *setting-control* user-default border-mode) #f)
       (set! (-> *setting-control* user-default region-mode) #f)
       (apply-settings *setting-control*)
       (set! *spawn-actors* #f)
       (set-blackout-frames (seconds 0.1))
       (send-event *target* 'reset)
       (let* ((s3-2 (get-process *4k-dead-pool* process #x4000))
              (v1-157 (when s3-2
                        (let ((t9-29 (method-of-type process activate)))
                          (t9-29 s3-2 *default-pool* (symbol->string (-> process symbol)) (the-as pointer #x70004000))
                          )
                        set-to-run
                        (let ((s1-2 (-> s3-2 main-thread))
                              (s0-1 (lambda :behavior process
                                      ((arg0 symbol) (arg1 symbol) (arg2 continue-point) (arg3 game-save))
                                      (set! (-> self mask) (process-mask))
                                      (stop arg0)
                                      (reset-actors arg1)
                                      (close! (-> *game-info* sub-task-list (game-task-node fortress-escape-start)) 'event)
                                      (set-continue! *game-info* arg2 #f)
                                      (when arg3
                                        (load-game *game-info* arg3)
                                        (set! arg2 (get-current-continue-forced *game-info*))
                                        (reset-actors 'life)
                                        (send-event (handle->process (-> *game-info* auto-save-proc)) 'done)
                                        )
                                      (suspend)
                                      (start arg0 arg2)
                                      (none)
                                      )
                                    )
                              )
                          (set! sv-112 (-> this mode))
                          (let ((t0-3 (get-current-continue-forced this))
                                (t1-3 arg1)
                                )
                            (run-next-time-in-process s3-2 s0-1 sv-112 arg0 t0-3 t1-3)
                            )
                          )
                        (-> s3-2 ppointer)
                        )
                      )
              )
         (when v1-157
           (set! (-> v1-157 0 mask) (process-mask))
           0
           )
         )
       (set-master-mode 'game)
       )
      )
    )
  (label cfg-131)
  this
  )

(defmethod give ((this game-info) (arg0 symbol) (arg1 float) (arg2 handle))
  (local-vars (ammo-max float))
  (with-pp
    (case arg0
      (('life)
       (if (>= arg1 0.0)
           (seek! (-> this life) (-> this life-max) arg1)
           (seek! (-> this life) 0.0 (- arg1))
           )
       (-> this life)
       )
      (('money)
       (if (< 0.0 arg1)
           (+! (-> this money-total) arg1)
           )
       (set! (-> this money) (+ (-> this money) arg1))
       )
      (('gem)
       (when (< 0.0 arg1)
         (+! (-> this gem-total) arg1)
         (let ((v1-7 (handle->process arg2)))
           (if (and v1-7 (-> v1-7 entity))
               (toggle-status (-> v1-7 entity) (entity-perm-status save) #t)
               )
           )
         )
       (set! (-> this gem) (+ (-> this gem) arg1))
       )
      (('skill)
       (if (< 0.0 arg1)
           (+! (-> this skill-total) arg1)
           )
       (set! (-> this skill) (+ (-> this skill) arg1))
       )
      (('karma)
       (set! (-> this karma) (+ (-> this karma) arg1))
       )
      (('eco-pill-dark)
       (cond
         ((< 0.0 arg1)
          (seek! (-> this eco-pill-dark) (-> *FACT-bank* eco-pill-dark-max-default) arg1)
          (if (and (demo?) (= (-> this eco-pill-dark) (-> *FACT-bank* eco-pill-dark-max-default)))
              (talker-spawn-func (-> *talker-speech* 79) *entity-pool* (target-pos 0) (the-as region #f))
              )
          (+! (-> this eco-pill-dark-total) arg1)
          )
         (else
           (seek! (-> this eco-pill-dark) 0.0 (- arg1))
           )
         )
       ;; og:preserve-this trigger effects
       (when (pc-get-trigger-effects-enabled?)
         (if (= (-> *FACT-bank* eco-pill-dark-max-default) (-> this eco-pill-dark))
            (pc-send-trigger-effect-feedback! (pc-trigger-effect-option left) 0 4)
            (pc-send-trigger-rumble! 16383 0 15)))
       (-> this eco-pill-dark)
       )
      (('fuel-cell)
       (let ((task (the int arg1)))
         (when (not (or (task-complete? this (the-as game-task task)) (>= (the-as uint 1) (the-as uint task))))
           (set! (-> this task-deaths) 0)
           (set! (-> this task-pickup-time) (-> *display* game-clock frame-counter))
           (set! (-> this unknown-array1 task) (-> *display* game-clock frame-counter))
           (+! (-> this fuel) 1.0)
           (logior! (-> this task-perm-list data task status) (entity-perm-status complete))
           (task-resolution-close! (the-as game-task task))
           )
         )
       (-> this fuel)
       )
      (('buzzer)
       (logand (the int arg1) #xffff)
       (sar (the int arg1) 16)
       0.0
       )
      (('ammo-yellow 'ammo-red 'ammo-blue 'ammo-dark)
       0.0
       (let* ((v1-41 arg0)
              (ammo-kind (cond
                           ((= v1-41 'ammo-yellow)
                            (set! ammo-max (-> *FACT-bank* ammo-yellow-max))
                            0
                            )
                           ((= v1-41 'ammo-red)
                            (set! ammo-max (-> *FACT-bank* ammo-red-max))
                            1
                            )
                           ((= v1-41 'ammo-blue)
                            (set! ammo-max (-> *FACT-bank* ammo-blue-max))
                            2
                            )
                           (else
                             (set! ammo-max (-> *FACT-bank* ammo-dark-max))
                             3
                             )
                           )
                         )
              )
         (if (logtest? (-> this features) (game-feature gun-upgrade-ammo))
             (set! ammo-max (* 2.0 ammo-max))
             )
         (if (>= arg1 0.0)
             (seek! (-> this gun-ammo ammo-kind) ammo-max arg1)
             (seek! (-> this gun-ammo ammo-kind) 0.0 (fabs arg1))
             )
         (set! (-> this gun-ammo ammo-kind) (fmin (-> this gun-ammo ammo-kind) ammo-max))
         (-> this gun-ammo ammo-kind)
         )
       )
      (('gun-yellow)
       (let ((a1-13 (new 'stack-no-clear 'event-message-block)))
         (set! (-> a1-13 from) (process->ppointer pp))
         (set! (-> a1-13 num-params) 0)
         (set! (-> a1-13 message) 'complete)
         (let ((t9-12 send-event-function)
               (v1-71 (-> *game-info* sub-task-list (game-task-node sewer-enemy-resolution)))
               )
           (t9-12
             (handle->process (if (-> v1-71 info)
                                  (-> v1-71 info manager)
                                  (the-as handle #f)
                                  )
                              )
             a1-13
             )
           )
         )
       (if (logtest? (logand (-> *setting-control* user-current features) (game-feature gun-yellow)) (-> this features))
           1.0
           0.0
           )
       )
      (('gun-dark)
       (let ((a1-14 (new 'stack-no-clear 'event-message-block)))
         (set! (-> a1-14 from) (process->ppointer pp))
         (set! (-> a1-14 num-params) 0)
         (set! (-> a1-14 message) 'complete)
         (let ((t9-13 send-event-function)
               (v1-85 (-> *game-info* sub-task-list (game-task-node sewer-escort-get-gun)))
               )
           (t9-13
             (handle->process (if (-> v1-85 info)
                                  (-> v1-85 info manager)
                                  (the-as handle #f)
                                  )
                              )
             a1-14
             )
           )
         )
       (if (logtest? (logand (-> *setting-control* user-current features) (game-feature gun-dark)) (-> this features))
           1.0
           0.0
           )
       )
      (('board)
       (cond
         ((< 0.0 arg1)
          (logior! (-> this features) (game-feature board))
          )
         ((< arg1 0.0)
          (logclear! (-> this features) (game-feature board))
          )
         )
       (if (logtest? (-> this features) (game-feature board))
           1.0
           0.0
           )
       )
      (('shield)
       (if (>= arg1 0.0)
           (seek! (-> this shield) (-> *FACT-bank* shield-max) arg1)
           (seek! (-> this shield) 0.0 (fabs arg1))
           )
       (-> this shield)
       )
      )
    )
  )

(defmethod game-info-method-22 ((this game-info))
  0
  )

;; WARN: Return type mismatch float vs none.
(defmethod reset! ((this fact-info-target) (arg0 symbol))
  (when (or (not arg0) (= arg0 'eco))
    (set! (-> this eco-timeout) 0)
    (set! (-> this eco-level) 0.0)
    (set! (-> this eco-pickup-time) (-> *display* game-clock frame-counter))
    )
  (when (or (not arg0) (= arg0 'health) (= arg0 'eco-green))
    (set! (-> this health-max) (-> *FACT-bank* health-max-default))
    (set! (-> this health) (-> this health-max))
    (set! (-> this health-pickup-time) (seconds -100))
    )
  (when (or (not arg0) (= arg0 'buzzer))
    (set! (-> this buzzer-max) (-> *FACT-bank* buzzer-max-default))
    (set! (-> this buzzer) 0.0)
    )
  (when (or (not arg0) (= arg0 'eco-pill-green))
    (set! (-> this eco-pill-green-max) (-> *FACT-bank* eco-pill-green-max-default))
    (set! (-> this eco-pill-green) 0.0)
    )
  (when (or (not arg0) (= arg0 'trick-judge))
    (set! (-> this trick-point-start-time) 0)
    (set! (-> this trick-point-duration) 0)
    0
    )
  (when (or (not arg0) (= arg0 'trick-point))
    (set! (-> this trick-point) 0.0)
    (set! (-> (the-as target (-> this process)) game score) 0.0)
    )
  (none)
  )

(defmethod pickup-collectable! ((this fact-info-target) (arg0 pickup-type) (arg1 float) (arg2 handle))
  (case arg0
    (((pickup-type health) (pickup-type eco-green))
     (cond
       ((>= arg1 0.0)
        (when (< 0.0 arg1)
          (if (or (!= (handle->process arg2) (handle->process (-> this eco-source)))
                  (>= (- (-> *display* game-clock frame-counter) (-> this eco-source-time)) (seconds 0.5))
                  )
              (sound-play "get-green-eco")
              )
          (send-event (-> this process) 'color-effect 'health (seconds 0.2))
          (when (handle->process arg2)
            (set! (-> this eco-source) arg2)
            (set! (-> this eco-source-time) (-> *display* game-clock frame-counter))
            )
          )
        (set! (-> this health-pickup-time) (-> *display* game-clock frame-counter))
        (seek! (-> this health) (-> this health-max) arg1)
        )
       (else
         (seek! (-> this health) 0.0 (- arg1))
         (if (>= arg1 -10.0)
             (pickup-collectable! this (pickup-type eco-pill-green) 0.0 arg2)
             )
         (if (= (-> this health) 0.0)
             (give (-> (the-as target (-> this process)) game) 'life (- (-> *GAME-bank* life-single-inc)) arg2)
             )
         )
       )
     (-> this health)
     )
    (((pickup-type eco-pill-green))
     (when (>= arg1 0.0)
       (set! (-> this eco-pill-green-pickup-time) (-> *display* game-clock frame-counter))
       (seek! (-> this eco-pill-green) (-> this eco-pill-green-max) arg1)
       (when (and (>= (-> this eco-pill-green) (-> *FACT-bank* eco-pill-green-max-default))
                  (< (-> this health) (-> this health-max))
                  )
         (set! (-> this eco-pill-green) (- (-> this eco-pill-green) (-> *FACT-bank* eco-pill-green-max-default)))
         (pickup-collectable!
           this
           (pickup-type health)
           (-> *FACT-bank* health-small-inc)
           (process->handle (-> this process))
           )
         )
       )
     (-> this eco-pill-green)
     )
    (((pickup-type eco-pill-dark))
     (when (< 0.0 arg1)
       (if (>= (- (-> *display* game-clock frame-counter) (-> this eco-pill-dark-pickup-time)) (seconds 0.05))
           (sound-play "get-dark-eco")
           )
       (send-event (-> this process) 'color-effect 'eco-pill-dark (seconds 0.2))
       (cond
         ((>= (- (-> *display* game-clock frame-counter) (-> (the-as target (-> this process)) shock-effect-time))
              (seconds 0.1)
              )
          (set! (-> (the-as target (-> this process)) shock-effect-time) (-> *display* game-clock frame-counter))
          (let ((s3-3 (rand-vu-int-range 0 2)))
            (dotimes (s2-2 s3-3)
              (process-drawable-shock-effect
                (the-as process-drawable (-> this process))
                *lightning-darkjak-pill*
                lightning-probe-callback
                (the-as sparticle-launcher #f)
                0
                0
                40960.0
                )
              )
            )
          )
         (else
           (send-event (handle->process arg2) 'effect #f)
           )
         )
       (set! (-> this eco-pill-dark-pickup-time) (-> *display* game-clock frame-counter))
       )
     (give (-> (the-as target (-> this process)) game) 'eco-pill-dark arg1 arg2)
     )
    (((pickup-type trick-judge))
     (when (< 0.0 arg1)
       (set! (-> this trick-point) 0.0)
       (set! (-> this trick-point-start-time) (-> *display* game-clock frame-counter))
       (set! (-> this trick-point-duration) (the-as time-frame (the int arg1)))
       )
     (the float (-> this trick-point-duration))
     )
    (((pickup-type trick-point))
     (when (nonzero? (-> this trick-point-duration))
       (set! (-> this trick-point-pickup-time) (-> *display* game-clock frame-counter))
       (set! (-> this trick-point) (fmax 0.0 (fmin (+ (-> this trick-point) arg1) (-> *FACT-bank* trick-point-max))))
       (when (!= arg1 0.0)
         (sound-play "get-trick-point")
         (process-spawn-function
           process
           (lambda :behavior target
             ((arg0 symbol) (arg1 symbol) (arg2 int))
             (let ((s3-0 (new 'stack-no-clear 'vector4w)))
               (set! (-> s3-0 quad) (the-as uint128 0))
               (when (transform-point-qword! s3-0 (the-as vector arg0))
                 ;; added for pc port, don't scale for high aspect
                 (let* ((scale (if (-> *pc-settings* use-vis?) (-> *video-params* relative-x-scale) 1.0))
                        (s5-0 (new
                                'stack
                                'font-context
                                *font-default-matrix*
                                (+ (the int (/ (the float (+ (/ (-> s3-0 x) 16) -1792)) scale)) -48)
                                (+ (/ (-> s3-0 y) 16) -1855)
                                0.0
                                (font-color orange)
                                (font-flags shadow kerning)
                                )
                              )
                       )
                   (set! (-> s5-0 scale) (lerp-scale 0.6 1.0 (the-as float arg1) 50.0 8000.0))
                   (let ((v1-9 s5-0))
                     (set! (-> v1-9 origin z) (the float (/ (-> s3-0 z) 16)))
                     )
                   (set! (-> s5-0 flags) (font-flags shadow kerning large))
                   (let ((s3-1 (current-time)))
                     (until (>= (- (current-time) s3-1) (+ arg2 -75))
                       (+! (-> s5-0 origin y) (* -120.0 (seconds-per-frame)))
                       (let ((s2-0 print-game-text))
                         (format (clear *temp-string*) "~4,,0f" arg1)
                         (s2-0 *temp-string* s5-0 #f 44 (bucket-id debug-no-zbuf1))
                         )
                       (suspend)
                       )
                     )
                   (let ((s4-1 (current-time)))
                     (until (>= (- (current-time) s4-1) (seconds 0.25))
                       (set! (-> s5-0 alpha) (lerp-scale 1.0 0.0 (the float (- (current-time) s4-1)) 0.0 150.0))
                       (+! (-> s5-0 origin y) (* -120.0 (seconds-per-frame)))
                       (let ((s3-2 print-game-text))
                         (format (clear *temp-string*) "~4,,0f" arg1)
                         (s3-2 *temp-string* s5-0 #f 44 (bucket-id debug-no-zbuf1))
                         )
                       (suspend)
                       )
                     )
                   )
                 )
               )
             (none)
             )
           (get-trans (the-as target (-> this process)) 3)
           arg1
           510
           :to (-> this process)
           )
         )
       )
     (-> this trick-point)
     )
    (((pickup-type money))
     (when (< 0.0 arg1)
       (if (>= (- (-> *display* game-clock frame-counter) (-> this money-pickup-time)) (seconds 0.05))
           (sound-play "money-pickup")
           )
       (set! (-> this money-pickup-time) (-> *display* game-clock frame-counter))
       )
     (give (-> (the-as target (-> this process)) game) 'money arg1 arg2)
     )
    (((pickup-type gem))
     (when (< 0.0 arg1)
       (if (>= (- (-> *display* game-clock frame-counter) (-> this gem-pickup-time)) (seconds 0.05))
           (sound-play "gem-pickup")
           )
       (set! (-> this gem-pickup-time) (-> *display* game-clock frame-counter))
       )
     (give (-> (the-as target (-> this process)) game) 'gem arg1 arg2)
     )
    (((pickup-type skill))
     (when (< 0.0 arg1)
       (if (>= (- (-> *display* game-clock frame-counter) (-> this skill-pickup-time)) (seconds 0.05))
           (sound-play "skill-pickup")
           )
       (set! (-> this skill-pickup-time) (-> *display* game-clock frame-counter))
       )
     (give (-> (the-as target (-> this process)) game) 'skill arg1 arg2)
     )
    (((pickup-type karma))
     (if (!= arg1 0.0)
         (set! (-> this karma-pickup-time) (-> *display* game-clock frame-counter))
         )
     (give (-> (the-as target (-> this process)) game) 'karma arg1 arg2)
     )
    (((pickup-type fuel-cell))
     (let ((s3-9 (the int arg1)))
       (if (not (or (task-complete? (-> (the-as target (-> this process)) game) (the-as game-task s3-9))
                    (>= (the-as uint 1) (the-as uint s3-9))
                    )
                )
           (set! (-> this task-pickup-time) (-> *display* game-clock frame-counter))
           )
       )
     (give (-> (the-as target (-> this process)) game) 'fuel-cell arg1 arg2)
     )
    (((pickup-type buzzer))
     (let ((f0-41 (give (-> (the-as target (-> this process)) game) 'buzzer arg1 arg2)))
       (if (!= f0-41 (-> this buzzer))
           (set! (-> this buzzer-pickup-time) (-> *display* game-clock frame-counter))
           )
       (set! (-> this buzzer) f0-41)
       )
     (-> this buzzer)
     )
    (((pickup-type ammo-yellow) (pickup-type ammo-red) (pickup-type ammo-blue) (pickup-type ammo-dark))
     (if (< 0.0 arg1)
         (set! (-> this ammo-pickup-time) (-> *display* game-clock frame-counter))
         )
     (let ((ammo-kind (cond
                        ((= arg0 (pickup-type ammo-yellow))
                         'ammo-yellow
                         )
                        ((= arg0 (pickup-type ammo-red))
                         'ammo-red
                         )
                        ((= arg0 (pickup-type ammo-blue))
                         'ammo-blue
                         )
                        (else
                          'ammo-dark
                          )
                        )
                      )
           )
       (if (< 0.0 arg1)
           (send-event (-> this process) 'color-effect ammo-kind (seconds 0.2))
           )
       (give (-> (the-as target (-> this process)) game) ammo-kind arg1 arg2)
       )
     )
    (((pickup-type gun-yellow)
      (pickup-type gun-red)
      (pickup-type gun-blue)
      (pickup-type gun-dark)
      (pickup-type board)
      )
     (let ((v1-192 arg0))
       (give
         (-> (the-as target (-> this process)) game)
         (cond
           ((= v1-192 (pickup-type gun-yellow))
            'gun-yellow
            )
           ((= v1-192 (pickup-type gun-red))
            'gun-red
            )
           ((= v1-192 (pickup-type gun-blue))
            'gun-blue
            )
           ((= v1-192 (pickup-type gun-dark))
            'gun-dark
            )
           (else
             'board
             )
           )
         arg1
         arg2
         )
       )
     )
    (((pickup-type shield))
     (if (< 0.0 arg1)
         (set! (-> this shield-pickup-time) (-> *display* game-clock frame-counter))
         )
     (give (-> (the-as target (-> this process)) game) 'shield arg1 arg2)
     )
    (((pickup-type eco-red) (pickup-type eco-blue) (pickup-type eco-yellow))
     (if (= arg1 0.0)
         (return (if (= (-> this eco-type) arg0)
                     (-> this eco-level)
                     0.0
                     )
                 )
         )
     (when (!= (-> this eco-type) arg0)
       (set! (-> this eco-level) 0.0)
       (set! (-> this eco-timeout) 0)
       0
       )
     (set! (-> this eco-type) (the-as int arg0))
     (let ((f0-49 (-> this eco-level)))
       (set! (-> this eco-level) 1.0)
       (when (and (= f0-49 0.0) (< 0.0 (-> this eco-level)))
         (set! (-> this eco-pickup-time) (-> *display* game-clock frame-counter))
         (send-event (-> this process) 'reset-collide)
         )
       )
     (set! (-> this eco-timeout)
           (the-as
             time-frame
             (min
               (+ (-> this eco-timeout) (* (the-as int (-> *FACT-bank* eco-single-timeout)) (the int arg1)))
               (the-as
                 time-frame
                 (+ (-> *FACT-bank* eco-full-timeout) (- (-> *display* game-clock frame-counter) (-> this eco-pickup-time)))
                 )
               )
             )
           )
     (if (>= (- (-> this eco-timeout) (- (-> *display* game-clock frame-counter) (-> this eco-pickup-time)))
             (the-as time-frame (-> *FACT-bank* eco-full-timeout))
             )
         (set! (-> this eco-level) 2.0)
         )
     (when (not (and (= (handle->process arg2) (handle->process (-> this eco-source)))
                     (< (- (-> *display* game-clock frame-counter) (-> this eco-source-time)) (seconds 0.5))
                     )
                )
       (cpad-set-buzz! (-> *cpad-list* cpads 0) 1 127 (seconds 0.2))
       (cpad-set-buzz! (-> *cpad-list* cpads 0) 0 17 (seconds 0.2))
       (case arg0
         (((pickup-type eco-blue))
          (sound-play "get-blue-eco")
          )
         (((pickup-type eco-green) (pickup-type health))
          (sound-play "get-green-eco")
          )
         (((pickup-type eco-yellow))
          (sound-play "get-yellow-eco")
          )
         (((pickup-type eco-red))
          (sound-play "get-red-eco")
          )
         )
       )
     (set! (-> this eco-source) arg2)
     (set! (-> this eco-source-time) (-> *display* game-clock frame-counter))
     (-> this eco-level)
     )
    (else
      ((method-of-type fact-info pickup-collectable!) this arg0 arg1 arg2)
      )
    )
  )

(defmethod actor-perm ((this game-info) (arg0 actor-id))
  (let ((game-perms (-> this perm-list)))
    (countdown (i (-> game-perms length))
      (if (= arg0 (-> game-perms data i aid))
          (return (-> game-perms data i))
          )
      )
    )
  (the-as entity-perm #f)
  )

(defmethod copy-perms-from-level! ((this game-info) (arg0 level))
  (let ((game-perms (-> this perm-list))
        (level-entities (-> arg0 bsp level entity))
        )
    (dotimes (i (-> level-entities length))
      (let ((entity-perm (-> level-entities data i entity extra perm)))
        (when (or (nonzero? (-> entity-perm task)) (logtest? (-> entity-perm status) (entity-perm-status save)))
          (let ((actor-perm (actor-perm this (-> entity-perm aid))))
            (cond
              (actor-perm
                (set! (-> actor-perm quad) (-> entity-perm quad))
                )
              ((< (-> game-perms length) (-> game-perms allocated-length))
               (set! (-> game-perms data (-> game-perms length) quad) (-> entity-perm quad))
               (+! (-> game-perms length) 1)
               )
              )
            )
          )
        )
      )
    )
  0
  )

(defmethod copy-perms-to-level! ((this game-info) (arg0 level))
  (let ((level-entities (-> arg0 bsp level entity)))
    (dotimes (i (-> level-entities length))
      (let* ((entity-perm (-> level-entities data i entity extra perm))
             (actor-perm (actor-perm this (-> entity-perm aid)))
             )
        (when actor-perm
          (set! (-> entity-perm quad) (-> actor-perm quad))
          (update entity-perm 'try (entity-perm-status bit-0 error dead no-kill bit-5 subtask-complete bit-9 bit-12))
          )
        )
      )
    )
  0
  )

(defmethod print ((this continue-point))
  (format #t "#<~A ~S @ #x~X>" (-> this type) (-> this name) this)
  this
  )

(defmethod debug-draw ((this continue-point))
  (add-debug-x #t (bucket-id debug-no-zbuf1) (-> this trans) (new 'static 'rgba :r #xff :a #x80))
  (add-debug-text-3d
    #t
    (bucket-id debug-no-zbuf1)
    (-> this name)
    (-> this trans)
    (font-color white)
    (new 'static 'vector2h :data (new 'static 'array int16 2 0 8))
    )
  (let ((a3-2 (vector-z-quaternion! (new-stack-vector0) (the-as quaternion (-> this quat)))))
    (add-debug-vector
      #t
      (bucket-id debug-no-zbuf1)
      (-> this trans)
      a3-2
      (meters 2)
      (new 'static 'rgba :r #xff :g #x80 :a #x80)
      )
    )
  0
  )

(defun-debug trsq->continue-point ((arg0 trsq))
  (let ((v1-1 (level-get-target-inside *level*)))
    (format #t "~%(static-continue-point ~A ()~%" (symbol->string (-> v1-1 name)))
    )
  (format #t "                       (target ~m ~m ~m " (-> arg0 trans x) (-> arg0 trans y) (-> arg0 trans z))
  (format #t "~f ~f ~f ~f)~%" (-> arg0 quat x) (-> arg0 quat y) (-> arg0 quat z) (-> arg0 quat w))
  (let ((gp-1 *math-camera*))
    (format
      #t
      "                       (camera ~m ~m ~m ~f ~f ~f "
      (-> gp-1 trans x)
      (-> gp-1 trans y)
      (-> gp-1 trans z)
      (-> gp-1 inv-camera-rot vector 0 x)
      (-> gp-1 inv-camera-rot vector 0 y)
      (-> gp-1 inv-camera-rot vector 0 z)
      )
    (format
      #t
      "~f ~f ~f ~f ~f ~f)~%"
      (-> gp-1 inv-camera-rot vector 1 x)
      (-> gp-1 inv-camera-rot vector 1 y)
      (-> gp-1 inv-camera-rot vector 1 z)
      (-> gp-1 inv-camera-rot vector 2 x)
      (-> gp-1 inv-camera-rot vector 2 y)
      (-> gp-1 inv-camera-rot vector 2 z)
      )
    )
  (let ((gp-2 format)
        (s5-0 #t)
        (s4-0 "                       (load '~A ")
        (v1-7 (lookup-level-info (-> *load-state* vis-nick)))
        )
    (gp-2 s5-0 s4-0 (if v1-7
                        (-> v1-7 name)
                        )
          )
    )
  (dotimes (gp-3 4)
    (let ((v1-10 (lookup-level-info (-> *load-state* want gp-3 name))))
      (if (and v1-10 (!= (-> v1-10 memory-mode) 4))
          (format #t "'~A '~A " (-> *load-state* want gp-3 name) (-> *load-state* want gp-3 display?))
          (format #t "#f #f ")
          )
      )
    )
  (format #t ")~%                       (sound ")
  (dotimes (gp-4 3)
    (format #t "~A " (-> *load-state* want-sound gp-4))
    )
  (format #t ")~%)~%")
  0
  )

(defun position->stream ((arg0 string) (arg1 symbol) (arg2 symbol))
  (format
    arg0
    "bug-report ~S ~S ~DK "
    *user*
    arg1
    (shr (* (dma-buffer-length (-> *display* frames (-> *display* last-screen) global-buf)) 16) 10)
    )
  (if arg2
      (format arg0 "~%")
      )
  (let* ((s4-1 format)
         (s3-1 arg0)
         (s2-1 "nick ~S continue ~S ")
         (v1-9 (lookup-level-info (-> *load-state* vis-nick)))
         (a2-2 (if v1-9
                   (-> v1-9 name)
                   )
               )
         (v1-11 (-> *game-info* current-continue))
         )
    (s4-1 s3-1 s2-1 a2-2 (if v1-11
                             (-> v1-11 name)
                             )
          )
    )
  (if arg2
      (format arg0 "~%")
      )
  ;; og:preserve-this level constant
  (dotimes (s4-2 LEVEL_MAX)
    (if (or (= (-> *level* level s4-2 status) 'active)
            (= (-> *level* level s4-2 status) 'alive)
            (= (-> *level* level s4-2 status) 'loaded)
            )
        (format arg0 "level ~D ~-8A ~-8A " s4-2 (-> *level* level s4-2 name) (-> *level* level s4-2 display?))
        (format arg0 "level ~D ~-8A ~-8A " s4-2 #f #f)
        )
    (if arg2
        (format arg0 "~%")
        )
    )
  (format arg0 "music ~-8S sound " (-> *setting-control* user-current music))
  (dotimes (s4-3 3)
    (format arg0 "~-8S " (-> *level* sound-bank s4-3))
    )
  (if arg2
      (format arg0 "~%")
      )
  (let ((v1-41 (target-pos 0)))
    (format arg0 "target ~m ~m ~m " (-> v1-41 x) (-> v1-41 y) (-> v1-41 z))
    )
  (if arg2
      (format arg0 "~%")
      )
  (let ((v1-45 (math-camera-pos)))
    (format arg0 "camera-trans ~m ~m ~m " (-> v1-45 x) (-> v1-45 y) (-> v1-45 z))
    )
  (if arg2
      (format arg0 "~%")
      )
  (let* ((a1-15 (math-camera-matrix))
         (v1-49 (matrix->quaternion (new 'stack-no-clear 'quaternion) a1-15))
         )
    (format arg0 "camera-rot ~f ~f ~f ~f" (-> v1-49 x) (-> v1-49 y) (-> v1-49 z) (-> v1-49 w))
    )
  (format arg0 "~%")
  0
  (none)
  )

(defun bug-report-display ((arg0 symbol))
  (case *bug-report-output-mode*
    (('*stdcon*)
     (let ((conts
             "                                                                                                                                                                                                                                                                "
             )
           )
       (clear conts)
       (position->stream conts arg0 #t)
       (process-spawn-function
         process
         (lambda :behavior process
           ((arg0 string))
           (let ((s5-0 (current-time)))
             (until (>= (- (current-time) s5-0) (seconds 10))
               (format *stdcon* "~S~%" arg0)
               (suspend)
               )
             )
           (none)
           )
         conts
         )
       )
     )
    (('file-stream)
     (format (clear *temp-string*) "db/bug-report/bug-report-~S.txt" *user*)
     *temp-string*
     (let ((s5-2 (new 'stack 'file-stream *temp-string* 'append)))
       (file-stream-seek s5-2 0 2)
       (position->stream (the-as string s5-2) arg0 #f)
       (file-stream-close s5-2)
       )
     )
    (else
      (position->stream (the-as string #t) arg0 #f)
      )
    )
  0
  )

(defun-debug print-continues ()
  (let ((levels *level-load-list*))
    (while (not (null? levels))
      (let ((conts (-> (the-as level-load-info (-> (the-as symbol (car levels)) value)) continues)))
        (while (not (null? conts))
          (let ((cont (the-as continue-point (car conts))))
            (if (not (logtest? (-> cont flags) (continue-flags change-continue)))
                (format #t "~S~%" (-> cont name))
                )
            )
          (set! conts (cdr conts))
          )
        )
      (set! levels (cdr levels))
      )
    )
  0
  )

(defmethod print ((this game-task-info))
  (format #t "#<game-task-info ~S @ #x~X>" (-> this name) this)
  this
  )

(defmethod debug-inspect ((this game-info) (arg0 symbol))
  (local-vars
    (sv-16 int)
    (sv-24 int)
    (sv-32 int)
    (sv-40 int)
    (sv-48 int)
    (sv-56 int)
    (sv-64 string)
    (sv-80 string)
    (sv-96 string)
    (sv-112 string)
    )
  (inspect this)
  (when (or (not arg0) (= arg0 'game-task))
    (format #t "~Tgame-task:~%")
    (format #t "~T~T~-32S     intro      play  death gem skill~%" "task")
    (format #t "~T~T--------------------~%")
    (let ((s4-0 2)
          (s3-0 109)
          )
      (while (>= (the-as uint s3-0) (the-as uint s4-0))
        (when (task-complete? this (the-as game-task s4-0))
          (set! sv-16 0)
          (set! sv-24 0)
          (set! sv-32 0)
          (set! sv-40 0)
          (set! sv-48 0)
          (set! sv-56 0)
          (let ((game-subtasks (-> *game-info* sub-task-list)))
            (dotimes (i (-> game-subtasks length))
              (when (nonzero? i)
                (let ((subtasks (-> game-subtasks i)))
                  (when (= (-> subtasks task) s4-0)
                    (when (zero? sv-24)
                      (set! sv-24 (the-as int (-> subtasks close-time)))
                      (set! sv-16 (the-as int (-> subtasks close-time)))
                      )
                    (when (logtest? (-> subtasks flags) (game-task-node-flag closed))
                      (set! sv-32 (the-as int (-> subtasks close-time)))
                      (set! sv-40 (the-as int (-> subtasks gem-count)))
                      (set! sv-48 (the-as int (-> subtasks skill-count)))
                      )
                    (set! sv-56 (+ sv-56 (-> subtasks death-count)))
                    (if (logtest? (-> subtasks flags) (game-task-node-flag close-task))
                        (goto cfg-19)
                        )
                    )
                  )
                )
              )
            )
          (label cfg-19)
          (if (nonzero? (-> this task-close-times s4-0))
              (set! sv-24 (max sv-24 (-> this task-close-times s4-0)))
              )
          (format
            #t
            "~T~T~-32S ~6,,1f min ~6,,1f min ~3d ~3d ~3d~%"
            (game-task->string (the-as game-task s4-0))
            (* 0.000055555556 (the float (- sv-24 sv-16)))
            (* 0.000055555556 (the float (- sv-32 sv-24)))
            sv-56
            sv-40
            sv-48
            )
          )
        (+! s4-0 1)
        )
      )
    )
  (when (= arg0 'game-task-node)
    (let ((s4-1 (-> *game-info* sub-task-list)))
      (dotimes (s3-1 (-> s4-1 length))
        (when (nonzero? s3-1)
          (let ((s2-1 (-> s4-1 s3-1))
                (s1-1 format)
                (s0-1 #t)
                )
            (set! sv-64 "~-55S ~-16S ~S    ~A~%")
            (set! sv-80 (-> s2-1 name))
            (cond
              ((logtest? (-> s2-1 flags) (game-task-node-flag closed))
               (set! sv-96 "closed")
               )
              ((open? s2-1)
               (set! sv-96 "open")
               )
              (else
                (set! sv-96 "inactive")
                )
              )
            (if (task-complete? *game-info* (-> s2-1 task))
                (set! sv-112 "res")
                (set! sv-112 "   ")
                )
            (let ((t1-1 (lookup-text! *common-text* (-> s2-1 description) #f)))
              (s1-1 s0-1 sv-64 sv-80 sv-96 sv-112 t1-1)
              )
            )
          )
        )
      )
    )
  (when (or (not arg0) (= arg0 'level))
    (format #t "~Tlevel:~%")
    (format #t "~T~T~-32S death in-time   enter-time~%" "level")
    (format #t "~T~T--------------------~%")
    (dotimes (s4-2 (-> *task-level* length))
      (format
        #t
        "~T~T~-32S ~3d  ~6,,1f min  ~6,,1f min~%"
        (-> *task-level* s4-2)
        (-> this deaths-per-level s4-2)
        (* 0.000055555556 (the float (-> this task-in-times s4-2)))
        (* 0.000055555556 (the float (-> this task-enter-times s4-2)))
        )
      )
    )
  (when (or (not arg0) (= arg0 'score))
    (format #t "~Tscore:~%")
    (format #t "~T~T--------------------~%")
    (dotimes (s4-3 19)
      (let ((v1-71 (get-game-score-ref this s4-3))
            (t9-18 format)
            (a0-26 #t)
            (a1-24 "~T~T~-32S ~8,,0f ~8,,0f ~8,,0f~%")
            (a2-22 s4-3)
            )
        (t9-18
          a0-26
          a1-24
          (cond
            ((= a2-22 16)
             "reverse-race-1"
             )
            ((= a2-22 7)
             "gungame-dark"
             )
            ((= a2-22 14)
             "bush-port"
             )
            ((= a2-22 12)
             "bush-race-2"
             )
            ((= a2-22 9)
             "whack"
             )
            ((= a2-22 1)
             "race-1"
             )
            ((= a2-22 11)
             "bush-race-1"
             )
            ((= a2-22 4)
             "gungame-red"
             )
            ((= a2-22 6)
             "gungame-blue"
             )
            ((= a2-22 5)
             "gungame-yellow"
             )
            ((= a2-22 15)
             "bush-errol"
             )
            ((= a2-22 2)
             "race-2"
             )
            ((zero? a2-22)
             "none"
             )
            ((= a2-22 10)
             "judge-skatea"
             )
            ((= a2-22 17)
             "reverse-race-2"
             )
            ((= a2-22 18)
             "reverse-race-3"
             )
            ((= a2-22 13)
             "bush-race-3"
             )
            ((= a2-22 8)
             "onin-game"
             )
            ((= a2-22 3)
             "race-3"
             )
            (else
              "*unknown*"
              )
            )
          (-> v1-71 0)
          (-> v1-71 1)
          (-> v1-71 2)
          )
        )
      )
    )
  (when (= arg0 'entity-perm)
    (format #t "~Tentity-perm:~%")
    (let ((game-perms (-> this perm-list)))
      (dotimes (s4-4 (-> game-perms length))
        (format #t "~T~T~`entity-perm`P~%" (-> game-perms data s4-4))
        )
      )
    )
  this
  )

(defmethod you-suck-stage ((this game-info) (arg0 symbol))
  (cond
    ((logtest? (-> *game-info* secrets) (game-secrets hero-mode))
     0
     )
    (else
      (let ((game-subtasks (-> *game-info* sub-task-list)))
        (dotimes (i (-> game-subtasks length))
          (when (nonzero? i)
            (let ((subtask (-> game-subtasks i)))
              (when (open? subtask)
                (let ((cur-lev (level-get-target-inside *level*)))
                  (when (and cur-lev (= (-> cur-lev info taskname) (-> subtask level)))
                    (let* ((suck-death-count (if (zero? (-> subtask suck-death-count))
                                                 5
                                                 (the-as int (-> subtask suck-death-count))
                                                 )
                                             )
                           (suck-death-stage (/ (the float (-> subtask death-count)) (the float suck-death-count)))
                           )
                      (return (min 4 (the int suck-death-stage)))
                      )
                    )
                  )
                )
              )
            )
          )
        )
      0
      )
    )
  )

(defmethod you-suck-scale ((this game-info) (arg0 object))
  (* 0.25 (the float (you-suck-stage this #f)))
  )

(defmethod adjust-to-screen-flip ((this cpad-info))
  ;; og:preserve-this mirror mode flag
  (when (or (logtest? (-> *game-info* secrets) (game-secrets hflip-screen))
            *PC-MIRROR-MODE-SET*)
    (set! (-> this leftx) (- 255 (the-as int (-> this leftx))))
    (set! (-> this rightx) (- 255 (the-as int (-> this rightx))))
    ;; while in the progress menu, invert left/right as well
    (when *progress-process*
      ;; right = 5th bit and 1st index for pressure
      ;; left = 7th bit and 2nd index for pressure
      (let ((right-pressed? (logtest? (-> this button0) (pad-buttons right)))
            (right-pressure (-> this abutton (abutton-idx right))) ;; og:preserve-this abutton indexing
            (left-pressed? (logtest? (-> this button0) (pad-buttons left)))
            (left-pressure (-> this abutton (abutton-idx left)))) ;; og:preserve-this abutton indexing
        (when right-pressed?
          (logclear! (-> this button0) (pad-buttons right))
          (logior! (-> this button0) (pad-buttons left)))
        (when left-pressed?
          (logclear! (-> this button0) (pad-buttons left))
          (logior! (-> this button0) (pad-buttons right)))
        (set! (-> this abutton (abutton-idx right)) left-pressure) ;; og:preserve-this abutton indexing
        (set! (-> this abutton (abutton-idx left)) right-pressure)))) ;; og:preserve-this abutton indexing
  0)

(defmethod game-info-method-28 ((this game-info) (arg0 game-score) (arg1 float))
  (when (!= arg1 0.0)
    (let ((v1-3 (&+ (-> this game-score data) (* (* arg0 8) 4))))
      (case arg0
        (((game-score race-1)
          (game-score race-2)
          (game-score race-3)
          (game-score bush-race-1)
          (game-score bush-race-2)
          (game-score bush-race-3)
          (game-score bush-port)
          (game-score bush-errol)
          (game-score reverse-race-1)
          (game-score reverse-race-2)
          (game-score reverse-race-3)
          )
         (dotimes (a0-5 8)
           (when (or (= (-> (&+ v1-3 (* a0-5 4)) 0) 0.0) (< arg1 (-> (&+ v1-3 (* a0-5 4)) 0)))
             (let ((a1-19 7))
               (while (< a0-5 a1-19)
                 (set! (-> (&+ v1-3 (* a1-19 4)) 0) (-> (&+ v1-3 (* (+ a1-19 -1) 4)) 0))
                 (+! a1-19 -1)
                 )
               )
             (set! (-> (&+ v1-3 (* a0-5 4)) 0) arg1)
             (return a0-5)
             )
           )
         )
        (else
          (dotimes (a0-6 8)
            (when (< (-> (&+ v1-3 (* a0-6 4)) 0) arg1)
              (let ((a1-26 7))
                (while (< a0-6 a1-26)
                  (set! (-> (&+ v1-3 (* a1-26 4)) 0) (-> (&+ v1-3 (* (+ a1-26 -1) 4)) 0))
                  (+! a1-26 -1)
                  )
                )
              (set! (-> (&+ v1-3 (* a0-6 4)) 0) arg1)
              (return a0-6)
              )
            )
          )
        )
      )
    )
  -1
  )

(defmethod get-game-score-ref ((this game-info) (arg0 int))
  (&+ (-> this game-score data) (* (* arg0 8) 4))
  )

(defmethod get-rank ((this highscore-info) (score float))
  (let ((place 0))
    (cond
      ((logtest? (-> this flags) (highscore-flags time))
       (cond
         ((= score 0.0)
          )
         ((>= (-> this gold-score) score)
          (set! place 3)
          )
         ((>= (-> this silver-score) score)
          (set! place 2)
          )
         ((>= (-> this bronze-score) score)
          (set! place 1)
          )
         )
       )
      (else
        (cond
          ((>= score (-> this gold-score))
           (set! place 3)
           )
          ((>= score (-> this silver-score))
           (set! place 2)
           )
          ((>= score (-> this bronze-score))
           (set! place 1)
           )
          )
        )
      )
    place
    )
  )

(kmemopen global "game-info")

(let ((gp-0 *game-info*))
  (set! (-> gp-0 task-counter) (the-as uint 1))
  (when (zero? (-> gp-0 perm-list))
    (set! (-> gp-0 perm-list) (new 'global 'entity-perm-array 4096))
    (set! (-> gp-0 perm-list length) 0)
    0
    )
  (if (zero? (-> gp-0 unknown-pad6))
      (set! (-> gp-0 unknown-pad6) (new 'global 'boxed-array uint16 1860))
      )
  (when (zero? (-> gp-0 death-pos))
    (set! (-> gp-0 death-pos) (new 'global 'vector-array 64))
    (set! (-> gp-0 death-pos length) 0)
    0
    )
  (if (zero? (-> gp-0 display-text-handle))
      (set! (-> gp-0 display-text-handle) (the-as handle #f))
      )
  (if (zero? (-> gp-0 game-score))
      (set! (-> gp-0 game-score) (new 'global 'boxed-array float 152))
      )
  (if (not (-> gp-0 current-continue))
      (set-continue! gp-0 *default-continue* #f)
      )
  (if (not (-> gp-0 last-continue))
      (set! (-> gp-0 last-continue) *default-continue*)
      )
  (set! (-> gp-0 want-auto-save) #f)
  (set! (-> gp-0 auto-save-proc) (the-as handle #f))
  (set! (-> gp-0 auto-save-status) (mc-status-code ok))
  (set! (-> gp-0 auto-save-card) 0)
  (set! (-> gp-0 auto-save-which) -1)
  (set! (-> gp-0 pov-camera-handle) (the-as handle #f))
  (set! (-> gp-0 other-camera-handle) (the-as handle #f))
  (set! (-> gp-0 features) (game-feature gun gun-yellow gun-red gun-blue gun-dark board sidekick darkjak))
  (dotimes (v1-43 2)
    (set! (-> gp-0 controller v1-43) (the-as handle #f))
    )
  (set! (-> gp-0 gun-ammo 0) (-> *FACT-bank* ammo-yellow-start))
  (set! (-> gp-0 gun-ammo 1) (-> *FACT-bank* ammo-red-start))
  (set! (-> gp-0 gun-ammo 2) (-> *FACT-bank* ammo-blue-start))
  (set! (-> gp-0 gun-ammo 3) (-> *FACT-bank* ammo-dark-start))
  (set! (-> gp-0 shield) 100.0)
  (set! (-> gp-0 score) 0.0)
  (set! (-> gp-0 score-owner) (the-as handle #f))
  (set! (-> gp-0 timer) 0)
  (set! (-> gp-0 timer-flash) #f)
  (set! (-> gp-0 timer-owner) (the-as handle #f))
  (set! (-> gp-0 counter) 0.0)
  (set! (-> gp-0 counter-flash) #f)
  (set! (-> gp-0 wanted-flash) #f)
  (set! (-> gp-0 distance) 0.0)
  )

0

(kmemclose)

(define *highscore-info-array*
  (new 'static 'boxed-array :type highscore-info
    (new 'static 'highscore-info)
    (new 'static 'highscore-info)
    (new 'static 'highscore-info)
    (new 'static 'highscore-info)
    (new 'static 'highscore-info :award-scores (new 'static 'array float 3 8000.0 10000.0 12000.0))
    (new 'static 'highscore-info :award-scores (new 'static 'array float 3 9000.0 11000.0 13000.0))
    (new 'static 'highscore-info :award-scores (new 'static 'array float 3 11000.0 13000.0 15000.0))
    (new 'static 'highscore-info :award-scores (new 'static 'array float 3 11000.0 13000.0 15000.0))
    (new 'static 'highscore-info
      :award-scores (new 'static 'array float 3 1000000000.0 1000000000.0 1000000000.0)
      )
    (new 'static 'highscore-info
      :award-scores (new 'static 'array float 3 1000000000.0 1000000000.0 1000000000.0)
      )
    (new 'static 'highscore-info :award-scores (new 'static 'array float 3 50000.0 90000.0 120000.0))
    (new 'static 'highscore-info
      :flags (highscore-flags time)
      :award-scores (new 'static 'array float 3 142.0 138.0 133.0)
      )
    (new 'static 'highscore-info
      :flags (highscore-flags time)
      :award-scores (new 'static 'array float 3 140.0 135.0 130.0)
      )
    (new 'static 'highscore-info
      :flags (highscore-flags time)
      :award-scores (new 'static 'array float 3 149.0 144.0 139.0)
      )
    (new 'static 'highscore-info
      :flags (highscore-flags time)
      :award-scores (new 'static 'array float 3 142.0 137.0 132.0)
      )
    (new 'static 'highscore-info
      :flags (highscore-flags time)
      :award-scores (new 'static 'array float 3 137.0 132.0 127.0)
      )
    (new 'static 'highscore-info
      :flags (highscore-flags time)
      :award-scores (new 'static 'array float 3 150.0 145.0 140.0)
      )
    (new 'static 'highscore-info
      :flags (highscore-flags time)
      :award-scores (new 'static 'array float 3 155.0 150.0 145.0)
      )
    (new 'static 'highscore-info
      :flags (highscore-flags time)
      :award-scores (new 'static 'array float 3 178.0 173.0 168.0)
      )
    )
  )
