Files
jak-project/goal_src/jak3/pc/progress/progress-pc.gc
T
water111 228dfd82d1 [jak3] Small bug fixes (#3933)
Fixes the pillars being transparent (but is a bit of a hack), the desert
sand not having texture filtering, and the "No memory card" on the title
screen with debug mode off.

---------

Co-authored-by: water111 <awaterford1111445@gmail.com>
2025-06-01 13:24:28 -04:00

1527 lines
60 KiB
Common Lisp

;;-*-Lisp-*-
(in-package goal)
#|
Additional PC port specific file for overriding/expanding the progress menu
This gives us more freedom to write code how we want.
|#
(deftype progress-global-state-pc (basic)
((decoration-draw-time time-frame)
(aspect-ratio-ratio-index int8)
(frame-rate-choice-index int8)
(frame-rate-disclaimer-time time-frame)
(music-player-track music-player-track-info)
(music-player-flava int8)
(music-player-selected symbol)
)
)
(define *progress-state-pc* (new 'static 'progress-global-state-pc :music-player-track #f))
(defmacro when-not-drawn-decoration (&rest body)
`(when (> (-> *display* real-clock integral-frame-counter) (-> *progress-state-pc* decoration-draw-time))
,@body
(set! (-> *progress-state-pc* decoration-draw-time) (-> *display* real-clock integral-frame-counter))))
(defun mc-status-code->string ((status mc-status-code))
(enum->string mc-status-code status))
(defmethod progress-method-33 ((this progress) (arg0 progress-box))
(set! (-> this scissor-count) (min 7 (+ (-> this scissor-count) 1)))
(let ((s5-0 (-> this scissor-stack (-> this scissor-count)))
(box (new 'stack 'hud-box))
(gp-1 (if (= (get-aspect-ratio) 'aspect4x3)
(-> arg0 aspect4x3)
(-> arg0 aspect16x9)
)
)
)
(vector-copy! s5-0 (the-as vector gp-1))
(mem-copy! (the pointer box) (the pointer gp-1) (size-of hud-box))
(set! gp-1 box)
(#when PC_PORT
(when (not (-> *pc-settings* use-vis?))
(set! (-> gp-1 min x) (the float (adjust-game-x (-> gp-1 min x))))
(set! (-> gp-1 max x) (the float (adjust-game-x (-> gp-1 max x))))
)
)
(with-dma-buffer-add-bucket ((v1-12 (-> *display* frames (-> *display* on-screen) global-buf))
(bucket-id hud-draw-hud-alpha)
)
(dma-buffer-add-gs-set v1-12
(scissor-1
(new 'static 'gs-scissor
:scax0 (the int (-> gp-1 box min x))
:scay0 (the int (-> gp-1 box min y))
:scax1 (the int (-> gp-1 box max x))
:scay1 (the int (-> gp-1 box max y))
)
)
)
)
(with-dma-buffer-add-bucket ((v1-23 (-> *display* frames (-> *display* on-screen) global-buf))
(bucket-id particles)
)
(dma-buffer-add-gs-set v1-23
(scissor-1
(new 'static 'gs-scissor
:scax0 (the int (-> gp-1 box min x))
:scay0 (the int (-> gp-1 box min y))
:scax1 (the int (-> gp-1 box max x))
:scay1 (the int (-> gp-1 box max y))
)
)
)
)
(with-dma-buffer-add-bucket ((v1-34 (-> *display* frames (-> *display* on-screen) global-buf))
(bucket-id hud-draw-pris2)
)
(dma-buffer-add-gs-set v1-34 (scissor-1 (new 'static 'gs-scissor
:scax0 (the int (-> gp-1 box min x))
:scay0 (the int (-> gp-1 box min y))
:scax1 (the int (-> gp-1 box max x))
:scay1 (the int (-> gp-1 box max y))
)
)
)
)
)
0
)
(defbehavior progress-trans progress ()
;; og:preserve-this added variable
(let ((speed-mod (if (-> *pc-settings* fast-progress?) (-> *pc-cheat-state* progress-speed) 1.0)))
(cond
((and (= (-> self next) 'none) (or (= (-> self starting-state) 'main) (= (-> self anim-frame) 1.0)))
(set! (-> self menu-transition)
(seek-ease
(-> self menu-transition)
0.0
(/ (* speed-mod (-> self clock time-adjust-ratio)) 10)
0.4
(/ (-> self clock time-adjust-ratio) 100)
)
)
)
(else
(seek! (-> self menu-transition) 1.0 (/ (-> self clock time-adjust-ratio) 10))
(when (and (= (-> self menu-transition) 1.0)
(or (and (nonzero? (-> self state-pos)) (= (-> self anim-frame) 1.0))
(or (and (zero? (-> self state-pos)) (= (-> self anim-frame) 0.0))
(and (!= (-> self starting-state) 'main) (!= (-> self next) 'none))
)
)
)
(set! (-> self current) (-> self next))
(set! (-> self next) 'none)
(set! (-> self option-index) (-> self next-option-index))
(set! (-> self want-option-index) 0)
(set-menu-options self (-> self current))
(set! (-> self scanlines-alpha) 0.0)
)
)
)
(set! (-> self main-menu)
(and (zero? (-> self state-pos)) (and (= (-> self menu-transition) 0.0)
(= (-> self next) 'none)
(or (= (-> self state-array 0) 'main) (= (-> self current) 'main))
)
)
)
(when *cheat-mode*
(when (zero? (-> self state-pos))
(cond
((and (cpad-hold? 0 l2) (cpad-hold? 0 r1))
(when (= (-> self current-options) *main-options*)
(set! (-> *progress-work* secrets-unlocked) #t)
(set! (-> *progress-work* selected-num) 0)
(set! (-> self current-options) *main-options-debug*)
)
)
((= (-> self current-options) *main-options-debug*)
(set! (-> self current-options) *main-options*)
)
)
)
)
(if (= (-> self ring-angle) (-> self ring-want-angle))
(respond-to-cpad self)
)
(let ((f30-0 (/ (-> self clock time-adjust-ratio) 200)))
(cond
((= (-> self menu-transition) 1.0)
(if (and (zero? (-> self state-pos)) (= (-> self starting-state) 'main))
(seek! (-> self anim-frame) 0.0 (/ (-> self clock time-adjust-ratio) 50))
(seek! (-> self anim-frame) 1.0 (/ (-> self clock time-adjust-ratio) 50))
)
(let ((f0-27 (if (and (zero? (-> self state-pos)) (!= (-> self starting-state) 'title))
0.0
0.2
)
)
)
(when (= (-> self next) 'bigmap)
(set! f0-27 0.4)
(set! f30-0 (/ (-> self clock time-adjust-ratio) 125))
)
(seek! (-> self pos-transition) f0-27 f30-0)
)
)
((zero? (-> self state-pos))
(if (= (-> self current) 'bigmap)
(set! f30-0 (/ (-> self clock time-adjust-ratio) 20))
)
(if (!= (-> self starting-state) 'title)
(seek! (-> self pos-transition) 0.0 f30-0)
)
)
)
)
(if (!= (-> self starting-state) 'main)
(set! (-> self pos-transition) 0.2)
)
(set-ring-position self)
(when (= (-> self ring-angle) (-> self ring-want-angle))
(cond
((< (-> self want-option-index) 0)
(cond
((and (= *cheat-mode* #f) (or (demo?) (kiosk?)))
(if (> (-> self option-index) 0)
(+! (-> self option-index) -1)
)
)
(else
(set! (-> self option-index)
(min-max-wrap-around (+ (-> self option-index) -1) 0 (+ (length (-> self current-options options)) -1))
)
)
)
(set! (-> self graphic-index) (-> self option-index))
(+! (-> self want-option-index) 1)
)
((> (-> self want-option-index) 0)
(cond
((and (= *cheat-mode* #f) (or (demo?) (kiosk?)))
(if (< (-> self option-index) (+ (length (-> self current-options options)) -1))
(+! (-> self option-index) 1)
)
)
(else
(set! (-> self option-index)
(min-max-wrap-around (+ (-> self option-index) 1) 0 (+ (length (-> self current-options options)) -1))
)
)
)
(+! (-> self want-option-index) -1)
)
)
)
(if (= (-> self anim-frame) 0.0)
(set! (-> self swing) (seek-ease
(-> self swing)
4.0
(/ (-> self clock time-adjust-ratio) 20)
0.5
(/ (-> self clock time-adjust-ratio) 200)
)
)
(set! (-> self swing) (seek-ease
(-> self swing)
0.0
(* 0.07 (-> self clock time-adjust-ratio))
0.5
(* 0.007 (-> self clock time-adjust-ratio))
)
)
)
(when (-> self main-menu)
(set! (-> self ring-want-angle) (ceil (* 182.04445 (* 36.0 (the float (-> self option-index))))))
(if (and (= (-> self ring-want-angle) 0.0) (< 32768.0 (-> self ring-angle)))
(set! (-> self ring-want-angle) 65536.0)
)
(let ((f0-54 (- (-> self ring-want-angle) (-> self ring-angle))))
(when (< 32768.0 (fabs f0-54))
(if (< 0.0 f0-54)
(+! (-> self ring-angle) 65536.0)
(+! (-> self ring-angle) -65536.0)
)
)
)
(seek! (-> self ring-angle) (-> self ring-want-angle) (* speed-mod 910.2222 (-> self clock time-adjust-ratio)))
)
(let ((gp-4 (quaternion-vector-angle!
(new 'stack-no-clear 'quaternion)
*x-vector*
(* 182.04445 (* (-> self swing) (sin (the float (* 40 (current-time))))))
)
)
(s5-4 (quaternion-vector-angle!
(new 'stack-no-clear 'quaternion)
*y-vector*
(* 182.04445 (* (-> self swing) (sin (the float (* 0 (current-time))))))
)
)
)
(quaternion*! (-> self root quat) (-> self init-quat) gp-4)
(quaternion*! (-> self root quat) (-> self root quat) s5-4)
)
(quaternion-normalize! (-> self root quat))
(if (= (-> self ring-angle) (-> self ring-want-angle))
(set! (-> self graphic-index) (-> self option-index))
)
(case *kernel-boot-message*
(('kiosk)
(if (and (nonzero? (-> self start-time))
(>= (- (-> *display* real-clock frame-counter) (-> self start-time)) (seconds 60))
(>= (- (-> *display* real-clock frame-counter) (-> *cpad-list* cpads 0 real-change-time)) (seconds 60))
(or (can-go-back? self) (= (-> self current) 'select-kiosk-start-special))
(not (handle->process (-> *game-info* auto-save-proc)))
)
(initialize! *game-info* 'game (the-as game-save #f) (the-as string #f) (the-as resetter-spec #f))
)
)
)
)
(none)
)
(defun end-scan ((arg0 hud-box) (arg1 float))
(with-dma-buffer-add-bucket ((s5-0 (-> *display* frames (-> *display* on-screen) global-buf))
(bucket-id bucket582)
)
(#when PC_PORT
(when (not (-> *pc-settings* use-vis?))
(set! (-> arg0 min x) (the float (the int (adjust-game-x (-> arg0 min x)))))
(set! (-> arg0 max x) (the float (the int (adjust-game-x (-> arg0 max x)))))
)
)
(draw-scan-and-line arg0 s5-0 arg1)
)
0
)
(defbehavior progress-post progress ()
(local-vars (sv-208 font-context) (sv-212 int) (sv-216 hud-box) (sv-220 symbol))
(when (-> self current-options)
(set-selected-color self)
(set! (-> self scissor-count) -1)
(progress-method-33 self (-> *progress-work* full-screen))
(let ((gp-0 (-> self current-options options)))
(let ((s3-0 (-> self current-options y-center))
(s5-0 (-> self current-options y-space))
)
(let ((s2-0 (new-stack-matrix0))
(s4-0 *progress-work*)
)
(mem-copy! (the-as pointer s2-0) (the-as pointer *font-default-matrix*) 64)
(set! sv-208 (new 'stack 'font-context s2-0 0 0 0.0 (font-color default) (font-flags shadow kerning)))
(set! sv-212 (- s3-0 (/ (* s5-0 (length gp-0)) 2)))
(set! sv-216 (new 'stack-no-clear 'hud-box))
(set! sv-220 (and (!= (-> self current) 'main) (or (= (-> self next) 'none) (> (-> self state-pos) 0))))
(progress-method-33 self (-> s4-0 small-screen))
(when sv-220
(begin-scan sv-216 self)
(let ((f30-0 (fmax 0.0 (* 2.0 (- 0.5 (-> self menu-transition))))))
(when (not (or (= (-> self current) 'bigmap) (= (-> self next) 'bigmap)))
(draw-bg-box-alpha-1 self (-> s4-0 small-screen) (* 144.0 f30-0))
(draw-bg-box-outline self (-> s4-0 small-screen) (* 128.0 f30-0))
)
)
)
)
; (if (or (= (-> self current-options) *title*) (= (-> self current-options) *options-options*))
; (+ s5-0 20)
; )
(if (or (= (-> self current-options) *title-pc*) (= (-> self current-options) *options-options-pc*))
(+! s5-0 20)
)
)
(dotimes (s5-1 (length gp-0))
(set! (-> self current-index) s5-1)
(set-scale! sv-208 0.5)
(set! (-> sv-208 origin x) 70.0)
(set! (-> sv-208 origin y) (the float sv-212))
(set-width! sv-208 375)
(set-height! sv-208 30)
(set! (-> sv-208 flags) (font-flags kerning middle middle-vert large))
(let ((v1-51 sv-208))
(set! (-> v1-51 color) (if (and (= s5-1 (-> self option-index)) (= (-> self menu-transition) 0.0))
(font-color font-color-33)
(font-color font-color-32)
)
)
)
;; og:preserve-this added for proper aspect ratio-ing
(#when PC_PORT
(when (not (-> *pc-settings* use-vis?))
(set! (-> sv-208 origin x) (the float (the int (adjust-game-x (-> sv-208 origin x)))))
(set! (-> sv-208 width) (the float (the int (* (-> sv-208 width) (-> *pc-settings* aspect-ratio-reciprocal)))))
)
)
(draw-option
(-> gp-0 s5-1)
self
sv-208
s5-1
(and (= (-> self menu-transition) 0.0) (-> self selected-option) (= s5-1 (-> self option-index)))
)
)
)
(if sv-220
(set! (-> self scanlines-alpha) (seek-ease
(-> self scanlines-alpha)
(- 1.0 (-> self menu-transition))
(/ (-> self clock time-adjust-ratio) 20)
0.3
(/ (-> self clock time-adjust-ratio) 1000)
)
)
)
(progress-method-34 self)
(end-scan sv-216 (-> self scanlines-alpha))
)
(when (and (< 0.8 (-> self anim-frame)) (or (= (-> self current) 'bigmap) (= (-> self next) 'bigmap)))
(progress-method-33 self (-> *progress-work* full-screen))
(cond
((>= (-> self pos-transition) 0.38)
(draw! *bigmap* 1792 1840 2304 2256)
)
(else
(let ((s4-1 (vector<-cspace! (new 'stack-no-clear 'vector) (-> self node-list data 21)))
(s3-1 (vector<-cspace! (new 'stack-no-clear 'vector) (-> self node-list data 24)))
(gp-1 (new 'stack-no-clear 'vector4w))
)
(set! (-> gp-1 quad) (the-as uint128 0))
(let ((s5-2 (new 'stack-no-clear 'vector4w)))
(set! (-> s5-2 quad) (the-as uint128 0))
(if (and (transform-point-qword! gp-1 s4-1) (transform-point-qword! s5-2 s3-1))
(draw! *bigmap* (/ (-> s5-2 x) 16) (/ (-> s5-2 y) 16) (/ (-> gp-1 x) 16) (/ (-> gp-1 y) 16))
)
)
)
)
)
(progress-method-34 self)
)
(ja-post)
)
(set! (-> (method-of-type progress come-in) trans)
(lambda :behavior progress ()
(let ((f30-0 (if (= (-> self starting-state) 'main)
0.0
0.2
)
)
;; og:preserve-this added variable
(speed-mod (if (-> *pc-settings* fast-progress?) (-> *pc-cheat-state* progress-speed) 1.0))
)
(when (hud-hidden?)
(set! (-> self pos-transition) (seek-ease
(-> self pos-transition)
f30-0
(* speed-mod 0.03 (-> self clock time-adjust-ratio))
0.4
(* 0.003 (-> self clock time-adjust-ratio))
)
)
(when (= (-> self lock-tick-count) 1)
(sound-play "ring-appear")
(set-menu-mode *blit-displays-work* #t)
)
(+! (-> self lock-tick-count) 1)
)
(set-ring-position self)
(when (= (-> self pos-transition) f30-0)
(set! (-> self start-time) (-> *display* real-clock frame-counter))
(go-virtual idle)
)
)
)
)
(set! (-> (method-of-type progress go-away) trans)
(lambda :behavior progress ()
;; og:preserve-this added variable
(let ((speed-mod (if (-> *pc-settings* fast-progress?) (-> *pc-cheat-state* progress-speed) 1.0)))
(seek! (-> self anim-frame) 0.0 (/ (* speed-mod (-> self clock time-adjust-ratio)) 50))
(cond
((= (-> self anim-frame) 0.0)
(seek! (-> self pos-transition) 1.0 (/ (* speed-mod (-> self clock time-adjust-ratio)) 50))
(if (= (-> self pos-transition) 1.0)
(go-virtual gone)
)
)
(else
(seek! (-> self pos-transition) 0.0 (/ (* speed-mod (-> self clock time-adjust-ratio)) 50))
)
)
(set-ring-position self)
)
)
)
(set! (-> (method-of-type progress idle) event)
(lambda :behavior progress ((proc process) (argc int) (message symbol) (block event-message-block))
(case message
(('notify)
(cond
((= (-> block param 0) 'done)
(let ((status (the mc-status-code (-> block param 1))))
(format #t "DONE NOTIFY: ~S ~S~%" (mc-status-code->string status) (-> self current))
)
;; og:preserve-this patched to next instead of current because we save synchronously
(case (-> self next)
(('saving)
(cond
((= (-> self state-array 0) 'title)
(let ((gp-1 (-> *setting-control* user-default auto-save)))
(sound-volume-off)
(set! (-> *setting-control* user-default auto-save) gp-1)
(progress-intro-start)
)
)
((-> *progress-work* hero-mode-save)
(set-next-state self 'hero-mode-message 0)
)
(else
(pop-state self)
)
)
)
(('formatting)
(set-next-state self 'creating 0)
)
(('creating)
(cond
((= (-> self state-array 0) 'title)
(set-next-state self 'select-save-title 0)
)
((-> *progress-work* hero-mode-save)
(set-next-state self 'select-save-hero 0)
)
(else
(set-next-state self 'select-save 0)
)
)
)
)
)
((= (-> block param 0) 'error)
(let ((status (the mc-status-code (-> block param 1))))
(format #t "ERROR NOTIFY: ~S ~S ~S~%"
(mc-status-code->string status)
(-> self current)
(-> self next)
)
)
(case (-> block param 1)
((14)
(set-next-state self 'insufficient-space 0)
)
(else
(case (-> self next) ;; og:preserve-this patched to next instead of current because we save synchronously
(('formatting 'format-card)
(set-next-state self 'error-formatting 0)
)
(('creating 'create-game)
(set-next-state self 'error-creating 0)
)
(('saving 'select-save 'select-save-title 'select-save-hero 'already-exists)
(set-next-state self 'error-saving 0)
)
(('loading 'select-load)
(set-next-state self 'error-loading 0)
)
)
)
)
)
)
)
)
)
)
(defmethod set-menu-options ((this progress) (arg0 symbol))
(set! (-> this current-options) #f)
(case arg0
(('go-away)
(go (method-of-object this go-away))
)
(('main)
(set! (-> this current-options) (cond
(*cheat-mode*
*main-options*
)
((kiosk?)
*main-kiosk-options*
)
((= *kernel-boot-message* 'demo)
*main-demo-options*
)
((= *kernel-boot-message* 'demo-shared)
*main-demo-shared-options*
)
(else
*main-options*
)
)
)
)
(('options)
(set! (-> this current-options) *options-options-pc*)
)
(('controls)
(set! (-> (the-as paged-menu-option (-> *controls-options* options 0)) page-index) 0)
(set! (-> (the-as paged-menu-option (-> *controls-options* options 0)) prev-page-index) 0)
(set! (-> this current-options) *controls-options*)
)
(('game-options)
(set! (-> this current-options) (cond
((demo?)
(if (= (scf-get-territory) 1)
*game-options-demo*
*game-options-demo*
)
)
(else
*game-options-pc*
)
)
)
)
(('graphic-options)
(set! (-> this current-options)
(if (or (= (scf-get-territory) 1) (and (= *progress-cheat* 'pal) (cpad-hold? 0 l2) (cpad-hold? 0 r2)))
*graphic-title-options-pal*
*graphic-options-pc*
)
)
)
(('sound-options)
(set! (-> this current-options) *sound-options-pc*)
)
(('picture-options)
(set! (-> this current-options) *picture-options*)
)
(('camera-options)
(set! (-> this current-options) *camera-options*)
)
(('select-load 'select-save)
(set! (-> this current-options) *load-save-options*)
)
(('select-save-title)
(set! (-> this current-options) *save-options-title*)
)
(('select-save-hero)
(logior! (-> *game-info* purchase-secrets) (game-secrets hero-mode))
(set! (-> *progress-work* hero-mode-save) #t)
(set! (-> this current-options) *load-save-options*)
)
(('hero-mode-message)
(set! (-> this current-options) *hero-mode-message-options*)
)
(('loading 'saving 'creating 'formatting)
(set! (-> this current-options) *loading-options*)
)
(('unformatted-card 'insufficient-space 'no-memory-card)
(set! (-> this current-options) *insufficient-space-options*)
)
(('secrets-insufficient-space 'secrets-no-memory-card)
(set! (-> this current-options) *secrets-insufficient-space-options*)
)
(('insert-card)
(set! (-> this current-options) *insert-card-options*)
)
(('error-loading 'error-saving 'error-formatting 'error-creating)
(set! (-> this current-options) *error-loading-options*)
)
(('error-auto-saving)
(set! (-> this current-options) *error-auto-saving-options*)
)
(('card-removed)
(set! (-> this current-options) *card-removed-options*)
)
(('error-disc-removed)
(set! (-> this current-options) *error-disc-removed-options*)
)
(('error-reading)
(set! (-> this current-options) *error-reading-options*)
)
(('icon-info)
(set! (-> this current-options) *icon-info-options*)
)
(('format-card)
(set! (-> this current-options) *format-card-options*)
)
(('already-exists)
(set! (-> this current-options) *already-exists-options*)
)
(('create-game)
(set! (-> this current-options) *create-game-options*)
)
(('video-mode-warning)
(set! (-> this current-options) *video-mode-warning-options*)
)
(('video-mode-ok)
(set! (-> this current-options) *video-mode-ok-options*)
)
(('progressive-mode-warning)
(set! (-> this current-options) *progressive-mode-warning-options*)
)
(('progressive-mode-ok)
(set! (-> this current-options) *progressive-mode-ok-options*)
)
(('language-select)
(set! (-> this current-options) *language-options*)
)
(('title)
(set! (-> this current-options) *title-pc*)
)
(('title-options)
(set! (-> this current-options) *options-options-pc*)
)
(('select-start 'select-pre-start 'select-kiosk-start 'select-kiosk-start-special)
(set! (-> this current-options) *select-start-options*)
(set! (-> (the-as menu-select-start-option (-> *select-start-options* options 0)) current-index) 0.0)
(set! (-> (the-as menu-select-start-option (-> *select-start-options* options 0)) target-index) 0.0)
(set! (-> (the-as menu-select-start-option (-> *select-start-options* options 0)) selected-index) 0)
0
)
(('select-scene)
(set! (-> this current-options) *select-scene-options*)
(set! (-> (the-as menu-select-scene-option (-> *select-scene-options* options 0)) current-index) 0.0)
(set! (-> (the-as menu-select-scene-option (-> *select-scene-options* options 0)) target-index) 0.0)
(set! (-> (the-as menu-select-scene-option (-> *select-scene-options* options 0)) selected-index) 0)
0
)
(('select-scene-special)
(set! (-> this starting-state) 'title)
(set! (-> this state-pos) 0)
(let ((v1-80 (-> this state-pos)))
(set! (-> this state-array v1-80) 'title)
(set! (-> this option-index-stack v1-80) 3)
(let ((v1-81 (+ v1-80 1)))
(set! (-> this state-array v1-81) 'unlocked-secrets)
(set! (-> this option-index-stack v1-81) (-> this option-index))
(set! (-> this state-pos) (+ v1-81 1))
)
)
(dotimes (s5-1 (-> this state-pos))
(format #t "select-scene-special: ~S ~D~%" (-> this state-array s5-1) (-> this option-index-stack s5-1))
)
(set! (-> this current-options) *select-scene-options*)
)
(('inventory)
(set! (-> this current-options) *inventory*)
)
(('bigmap)
(set! (-> this current-options) *bigmap-options*)
)
(('missions)
(set! (-> this missions-total-spacing) 0.0)
(set! (-> (the-as menu-missions-option (-> *missions-options* options 0)) current-index) 0.0)
(set! (-> (the-as menu-missions-option (-> *missions-options* options 0)) target-index) 0.0)
(set! (-> this current-options) *missions-options*)
)
(('highscores)
(set! (-> this current-options) *highscores-options*)
)
(('secret)
(set! (-> this secret-buying) #f)
(set! (-> this current-options) *secret-options*)
)
(('quit-restart)
(set! (-> this current-options) *quit-restart-options*)
)
(('unlocked-secrets)
(set! (-> this current-options) *unlocked-secrets-pc*)
)
;; pc menus
(('aspect-ratio-custom)
(set! (-> *progress-state-pc* aspect-ratio-ratio-index) 0)
(set! (-> this current-options) *aspect-ratio-custom-options*)
)
(('music-player)
(set! (-> *progress-state-pc* music-player-selected) #f)
(set! (-> (the-as menu-music-player-option (-> *music-player-options* options 0)) excitement) 0)
(set! (-> this current-options) *music-player-options*)
(when (aif (level-get *level* 'title) (= (-> it status) 'active))
(remove-setting *setting-control* (handle->process (-> *game-info* controller 0)) 'music-volume)
)
)
(('resolutions)
(set! (-> (the-as menu-resolution-option (-> *resolutions-options* options 0)) selected-index) -1)
(set! (-> this current-options) *resolutions-options*)
)
(('fps-disclaimer)
(set-time! (-> *progress-state-pc* frame-rate-disclaimer-time))
(set! (-> this current-options) *frame-rate-disclaimer-options*)
)
(('generic-menu)
;; a single condition to handle all generic menu links
(let ((curr-history-entry (-> *progress-pc-generic-store* history-stack
(-> *progress-pc-generic-store* history-stack-index))))
;; call the on-load function is appropriate, this can be used to perform some kind of generic setup
;; for the particular route
(call-on-load curr-history-entry)
;; restore state from the history entry
(set! (-> *progress-pc-generic-store* clear-screen?) #f)
(set! (-> *progress-pc-generic-store* current-menu-hover-index) (-> curr-history-entry hover-index))
(set! (-> *progress-pc-generic-store* current-menu-scroll-index) (the float (-> curr-history-entry scroll-index)))
(if (!= (-> curr-history-entry progress-id) 'generic-menu)
;; do a recursive call to hit the relevant case in this switch
(set-menu-options this (-> curr-history-entry progress-id))
;; otherwise, set the options
(set! (-> this current-options) (-> curr-history-entry ref)))))
)
(when (= (-> this current-options) #f)
(format #t "Didn't find new menu settings!!~%")
(pop-state this)
)
0
)
(defun set-progress-frame-rate-index ((idx int))
"Set the frame rate option index accordingly."
(when idx
(set! (-> *progress-state-pc* frame-rate-choice-index) idx)
(return 0)
)
;; default to 60 fps
(set! (-> *progress-state-pc* frame-rate-choice-index) 0)
;; lookup entry that matches
(dotimes (i (-> *frame-rate-options* length))
(if (= (-> *pc-settings* target-fps) (-> *frame-rate-options* i))
(set! (-> *progress-state-pc* frame-rate-choice-index) i))
)
0)
(defmethod init-defaults ((this progress))
(set! (-> this total-num-tasks) 0)
(set! (-> this clear-screen) #f)
(set! (-> this scanlines-alpha) 0.0)
(set-time! (-> this start-time))
(set! (-> this which-slot) (-> *progress-work* last-slot-saved))
(set! (-> this yes-no-choice) #f)
(set-time! (-> this time-out))
(set-time! (-> this last-sound))
(set-time! (-> this last-move))
(set! (-> this center-x-backup) (-> *setting-control* user-default screenx))
(set! (-> this center-y-backup) (-> *setting-control* user-default screeny))
(set! (-> this flip-horizontal) (-> *setting-control* cam-default flip-horizontal))
(set! (-> this flip-vertical) (-> *setting-control* cam-default flip-vertical))
(set! (-> this progressive-scan) (-> *setting-control* user-default set-video-mode))
(set! (-> this aspect-ratio) (get-aspect-ratio))
(set! (-> this video-mode) (get-video-mode))
(set! (-> this stereo-mode-backup) (-> *setting-control* user-default stereo-mode))
(set! (-> this vibrations) (-> *setting-control* user-default vibration))
(set! (-> this subtitles) (-> *setting-control* user-default subtitle))
(set! (-> this language-index) (the-as language-enum-s32 (-> *setting-control* user-default language)))
(set! (-> this subtitle-language-index)
(the-as language-enum-s32 (-> *setting-control* user-default subtitle-language))
)
(set! (-> this audio-language-index)
(the-as language-enum-s32 (-> *setting-control* user-default audio-language))
)
(set! (-> (the-as menu-missions-option (-> *missions-options* options 0)) current-index) 0.0)
(set! (-> (the-as menu-missions-option (-> *missions-options* options 0)) target-index) 0.0)
(set! (-> *progress-work* secrets-unlocked) #f)
(set! (-> *progress-work* hero-mode-save) #f)
(set-setting-by-param *setting-control* 'extra-bank '((force2 menu1)) 0 0)
(cond
((or (nonzero? (-> *setting-control* user-current subtitle-language))
(nonzero? (-> *setting-control* user-current language))
(nonzero? (-> *setting-control* user-current audio-language))
)
(set! (-> *unlocked-secrets* options length) 11)
)
(else
(set! (-> *unlocked-secrets* options length) 12)
)
)
;; PC STATE BEGIN
;; --------------
(init! *progress-pc-generic-store*)
(set! (-> *progress-state-pc* music-player-track) #f)
)
(defun progress-pc-fetch-external-times ((highscore-index int))
(when (-> *pc-settings* speedrunner-mode?)
(case highscore-index
((0) (pc-fetch-external-highscores "was-pre-game"))
((1) (pc-fetch-external-highscores "air-time"))
((2) (pc-fetch-external-highscores "total-air-time"))
((3) (pc-fetch-external-highscores "jump-distance"))
((4) (pc-fetch-external-highscores "total-jump-distance"))
((5) (pc-fetch-external-highscores "roll-count"))
((6) (pc-fetch-external-highscores "wascity-gungame"))
((7) (pc-fetch-external-highscores "jetboard"))
((8) (pc-fetch-external-highscores "gungame-yellow-2"))
((9) (pc-fetch-external-highscores "gungame-red-2"))
((10) (pc-fetch-external-highscores "gungame-ratchet"))
((11) (pc-fetch-external-highscores "gungame-clank"))
((12) (pc-fetch-external-highscores "power-game"))
((13) (pc-fetch-external-highscores "destroy-interceptors"))
((14) (pc-fetch-external-race-times "time-trial"))
((15) (pc-fetch-external-race-times "rally"))
((16) (pc-fetch-external-speedrun-times "any"))
((17) (pc-fetch-external-speedrun-times "nooob"))
((18) (pc-fetch-external-speedrun-times "allmissions"))
((19) (pc-fetch-external-speedrun-times "100"))
((20) (pc-fetch-external-speedrun-times "anyorbs"))
((21) (pc-fetch-external-speedrun-times "anyhero")))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; CUSTOM MENU OPTIONS
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmacro min-max-wrap-around+! (var inc minimum maximum)
`(set! ,var (min-max-wrap-around (+ ,var ,inc) ,minimum ,maximum)))
(defmethod respond-progress ((obj menu-aspect-ratio-custom-option) (arg0 progress) (arg1 symbol))
"Handle progress menu navigation logic."
(let ((aspect-custom-val-ptr (case (-> *progress-state-pc* aspect-ratio-ratio-index)
((0)
(&-> *pc-settings* aspect-custom-x))
((1)
(&-> *pc-settings* aspect-custom-y))
(else
(&-> *pc-settings* aspect-custom-x))
)))
(cond
((cpad-pressed? 0 left l-analog-left)
(when (< 0 (-> *progress-state-pc* aspect-ratio-ratio-index))
(sound-play "roll-over")
(1-! (-> *progress-state-pc* aspect-ratio-ratio-index))
)
)
((cpad-pressed? 0 right l-analog-right)
(when (> 1 (-> *progress-state-pc* aspect-ratio-ratio-index))
(sound-play "roll-over")
(1+! (-> *progress-state-pc* aspect-ratio-ratio-index))
)
)
((cpad-pressed? 0 up l-analog-up)
(when (> 99 (-> aspect-custom-val-ptr))
(sound-play "roll-over")
(1+! (-> aspect-custom-val-ptr))
)
)
((cpad-pressed? 0 down l-analog-down)
(when (< 1 (-> aspect-custom-val-ptr))
(sound-play "roll-over")
(1-! (-> aspect-custom-val-ptr))
)
)
((cpad-pressed? 0 triangle)
(cpad-clear! 0 triangle)
(sound-play "generic-beep")
(pop-state arg0)
)
((cpad-pressed? 0 confirm)
(cpad-clear! 0 confirm)
(when (>= (/ (the float (-> *pc-settings* aspect-custom-x)) (the float (-> *pc-settings* aspect-custom-y))) (/ 4.0 3.0))
(set! (-> *setting-control* user-default aspect-ratio) 'aspect4x3)
(set-aspect! *pc-settings* (-> *pc-settings* aspect-custom-x) (-> *pc-settings* aspect-custom-y))
(sound-play "generic-beep")
(pop-state arg0)
)
)
))
0
)
(defmethod respond-progress ((this menu-frame-rate-disclaimer-option) (arg0 progress) (arg1 symbol))
"Handle progress menu navigation logic."
(when (time-elapsed? (-> *progress-state-pc* frame-rate-disclaimer-time) (seconds 3))
(let ((choice (&-> arg0 yes-no-choice))
(sound? #f)
)
(cond
((cpad-pressed? 0 left l-analog-left)
(set! sound? (not (-> choice 0)))
(set! (-> choice 0) #t)
)
((cpad-pressed? 0 right l-analog-right)
(set! sound? (-> choice 0))
(set! (-> choice 0) #f)
)
((cpad-pressed? 0 confirm)
(cpad-clear! 0 confirm)
(cond
((-> arg0 yes-no-choice)
(true! *frame-rate-disclaimer-seen?*)
(sound-play "generic-beep")
(set-frame-rate! *pc-settings* (-> *frame-rate-options* (-> *progress-state-pc* frame-rate-choice-index)) #t)
(commit-to-file *pc-settings*)
(pop-state arg0)
)
(else
(sound-play "generic-beep")
(set-progress-frame-rate-index (the int #f))
(pop-state arg0)
)
)
)
)
(if sound?
(sound-play "generic-beep")
)
)
)
0
)
(defbehavior play-music-player progress ((info music-player-track-info) (flava int))
"play a music track using music player track info."
(set! (-> *progress-state-pc* music-player-track) info)
(set-setting! 'music (-> info name) 0.0 0)
(set-setting! 'sound-flava #f 999999.0 flava)
(set-setting! 'sound-mode #f 0.0 (-> info mode))
(apply-settings *setting-control*)
(sound-group-continue (sound-group music))
0)
(defbehavior stop-music-player progress ()
"play a music track using music player track info."
(remove-setting! 'music)
(remove-setting! 'sound-flava)
(remove-setting! 'sound-mode)
(sound-set-midi-reg 0 0)
(sound-set-midi-reg 2 0)
(sound-set-midi-reg 16 0)
(set! (-> *progress-state-pc* music-player-track) #f)
;(min! (-> *setting-control* user-current sound-excitement) 0.0)
(sound-set-midi-reg 16 (the int (* 100.0 (-> *setting-control* user-current sound-excitement))))
(set! (-> *setting-control* sound-excitement-change-time) (-> *display* base-clock frame-counter))
(apply-settings *setting-control*)
(sound-group-pause (sound-group music))
0)
(defun count-bits ((val int))
"return the number of bits set to 1."
(let ((bits 0))
(dotimes (i 64)
(if (logtest? val (ash 1 i))
(1+! bits))
)
bits)
)
(defun bit-on-offset ((bits int) (n int))
"return the bit offset of where the n'th bit that is set to 1 is"
(let ((bit-on-i 0))
(dotimes (i 64)
(if (logtest? bits (ash 1 i))
(if (= bit-on-i n)
(return i)
(1+! bit-on-i)))
))
-1)
(defmethod respond-progress ((obj menu-music-player-option) (arg0 progress) (arg1 symbol))
"Handle progress menu navigation logic."
(if (= 0.0 (-> obj max-scroll))
(set! (-> obj max-scroll) (+ -141.0 (* (-> *music-player-tracks* length) 23))))
;; control logic
(let ((scroll-sound? #f)
(track-max (1- (-> *music-player-tracks* length)))
(flava-max (1- (count-bits (the-as int (-> *music-player-tracks* (-> obj music-index) flava)))))
(old-excitement (-> obj excitement))
(play? #f))
;; excitement controls
(cond
((cpad-pressed? 0 right l-analog-right)
(seekl! (-> obj excitement) 3 1))
((cpad-pressed? 0 left l-analog-left)
(seekl! (-> obj excitement) 0 1))
)
(when (!= (-> obj excitement) old-excitement)
(sound-play "generic-beep")
(sound-set-midi-reg 16 (* 25 (-> obj excitement))) ;; play new excitement track
(unless (or (< (-> obj excitement) old-excitement) (process-by-name "sound-stinger" arg0))
(process-spawn-function process :to arg0 :name "sound-stinger"
(lambda :behavior process ((stinger int))
(let ((state-time (current-time)))
(format 0 "set stinger ~D~%" stinger)
(sound-set-midi-reg 0 stinger)
(until (>= (- (current-time) state-time) (seconds 0.5))
(suspend))
(sound-set-midi-reg 0 0)
)
)
(+ 9 (-> obj excitement)))
)
(unless (process-by-name "sound-excitement" arg0)
(process-spawn-function process :to arg0 :name "sound-excitement"
(lambda :behavior process ((excite-fade int))
(let ((state-time (current-time)))
(format 0 "set excitement fade ~D~%" (* 25 excite-fade))
(sound-set-midi-reg 2 (* 25 excite-fade)) ;; fade out old excitement track
(until (>= (- (current-time) state-time) (seconds 0.8))
(suspend))
)
)
old-excitement)
)
)
(cond
((or (cpad-pressed? 0 down l-analog-down)
(and (cpad-hold? 0 down l-analog-down) (>= (- (current-time) (-> obj last-move)) (seconds 0.2))))
(set! (-> obj last-move) (current-time))
(true! scroll-sound?)
(cond
((-> *progress-state-pc* music-player-selected)
(min-max-wrap-around+! (-> obj flava-index) 1 0 flava-max))
(else
(min-max-wrap-around+! (-> obj music-index) 1 0 track-max)
(if (= (-> obj music-index) 0)
(set! (-> obj current-scroll) 0.0)))
))
((or (cpad-pressed? 0 up l-analog-up)
(and (cpad-hold? 0 up l-analog-up) (>= (- (current-time) (-> obj last-move)) (seconds 0.2))))
(set! (-> obj last-move) (current-time))
(true! scroll-sound?)
(cond
((-> *progress-state-pc* music-player-selected)
(min-max-wrap-around+! (-> obj flava-index) -1 0 flava-max))
(else
(min-max-wrap-around+! (-> obj music-index) -1 0 track-max)
(if (= (-> obj music-index) track-max)
(set! (-> obj current-scroll) (-> obj max-scroll))))
))
((cpad-pressed? 0 confirm)
(cpad-clear! 0 confirm)
(sound-play "generic-beep")
(cond
;; track is locked. do nothing.
((not (get-bit (-> *pc-settings* music-unlocked) (-> obj music-index)))
)
;; we have a track with a submenu selected
((-> *progress-state-pc* music-player-selected)
(let ((flava (bit-on-offset (the-as int (-> *music-player-tracks* (-> obj music-index) flava)) (-> obj flava-index))))
(cond
((flava-unlocked? flava)
(set! (-> *progress-state-pc* music-player-flava) flava)
(true! play?)
;; exit submenu
(false! (-> *progress-state-pc* music-player-selected))
)
(else
;; do nothing.
)
)
)
)
;; we have a track with a submenu that's not open, open it
((nonzero? (-> *music-player-tracks* (-> obj music-index) flava))
;; same track that's currently playing, we can just reuse the flava position that's being used
;; otherwise use zero.
(if (= (-> *progress-state-pc* music-player-track) (-> *music-player-tracks* (-> obj music-index)))
(set! (-> obj flava-index) (count-bits (logand (1- (ash 1 (-> *progress-state-pc* music-player-flava))) (the-as int (-> *music-player-tracks* (-> obj music-index) flava)))))
(set! (-> obj flava-index) 0))
(true! (-> *progress-state-pc* music-player-selected)))
;; no submenu required, just play track.
(else
(set! (-> *progress-state-pc* music-player-flava) 0)
(true! play?))
)
(when play?
(play-music-player (-> *music-player-tracks* (-> obj music-index)) (-> *progress-state-pc* music-player-flava))
)
)
((cpad-pressed? 0 triangle)
(cpad-clear! 0 triangle)
(sound-play "generic-beep")
(cond
((-> *progress-state-pc* music-player-selected)
(false! (-> *progress-state-pc* music-player-selected)))
(else
(stop-music-player)
(pop-state arg0))
)
)
)
(when scroll-sound?
(sound-play "roll-over"))
)
0
)
(defun calculate-current-resolution-index ((want-aspect float) (want-w int) (want-h int))
(let ((res-w 0)
(res-h 0)
(res-aspect 0.0)
(res-valid 0))
(dotimes (i (pc-get-num-resolutions (= (pc-get-display-mode) 'windowed)))
(pc-get-resolution i (= (pc-get-display-mode) 'windowed) (& res-w) (& res-h))
(set! res-aspect (/ (the float res-w) (the float res-h)))
(when (or (= (pc-get-display-mode) 'windowed)
(< (fabs (- want-aspect res-aspect)) 0.05))
(if (and (= res-h want-h) (= res-w want-w))
(return res-valid))
(1+! res-valid))
)
(cond
;; 512x416
((and (= want-w 512) (= want-h 416))
res-valid)
;; 512x208
((and (= want-w 512) (= want-h 208))
(1+ res-valid))
;; nothing found
(else
-1)
))
)
(defglobalconstant DEBUG_RESOLUTION_OPTION #f)
(defmethod respond-progress ((this menu-resolution-option) (arg0 progress) (arg1 symbol))
"Handle progress menu navigation logic."
;; control logic
(let ((scroll-sound? #f)
(resolutions-valid 0)
(resolution-found #f)
(cur-w 0)
(cur-h 0)
(select-w -1)
(select-h -1)
)
(set! (-> this num-resolutions) (pc-get-num-resolutions (= (pc-get-display-mode) 'windowed)))
(cond
;; valid state
((> (-> this num-resolutions) 0)
(true! (-> this valid?))
;; this code isnt the greatest...
;; the logic here is that, unlike jak 1, we don't build a list of resolutions and then scroll through that.
;; we calculate the list every frame, keeping track of the index that is highlighted.
;; this allows for infinite resolutions and for it to update live according to monitor changes.
(cond
((fullscreen?)
;; grab current window sizes for aspect ratio purposes (only relevant for fullscreen)
(pc-get-window-size (&-> this win-w) (&-> this win-h))
(set! cur-w (-> *pc-settings* width))
(set! cur-h (-> *pc-settings* height))
(set! (-> this win-aspect) (/ (the float (-> this win-w)) (the float (-> this win-h))))
(#when DEBUG_RESOLUTION_OPTION (format *stdcon* "fullscreen mode~%"))
)
(else
(set! cur-w (-> *pc-settings* window-width))
(set! cur-h (-> *pc-settings* window-height))
(set! (-> this win-aspect) (/ (the float cur-w) (the float cur-h)))
(#when DEBUG_RESOLUTION_OPTION (format *stdcon* "windowed mode~%"))
)
)
;; check if we want to automatically pick something already
(when (= -1 (-> this selected-index))
(set! (-> this selected-index) (calculate-current-resolution-index (-> this win-aspect) cur-w cur-h))
(#when DEBUG_RESOLUTION_OPTION (format #t "recalc index got ~D~%" (-> this selected-index)))
;; update if not invalid?
(cond
((= (-> this selected-index) -1)
(set! (-> this selected-index) 0) ;; give up, just select the first one by default.
)
(else
(set! select-w cur-w)
(set! select-h cur-h)
(true! resolution-found)
(set! (-> this scroll-index) (the float (-> this selected-index)))
)
)
)
;; if we haven't automatically picked a resolution, iterate and find the one highlighted
(when (not resolution-found)
(#when DEBUG_RESOLUTION_OPTION (format *stdcon* "finding resolution ~D~%" (-> this selected-index)))
(dotimes (i (-> this num-resolutions))
;; count "valid" resolutions
(let ((this-w 0) (this-h 0) (this-aspect 0.0))
(pc-get-resolution i (= (pc-get-display-mode) 'windowed) (& this-w) (& this-h))
(set! this-aspect (/ (the float this-w) (the float this-h)))
(when (or (= (pc-get-display-mode) 'windowed)
(< (fabs (- (-> this win-aspect) this-aspect)) 0.05))
;; this is the highlighted option - save it
(when (= resolutions-valid (-> this selected-index))
(set! select-w this-w) (set! select-h this-h)
(true! resolution-found)
;;(set! i (-> this num-resolutions)) ;; abandon loop
)
(1+! resolutions-valid)
))
)
)
;; if still didn't find it, it must be one of the hardcoded cases
(cond
(resolution-found
;; yay
)
;; 512x416
((and (fullscreen?) (= resolutions-valid (-> this selected-index)))
(set! select-w 512)
(set! select-h 416)
)
;; 512x208
((and (fullscreen?) (= (1+ resolutions-valid) (-> this selected-index)))
(set! select-w 512)
(set! select-h 208)
)
;; STILL nothing? I don't know how this happens, just don't even try then.
(else
(false! (-> this valid?))
)
)
;; hardcoded cases
(when (fullscreen?)
(+! resolutions-valid 2))
)
;; not sure what happened, but there's not even any resolutions
(else
(false! (-> this valid?))
)
)
(cond
((-> this valid?)
(#when DEBUG_RESOLUTION_OPTION
(format *stdcon* "selected: ~D (~D x ~D)~%" (-> this selected-index) select-w select-h)
(format *stdcon* "current: ~D x ~D~%" cur-w cur-h)
(format *stdcon* "resolution: ~D valid (out of ~D)~%" resolutions-valid (-> this num-resolutions))
)
(cond
;; navigate up
((or (cpad-pressed? 0 up l-analog-up)
(and (cpad-hold? 0 up l-analog-up) (time-elapsed? (-> this last-move) (seconds 0.2))))
(set-time! (-> this last-move))
(true! scroll-sound?)
(min-max-wrap-around+! (-> this selected-index) -1 0 (1- resolutions-valid))
)
;; navigate down
((or (cpad-pressed? 0 down l-analog-down)
(and (cpad-hold? 0 down l-analog-down) (time-elapsed? (-> this last-move) (seconds 0.2))))
(set-time! (-> this last-move))
(true! scroll-sound?)
(min-max-wrap-around+! (-> this selected-index) 1 0 (1- resolutions-valid))
)
;; select
((cpad-pressed? 0 confirm)
(cpad-clear! 0 confirm)
(set-window-size! *pc-settings* select-w select-h)
(pc-settings-save)
(pop-state arg0))
;; exit
((cpad-pressed? 0 triangle)
(cpad-clear! 0 triangle)
(pop-state arg0))
)
)
(else
;; just triangle to exit
(when (cpad-pressed? 0 triangle)
(cpad-clear! 0 triangle)
(pop-state arg0))
)
)
(when scroll-sound?
(sound-play "roll-over"))
)
0
)
(defun hide-progress-screen ()
(when (and *progress-process* (!= (-> *progress-process* 0 starting-state) 'title))
(stop-music-player)
(set-next-state (-> *progress-process* 0) 'go-away 0)
(clear-history! *progress-pc-generic-store*)
)
(none)
)
;; NOTE - this technically includes the gold/silver/bronze times
;; maybe figure out how to omit them eventually, (not sure if there is anything that differentiates them)
;; From a highscores perspective it doesn't really matter, the default scores are awful
(define-extern get-highscore-score (function int int))
(defun progress-pc-get-num-nonzero-local-scores ((highscore-index int))
(let ((count 0)
(score-ptr (get-game-score-ref *game-info* (get-highscore-score highscore-index))))
(dotimes (idx 8)
(when (> (-> score-ptr idx) 0)
(inc! count)))
count))
(defun progress-pc-max-external-scores ((highscore-index int))
(case highscore-index
((0) (pc-get-num-external-highscores "scatter"))
((1) (pc-get-num-external-highscores "blaster"))
((2) (pc-get-num-external-highscores "vulcan"))
((3) (pc-get-num-external-highscores "peacemaker"))
((4) (pc-get-num-external-highscores "jetboard"))
((5) (pc-get-num-external-race-times "class3"))
((6) (pc-get-num-external-race-times "class2"))
((7) (pc-get-num-external-race-times "class1"))
((8) (pc-get-num-external-race-times "port"))
((9) (pc-get-num-external-race-times "erol"))
((10) (pc-get-num-external-race-times "class3rev"))
((11) (pc-get-num-external-race-times "class2rev"))
((12) (pc-get-num-external-race-times "class1rev"))
((13) (pc-get-num-external-highscores "onin"))
((14) (pc-get-num-external-highscores "mash"))))
(defun progress-pc-max-highscore-rows ((highscore-index int))
(case highscore-index
((0) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-highscores "scatter")))
((1) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-highscores "blaster")))
((2) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-highscores "vulcan")))
((3) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-highscores "peacemaker")))
((4) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-highscores "jetboard")))
((5) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-race-times "class3")))
((6) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-race-times "class2")))
((7) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-race-times "class1")))
((8) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-race-times "port")))
((9) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-race-times "erol")))
((10) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-race-times "class3rev")))
((11) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-race-times "class2rev")))
((12) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-race-times "class1rev")))
((13) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-highscores "onin")))
((14) (+ (progress-pc-get-num-nonzero-local-scores highscore-index) (pc-get-num-external-highscores "mash")))
((15) (pc-get-num-external-speedrun-times "any"))
((16) (pc-get-num-external-speedrun-times "anyhoverless"))
((17) (pc-get-num-external-speedrun-times "allmissions"))
((18) (pc-get-num-external-speedrun-times "100"))
((19) (pc-get-num-external-speedrun-times "anyorbs"))
((20) (pc-get-num-external-speedrun-times "anyhero"))
(else 8)))
(defmethod respond-progress ((this menu-sub-menu-option) (arg0 progress) (arg1 symbol))
(let ((s4-0 *progress-work*))
(when (and (not (-> s4-0 secrets-unlocked))
(or
;; for some reason we hit this case on the non-debug first time title screen.
;; we don't have to worry about insufficient memory card space, so this is just
;; commented out.
;; (= (-> arg0 current-options) *title-pc*)
(= (-> arg0 current-options) *unlocked-secrets*)
(= (-> arg0 current-options) *select-scene-options*)
(= (-> arg0 current-options) *select-start-options*)
)
)
(set! (-> arg0 state-pos) 0)
(set-next-state arg0 'secrets-insufficient-space 0)
)
(when (= (-> this name) (text-id progress-continue-without-save))
(let ((a1-3 (get-state-check-card arg0 (-> arg0 current))))
(set-next-state arg0 a1-3 0)
)
)
(when (and (= (-> this name) (text-id progress-secrets))
(= *title-pc* (-> arg0 current-options))
(not (-> s4-0 secrets-unlocked))
(= (-> arg0 option-index) 3)
)
(set! (-> arg0 option-index) 0)
0
)
)
(when (cpad-pressed? 0 confirm)
(logclear! (-> *cpad-list* cpads 0 button0-abs 0) (pad-buttons confirm))
(logclear! (-> *cpad-list* cpads 0 button0-rel 0) (pad-buttons confirm))
(cond
((= (-> this name) (text-id progress-exit-demo))
(case *kernel-boot-message*
(('demo-shared)
(set! *master-exit* 'force)
(set-master-mode 'game)
)
(('demo)
(set! (-> *game-info* mode) 'play)
(initialize! *game-info* 'game (the-as game-save #f) "title-restart" (the-as resetter-spec #f))
)
)
)
((= (-> this name) (text-id progress-continue-without-save))
(progress-intro-start)
)
((= (-> this next-state) 'back)
(pop-state arg0)
)
(else
(sound-play "generic-beep")
(push-state arg0)
(set-next-state arg0 (-> this next-state) 0)
)
)
)
0
)
(defmethod respond-progress ((this menu-exit-game-option) (arg0 progress) (selected? symbol))
"Handle progress menu navigation logic."
(let ((choice (&-> arg0 yes-no-choice))
(gp-0 #f)
)
(when selected?
(cond
((cpad-pressed? 0 left l-analog-left)
(when (not (-> choice 0))
(set! gp-0 #t)
(set! (-> choice 0) #t)
)
)
((cpad-pressed? 0 right l-analog-right)
(set! gp-0 (the symbol (-> choice 0)))
(set! (-> choice 0) #f)
)
((cpad-pressed? 0 confirm)
(if (-> choice 0)
(kernel-shutdown (the int (runtime-exit-status exit)))
)
)
)
)
(if gp-0
(sound-play "generic-beep")
)
)
0
)