diff --git a/goal_src/jak3/pc/features/speedruns-h.gc b/goal_src/jak3/pc/features/speedruns-h.gc index 2c228bb8e0..8136a0ad45 100644 --- a/goal_src/jak3/pc/features/speedruns-h.gc +++ b/goal_src/jak3/pc/features/speedruns-h.gc @@ -87,6 +87,8 @@ ;; e.g. for All Open Orbs (Post Game) (post-game 4) (post-game-heromode 5) + (act-2-heromode 6) + (act-3-heromode 7) ;; TODO - add ILs and such later ;; there's no point in adding categories that just start from a new-game and have later restrictions ;; because we aren't going to modify the code to make that possible diff --git a/goal_src/jak3/pc/features/speedruns.gc b/goal_src/jak3/pc/features/speedruns.gc index 6bc2024628..eb7cc79136 100644 --- a/goal_src/jak3/pc/features/speedruns.gc +++ b/goal_src/jak3/pc/features/speedruns.gc @@ -143,8 +143,90 @@ lighteco darkeco)) -(defun reset-speedrunner-mode-hm-secrets! ((obj pc-settings-jak3)) - (set! (-> obj speedrunner-mode-hm-secrets) (the-as uint64 HERO_MODE_SECRETS)) +(defconstant ACT_2_SECRETS + (game-secrets board-fast ;; :avail-after (game-task-node desert-oasis-defense-resolution) + vehicle-fox ;; :avail-after (game-task-node desert-oasis-defense-introduction) + gun-upgrade-red-1 ;; :avail-after (game-task-node arena-fight-2-resolution) + gun-upgrade-red-2 ;; :avail-after (game-task-node arena-fight-3-resolution) + gun-upgrade-yellow-1 ;; :avail-after (game-task-node arena-fight-2-resolution) + gun-upgrade-yellow-2 ;; :avail-after (game-task-node arena-fight-3-resolution) + gun-upgrade-blue-1 ;; :avail-after (game-task-node arena-fight-3-resolution) + gun-upgrade-blue-2 ;; :avail-after (game-task-node mine-boss-resolution) + gun-upgrade-ammo-red ;; :avail-after (game-task-node arena-fight-3-resolution) + gun-upgrade-ammo-yellow ;; :avail-after (game-task-node arena-fight-3-resolution) + gun-upgrade-ammo-blue)) ;; :avail-after (game-task-node mine-boss-resolution) + +(defconstant ACT_3_SECRETS + (game-secrets unlimited-turbos ;; :avail-after (game-task-node factory-boss-resolution) + vehicle-hit-points ;; :avail-after (game-task-node nest-hunt-resolution) + board-fast + vehicle-fox + vehicle-mirage ;; :avail-after (game-task-node desert-artifact-race-2-resolution) + vehicle-x-ride ;; :avail-after (game-task-node desert-artifact-race-2-resolution) + darkjak-tracking ;; :avail-after (game-task-node city-destroy-darkeco-resolution) + gun-upgrade-red-1 + gun-upgrade-red-2 + gun-upgrade-red-3 ;; :avail-after (game-task-node city-gun-course-2-resolution) + gun-upgrade-yellow-1 + gun-upgrade-yellow-2 + gun-upgrade-yellow-3 ;; :avail-after (game-task-node city-gun-course-1-resolution) + gun-upgrade-blue-1 + gun-upgrade-blue-2 + gun-upgrade-blue-3 ;; :avail-after (game-task-node city-destroy-grid-resolution) + gun-upgrade-dark-1 ;; :avail-after (game-task-node city-blow-barricade-resolution) + gun-upgrade-ammo-red + gun-upgrade-ammo-yellow + gun-upgrade-ammo-blue + gun-upgrade-ammo-dark)) ;; :avail-after (game-task-node city-blow-barricade-resolution) + +(defconstant POST_GAME_SECRETS + (game-secrets endless-ammo ;; :avail-after (game-task-node desert-final-boss-resolution) + invulnerable ;; :avail-after (game-task-node desert-final-boss-resolution) + endless-dark ;; :avail-after (game-task-node desert-final-boss-resolution) + endless-light ;; :avail-after (game-task-node desert-final-boss-resolution) + unlimited-turbos + vehicle-hit-points + board-fast + vehicle-fox + vehicle-mirage + vehicle-x-ride + darkjak-tracking + button-invis ;; :avail-after (game-task-node desert-final-boss-resolution) + gun-upgrade-red-1 + gun-upgrade-red-2 + gun-upgrade-red-3 + gun-upgrade-yellow-1 + gun-upgrade-yellow-2 + gun-upgrade-yellow-3 + gun-upgrade-blue-1 + gun-upgrade-blue-2 + gun-upgrade-blue-3 + gun-upgrade-dark-1 + gun-upgrade-dark-2 ;; :avail-after (game-task-node temple-defend-resolution) + gun-upgrade-dark-3 ;; :avail-after (game-task-node city-blow-tower-resolution) + gun-upgrade-ammo-red + gun-upgrade-ammo-yellow + gun-upgrade-ammo-blue + gun-upgrade-ammo-dark)) + +(defun reset-speedrunner-mode-secrets! ((obj pc-settings-jak3) (cat speedrun-category)) + (case cat + (((speedrun-category newgame-heromode) (speedrun-category post-game-heromode) (speedrun-category act-2-heromode) (speedrun-category act-3-heromode)) + (set! (-> obj speedrunner-mode-hm-secrets) (the-as uint64 HERO_MODE_SECRETS))) + (((speedrun-category act-2)) + (set! (-> obj speedrunner-mode-act2-secrets) (the-as uint64 ACT_2_SECRETS))) + (((speedrun-category act-3)) + (set! (-> obj speedrunner-mode-act3-secrets) (the-as uint64 ACT_3_SECRETS))) + (((speedrun-category post-game)) + (set! (-> obj speedrunner-mode-postgame-secrets) (the-as uint64 POST_GAME_SECRETS))) + ) + (none)) + +(defun reset-speedrunner-mode-secrets-all! ((obj pc-settings-jak3)) + (reset-speedrunner-mode-secrets! obj (speedrun-category newgame-heromode)) + (reset-speedrunner-mode-secrets! obj (speedrun-category act-2)) + (reset-speedrunner-mode-secrets! obj (speedrun-category act-3)) + (reset-speedrunner-mode-secrets! obj (speedrun-category post-game)) (none)) (define-extern reset-arena-trainer-globals (function none)) @@ -187,10 +269,48 @@ (set! (-> *game-info* features) HERO_MODE_FEATURES)))) (((speedrun-category act-2)) (start 'play (get-continue-by-name *game-info* (play-task (game-task sewer-met-hum) 'debug 'play))) - (set-master-mode 'game)) + (set-master-mode 'game) + (set! (-> *game-info* secrets) (the-as game-secrets (-> *pc-settings* speedrunner-mode-act2-secrets))) + (set! (-> *game-info* purchase-secrets) (the-as game-secrets (-> *pc-settings* speedrunner-mode-act2-secrets)))) + (((speedrun-category act-2-heromode)) + (process-spawn-function process + (lambda :behavior process () + (set! (-> *game-info* mode) 'debug) + (initialize! *game-info* 'game (the game-save #f) (the string #f) (the resetter-spec #f)) + (set! (-> *game-info* mode) 'play) + (logior! (-> *game-info* secrets) (game-secrets hero-mode)) + (logior! (-> *game-info* purchase-secrets) (game-secrets hero-mode)) + (start 'play (get-continue-by-name *game-info* (play-task (game-task sewer-met-hum) 'debug 'play))) + (until (and *target* (!= (-> *target* next-state name) 'target-continue)) + (suspend)) + (mark-played! (-> *talker-speech* 138)) ;; prevent 600 orbs popup + (send-event *target* 'get-pickup (pickup-type skill) 1000.0) + (send-event *target* 'get-pickup (pickup-type gem) 1000.0) + (set! (-> *game-info* secrets) (the-as game-secrets (-> *pc-settings* speedrunner-mode-hm-secrets))) + (set! (-> *game-info* purchase-secrets) (the-as game-secrets (-> *pc-settings* speedrunner-mode-hm-secrets))) + (set! (-> *game-info* features) HERO_MODE_FEATURES)))) (((speedrun-category act-3)) (start 'play (get-continue-by-name *game-info* (play-task (game-task temple-defend) 'debug 'play))) - (set-master-mode 'game)) + (set-master-mode 'game) + (set! (-> *game-info* secrets) (the-as game-secrets (-> *pc-settings* speedrunner-mode-act3-secrets))) + (set! (-> *game-info* purchase-secrets) (the-as game-secrets (-> *pc-settings* speedrunner-mode-act3-secrets)))) + (((speedrun-category act-3-heromode)) + (process-spawn-function process + (lambda :behavior process () + (set! (-> *game-info* mode) 'debug) + (initialize! *game-info* 'game (the game-save #f) (the string #f) (the resetter-spec #f)) + (set! (-> *game-info* mode) 'play) + (logior! (-> *game-info* secrets) (game-secrets hero-mode)) + (logior! (-> *game-info* purchase-secrets) (game-secrets hero-mode)) + (start 'play (get-continue-by-name *game-info* (play-task (game-task temple-defend) 'debug 'play))) + (until (and *target* (!= (-> *target* next-state name) 'target-continue)) + (suspend)) + (mark-played! (-> *talker-speech* 138)) ;; prevent 600 orbs popup + (send-event *target* 'get-pickup (pickup-type skill) 1000.0) + (send-event *target* 'get-pickup (pickup-type gem) 1000.0) + (set! (-> *game-info* secrets) (the-as game-secrets (-> *pc-settings* speedrunner-mode-hm-secrets))) + (set! (-> *game-info* purchase-secrets) (the-as game-secrets (-> *pc-settings* speedrunner-mode-hm-secrets))) + (set! (-> *game-info* features) HERO_MODE_FEATURES)))) (((speedrun-category post-game)) (process-spawn-function process (lambda :behavior process () @@ -199,6 +319,10 @@ (set! (-> *game-info* mode) 'play) (task-close! "city-win-introduction") (start 'play (get-continue-by-name *game-info* "wascity-start")) + (until (and *target* (!= (-> *target* next-state name) 'target-continue)) + (suspend)) + (set! (-> *game-info* secrets) (the-as game-secrets (-> *pc-settings* speedrunner-mode-postgame-secrets))) + (set! (-> *game-info* purchase-secrets) (the-as game-secrets (-> *pc-settings* speedrunner-mode-postgame-secrets))) ))) (((speedrun-category post-game-heromode)) (process-spawn-function process @@ -386,6 +510,42 @@ (deactivate self))) (cam-master-activate-slave #f)) +(defmacro speedrun-get-secrets-length (secrets) + (with-gensyms (num-secrets) + `(let ((,num-secrets 0)) + (dotimes (i 64) + (when (logtest? ,secrets (shl 1 i)) ;; valid secret + (+! ,num-secrets 1))) + ,num-secrets))) + +(defmacro speedrun-secrets-confirm (full-secrets index settings-secrets) + (with-gensyms (num-secrets) + `(let ((,num-secrets 0)) + (dotimes (i 64) + (when (logtest? ,full-secrets (shl 1 i)) ;; valid secret + (when (= ,num-secrets ,index) ;; index-th valid secret + (logxor! ,settings-secrets (shl 1 i)) + (return (pc-settings-save))) + (+! ,num-secrets 1)))))) + +(defmacro speedrun-secrets-get-label (secrets index str-dest) + (with-gensyms (num-secrets) + `(let ((,num-secrets 0)) + (dotimes (i 64) + (when (logtest? ,secrets (shl 1 i)) ;; valid secret + (when (= ,num-secrets ,index) ;; index-th valid secret + (return (copy-string<-string ,str-dest (bitfield->string game-secrets i)))) + (+! ,num-secrets 1)))))) + +(defmacro speedrun-secrets-selected? (full-secrets index settings-secrets) + (with-gensyms (num-secrets) + `(let ((,num-secrets 0)) + (dotimes (i 64) + (when (logtest? ,full-secrets (shl 1 i)) ;; valid secret + (when (= ,num-secrets ,index) ;; index-th valid secret + (return (logtest? ,settings-secrets (shl 1 i)))) + (+! ,num-secrets 1)))))) + (define *speedrun-popup-menu-entries* (new 'static 'boxed-array @@ -433,6 +593,15 @@ :is-toggled? (lambda () (= (-> *speedrun-info* category) (speedrun-category act-2)))) + (new 'static + 'popup-menu-flag + :label "Act 2 Hero Mode" + :on-confirm + (lambda () + (set-category! *speedrun-info* (speedrun-category act-2-heromode))) + :is-toggled? + (lambda () + (= (-> *speedrun-info* category) (speedrun-category act-2-heromode)))) (new 'static 'popup-menu-flag :label "Act 3" @@ -442,6 +611,15 @@ :is-toggled? (lambda () (= (-> *speedrun-info* category) (speedrun-category act-3)))) + (new 'static + 'popup-menu-flag + :label "Act 3 Hero Mode" + :on-confirm + (lambda () + (set-category! *speedrun-info* (speedrun-category act-3-heromode))) + :is-toggled? + (lambda () + (= (-> *speedrun-info* category) (speedrun-category act-3-heromode)))) (new 'static 'popup-menu-flag :label "Post-Game" @@ -470,25 +648,94 @@ (lambda () (= (-> *speedrun-info* category) (speedrun-category all-cheats-allowed)))))) (new 'static - 'popup-menu-dynamic-submenu - :label "Select Hero Mode secrets" - :get-length - (lambda () - 58) - :get-entry-label - (lambda ((index int) (str-dest string)) - (copy-string<-string str-dest (bitfield->string game-secrets index))) - :on-entry-confirm - (lambda ((index int)) - (logxor! (-> *pc-settings* speedrunner-mode-hm-secrets) (shl 1 index)) - (pc-settings-save)) - :entry-selected? - (lambda ((index int)) - (logtest? (-> *pc-settings* speedrunner-mode-hm-secrets) (shl 1 index))) - :on-reset - (lambda () - (reset-speedrunner-mode-hm-secrets! *pc-settings*) - (pc-settings-save))) + 'popup-menu-submenu + :label "Select Secrets" + :entries + (new 'static + 'boxed-array + :type + popup-menu-entry + (new 'static + 'popup-menu-dynamic-submenu + :label "Hero Mode Categories" + :get-length + (lambda () + 58) ;; (gun-upgrade-ammo-dark 57) last one to show + :get-entry-label + (lambda ((index int) (str-dest string)) + (copy-string<-string str-dest (bitfield->string game-secrets index))) + :on-entry-confirm + (lambda ((index int)) + (logxor! (-> *pc-settings* speedrunner-mode-hm-secrets) (shl 1 index)) + (pc-settings-save)) + :entry-selected? + (lambda ((index int)) + (logtest? (-> *pc-settings* speedrunner-mode-hm-secrets) (shl 1 index))) + :on-reset + (lambda () + (reset-speedrunner-mode-secrets! *pc-settings* (speedrun-category newgame-heromode)) + (pc-settings-save))) + (new 'static + 'popup-menu-dynamic-submenu + :label "Act 2" + :get-length + (lambda () + (speedrun-get-secrets-length ACT_2_SECRETS)) + :get-entry-label + (lambda ((index int) (str-dest string)) + (speedrun-secrets-get-label ACT_2_SECRETS index str-dest)) + :on-entry-confirm + (lambda ((index int)) + (speedrun-secrets-confirm ACT_2_SECRETS index (-> *pc-settings* speedrunner-mode-act2-secrets))) + :entry-selected? + (lambda ((index int)) + (speedrun-secrets-selected? ACT_2_SECRETS index (-> *pc-settings* speedrunner-mode-act2-secrets))) + :on-reset + (lambda () + (reset-speedrunner-mode-secrets! *pc-settings* (speedrun-category act-2)) + (pc-settings-save)) + ) + (new 'static + 'popup-menu-dynamic-submenu + :label "Act 3" + :get-length + (lambda () + (speedrun-get-secrets-length ACT_3_SECRETS)) + :get-entry-label + (lambda ((index int) (str-dest string)) + (speedrun-secrets-get-label ACT_3_SECRETS index str-dest)) + :on-entry-confirm + (lambda ((index int)) + (speedrun-secrets-confirm ACT_3_SECRETS index (-> *pc-settings* speedrunner-mode-act3-secrets))) + :entry-selected? + (lambda ((index int)) + (speedrun-secrets-selected? ACT_3_SECRETS index (-> *pc-settings* speedrunner-mode-act3-secrets))) + :on-reset + (lambda () + (reset-speedrunner-mode-secrets! *pc-settings* (speedrun-category act-3)) + (pc-settings-save)) + ) + (new 'static + 'popup-menu-dynamic-submenu + :label "Post-Game" + :get-length + (lambda () + (speedrun-get-secrets-length POST_GAME_SECRETS)) + :get-entry-label + (lambda ((index int) (str-dest string)) + (speedrun-secrets-get-label POST_GAME_SECRETS index str-dest)) + :on-entry-confirm + (lambda ((index int)) + (speedrun-secrets-confirm POST_GAME_SECRETS index (-> *pc-settings* speedrunner-mode-postgame-secrets))) + :entry-selected? + (lambda ((index int)) + (speedrun-secrets-selected? POST_GAME_SECRETS index (-> *pc-settings* speedrunner-mode-postgame-secrets))) + :on-reset + (lambda () + (reset-speedrunner-mode-secrets! *pc-settings* (speedrun-category post-game)) + (pc-settings-save)) + ) + )) (new 'static 'popup-menu-dynamic-submenu :label "Custom Category Select" diff --git a/goal_src/jak3/pc/pckernel-impl.gc b/goal_src/jak3/pc/pckernel-impl.gc index bf28c88aa9..bf57ea3e10 100644 --- a/goal_src/jak3/pc/pckernel-impl.gc +++ b/goal_src/jak3/pc/pckernel-impl.gc @@ -112,6 +112,9 @@ (pacman-dpad? symbol) (speedrunner-mode-custom-bind uint32) (speedrunner-mode-hm-secrets uint64) + (speedrunner-mode-act2-secrets uint64) + (speedrunner-mode-act3-secrets uint64) + (speedrunner-mode-postgame-secrets uint64) (memcard-subtitles? symbol) @@ -201,7 +204,7 @@ (set! (-> obj subtitle-speaker?) 'auto) 0) -(define-extern reset-speedrunner-mode-hm-secrets! (function pc-settings-jak3 none)) +(define-extern reset-speedrunner-mode-secrets-all! (function pc-settings-jak3 none)) (defmethod reset-extra ((obj pc-settings-jak3) (call-handlers symbol)) "Set the default goodies settings" @@ -217,7 +220,7 @@ (dotimes (i 6) (set! (-> obj flava-unlocked i) #f)) - (reset-speedrunner-mode-hm-secrets! obj) + (reset-speedrunner-mode-secrets-all! obj) ;(set! (-> obj stats) *statistics*) 0) diff --git a/goal_src/jak3/pc/pckernel.gc b/goal_src/jak3/pc/pckernel.gc index cf2d1d0964..e61ca25450 100644 --- a/goal_src/jak3/pc/pckernel.gc +++ b/goal_src/jak3/pc/pckernel.gc @@ -678,6 +678,9 @@ ) ) (("speedrunner-mode-hm-secrets") (set! (-> obj speedrunner-mode-hm-secrets) (file-stream-read-int file))) + (("speedrunner-mode-act2-secrets") (set! (-> obj speedrunner-mode-act2-secrets) (file-stream-read-int file))) + (("speedrunner-mode-act3-secrets") (set! (-> obj speedrunner-mode-act3-secrets) (file-stream-read-int file))) + (("speedrunner-mode-postgame-secrets") (set! (-> obj speedrunner-mode-postgame-secrets) (file-stream-read-int file))) ;; (("stats") ;; (dosettings (file) @@ -733,6 +736,9 @@ (format file ")~%") (format file " (speedrunner-mode-hm-secrets #x~x)~%" (-> obj speedrunner-mode-hm-secrets)) + (format file " (speedrunner-mode-act2-secrets #x~x)~%" (-> obj speedrunner-mode-act2-secrets)) + (format file " (speedrunner-mode-act3-secrets #x~x)~%" (-> obj speedrunner-mode-act3-secrets)) + (format file " (speedrunner-mode-postgame-secrets #x~x)~%" (-> obj speedrunner-mode-postgame-secrets)) ;; (format file " (stats~%") ;; (format file " (kill-stats~%")