mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
g/j2: Implement speedrunner mode in jak 2 (#2976)
This commit is contained in:
parent
d784561d43
commit
d701a54c43
|
@ -1124,8 +1124,46 @@ static std::vector<ReplaceInfo> s_replace_info_jak2 = {
|
|||
{"~Y~-6Hº~Z~+10H", "°"},
|
||||
|
||||
// Color / Emphasis
|
||||
{"~[~0L", "<COLOR_DEFAULT>"},
|
||||
{"~[~1L", "<COLOR_WHITE>"},
|
||||
{"~[~32L", "<COLOR_DEFAULT>"}};
|
||||
{"~[~2L", "<COLOR_TRANSPARENT>"},
|
||||
{"~[~3L", "<COLOR_RED>"},
|
||||
{"~[~4L", "<COLOR_ORANGE>"},
|
||||
{"~[~5L", "<COLOR_YELLOW>"},
|
||||
{"~[~6L", "<COLOR_GREEN>"},
|
||||
{"~[~7L", "<COLOR_BLUE>"},
|
||||
{"~[~8L", "<COLOR_CYAN>"},
|
||||
{"~[~9L", "<COLOR_PINK>"},
|
||||
{"~[~10L", "<COLOR_MENU-SELECTED>"},
|
||||
{"~[~11L", "<COLOR_MENU-SELECTED-PARENT>"},
|
||||
{"~[~12L", "<COLOR_MENU>"},
|
||||
{"~[~13L", "<COLOR_MENU-PARENT>"},
|
||||
{"~[~14L", "<COLOR_MENU-FUNC-BAD>"},
|
||||
{"~[~15L", "<COLOR_MENU-FLAG-ON>"},
|
||||
{"~[~16L", "<COLOR_MENU-FLAG-ON-PARENT>"},
|
||||
{"~[~17L", "<COLOR_MENU-FLAG-OFF>"},
|
||||
{"~[~18L", "<COLOR_MENU-FLAG-OFF-PARENT>"},
|
||||
{"~[~19L", "<COLOR_MENU-INVALID>"},
|
||||
{"~[~20L", "<COLOR_FLAT-YELLOW>"},
|
||||
{"~[~21L", "<COLOR_COLOR-21>"},
|
||||
{"~[~22L", "<COLOR_PAD-BACK>"},
|
||||
{"~[~23L", "<COLOR_PAD-SHINE>"},
|
||||
{"~[~24L", "<COLOR_PAD-SQUARE>"},
|
||||
{"~[~25L", "<COLOR_PAD-CIRCLE>"},
|
||||
{"~[~26L", "<COLOR_PAD-TRIANGLE>"},
|
||||
{"~[~27L", "<COLOR_PAD-CROSS>"},
|
||||
{"~[~28L", "<COLOR_PROGRESS-OLD-BLUE>"},
|
||||
{"~[~29L", "<COLOR_PROGRESS-OLD-YELLOW>"},
|
||||
{"~[~30L", "<COLOR_PROGRESS-OLD-SELECTED>"},
|
||||
{"~[~31L", "<COLOR_PROGRESS-OLD-PERCENT>"},
|
||||
{"~[~32L", "<COLOR_PROGRESS>"},
|
||||
{"~[~33L", "<COLOR_PROGRESS-SELECTED>"},
|
||||
{"~[~34L", "<COLOR_PROGRESS-FORCE-SELECTED>"},
|
||||
{"~[~35L", "<COLOR_PROGRESS-OPTION-OFF>"},
|
||||
{"~[~36L", "<COLOR_COLOR-36>"},
|
||||
{"~[~37L", "<COLOR_CREDITS-STAFF-TITLE-1>"},
|
||||
{"~[~38L", "<COLOR_CREDITS-STAFF-TITLE-2>"},
|
||||
{"~[~39L", "<COLOR_COLOR-39>"}};
|
||||
|
||||
static std::vector<EncodeInfo> s_encode_info_jak2 = {
|
||||
{"ˇ", {0x10}}, // caron
|
||||
|
|
|
@ -292,7 +292,7 @@ void InitIOP() {
|
|||
}
|
||||
}
|
||||
|
||||
AutoSplitterBlock gAutoSplitterBlock;
|
||||
AutoSplitterBlock g_auto_splitter_block_jak1;
|
||||
|
||||
/*!
|
||||
* Initialize GOAL Runtime. This is the main initialization which is called before entering
|
||||
|
@ -357,7 +357,8 @@ int InitMachine() {
|
|||
}
|
||||
|
||||
// TODO - better place to put this?
|
||||
gAutoSplitterBlock.pointer_to_symbol =
|
||||
// TODO - yes, see jak2's code!
|
||||
g_auto_splitter_block_jak1.pointer_to_symbol =
|
||||
(u64)g_ee_main_mem + intern_from_c("*autosplit-info-jak1*")->value;
|
||||
|
||||
lg::info("InitListenerConnect");
|
||||
|
|
|
@ -45,5 +45,5 @@ struct AutoSplitterBlock {
|
|||
const char marker[20] = "UnLiStEdStRaTs_JaK1";
|
||||
u64 pointer_to_symbol = 0;
|
||||
};
|
||||
extern AutoSplitterBlock gAutoSplitterBlock;
|
||||
extern AutoSplitterBlock g_auto_splitter_block_jak1;
|
||||
} // namespace jak1
|
||||
|
|
|
@ -362,7 +362,8 @@ void InitIOP() {
|
|||
}
|
||||
printf("InitIOP OK\n");
|
||||
}
|
||||
AutoSplitterBlock gAutoSplitterBlock;
|
||||
|
||||
AutoSplitterBlock g_auto_splitter_block_jak2;
|
||||
|
||||
int InitMachine() {
|
||||
// heap_start = malloc(0x10);
|
||||
|
@ -662,7 +663,7 @@ void pc_set_levels(u32 lev_list) {
|
|||
}
|
||||
|
||||
void init_autosplit_struct() {
|
||||
gAutoSplitterBlock.pointer_to_symbol =
|
||||
g_auto_splitter_block_jak2.pointer_to_symbol =
|
||||
(u64)g_ee_main_mem + (u64)intern_from_c("*autosplit-info-jak2*")->value();
|
||||
}
|
||||
|
||||
|
@ -741,6 +742,12 @@ inline u64 bool_to_symbol(const bool val) {
|
|||
// return bool_to_symbol(false);
|
||||
//}
|
||||
|
||||
void encode_utf8_string(u32 src_str_ptr, u32 str_dest_ptr) {
|
||||
auto str = std::string(Ptr<String>(src_str_ptr).c()->data());
|
||||
std::string converted = get_font_bank(GameTextVersion::JAK2)->convert_utf8_to_game(str);
|
||||
strcpy(Ptr<String>(str_dest_ptr).c()->data(), converted.c_str());
|
||||
}
|
||||
|
||||
void InitMachine_PCPort() {
|
||||
// PC Port added functions
|
||||
init_common_pc_port_functions(
|
||||
|
@ -756,6 +763,7 @@ void InitMachine_PCPort() {
|
|||
make_function_symbol_from_c("__pc-set-levels", (void*)pc_set_levels);
|
||||
make_function_symbol_from_c("__pc-get-tex-remap", (void*)lookup_jak2_texture_dest_offset);
|
||||
make_function_symbol_from_c("pc-init-autosplitter-struct", (void*)init_autosplit_struct);
|
||||
make_function_symbol_from_c("pc-encode-utf8-string", (void*)encode_utf8_string);
|
||||
|
||||
// discord rich presence
|
||||
make_function_symbol_from_c("pc-discord-rpc-update", (void*)update_discord_rpc);
|
||||
|
|
|
@ -111,6 +111,6 @@ struct AutoSplitterBlock {
|
|||
u64 pointer_to_symbol = 0;
|
||||
};
|
||||
|
||||
extern AutoSplitterBlock gAutoSplitterBlock;
|
||||
extern AutoSplitterBlock g_auto_splitter_block_jak2;
|
||||
|
||||
} // namespace jak2
|
||||
|
|
|
@ -157,7 +157,7 @@
|
|||
(initialize! *game-info* 'game (the-as game-save #f) "jungle-start")
|
||||
)
|
||||
(((speedrun-category il-misty))
|
||||
;; spawn at start of misty
|
||||
;; spawn at start of misty
|
||||
(initialize! *game-info* 'game (the-as game-save #f) "misty-start")
|
||||
)
|
||||
(((speedrun-category il-firecanyon))
|
||||
|
@ -240,7 +240,7 @@
|
|||
(set! (-> *setting-control* default auto-save) #t)
|
||||
(none)
|
||||
)
|
||||
|
||||
|
||||
(defun setup-speedrun-post-blackout ()
|
||||
(when (and (-> *speedrun-info* needs-post-blackout-setup?) (>= (-> *display* base-frame-counter) (-> *game-info* blackout-time)))
|
||||
(set! (-> *speedrun-info* needs-post-blackout-setup?) #f)
|
||||
|
|
|
@ -295,8 +295,7 @@
|
|||
(update-discord-rpc obj)
|
||||
|
||||
;; update auto-splitter info
|
||||
(when (-> *pc-settings* speedrunner-mode?)
|
||||
(update-speedrun obj))
|
||||
(update-speedrun obj)
|
||||
|
||||
(when (not (-> obj use-vis?))
|
||||
(update-video-hacks obj)
|
||||
|
|
|
@ -292,7 +292,7 @@
|
|||
|
||||
(defmethod update-speedrun pc-settings-jak1 ((obj pc-settings-jak1))
|
||||
"update speedrun module"
|
||||
(with-profiler "speedrun-update-jak1"
|
||||
(with-profiler "speedrun-update"
|
||||
(speedrun-mode-update))
|
||||
(none))
|
||||
|
||||
|
|
|
@ -238,8 +238,8 @@
|
|||
"settings.o"
|
||||
"autosplit-h.o" ;; added
|
||||
"autosplit.o" ;; added
|
||||
"popup-menu-h.o" ;; added
|
||||
"speedruns-h.o" ;; added
|
||||
"speedruns.o" ;; added
|
||||
"mood-tables.o"
|
||||
"mood-tables2.o"
|
||||
"mood.o"
|
||||
|
@ -327,6 +327,8 @@
|
|||
"board-states.o"
|
||||
"mech-h.o"
|
||||
"menu.o"
|
||||
"popup-menu.o" ;; added
|
||||
"speedruns.o" ;; added
|
||||
"drawable.o"
|
||||
"drawable-group.o"
|
||||
"drawable-inline-array.o"
|
||||
|
|
|
@ -1778,7 +1778,9 @@ auto-save-post
|
|||
)
|
||||
(suspend)
|
||||
)
|
||||
(activate-progress *dproc* 'icon-info)
|
||||
;; og:preserve-this Disable the auto-save prompt in speedrunner mode, we get it
|
||||
(when (not (-> *pc-settings* speedrunner-mode?))
|
||||
(activate-progress *dproc* 'icon-info))
|
||||
(while *progress-process*
|
||||
(suspend)
|
||||
)
|
||||
|
|
|
@ -922,6 +922,8 @@
|
|||
;; draw and update menus
|
||||
(with-profiler 'menu-hook *profile-menu-hook-color*
|
||||
(*menu-hook*)
|
||||
(when *speedrun-menu*
|
||||
(draw! (-> *speedrun-menu* 0)))
|
||||
)
|
||||
|
||||
;; load text files as needed from the menu update
|
||||
|
|
|
@ -3308,6 +3308,31 @@
|
|||
)
|
||||
:want-sound (new 'static 'array symbol 3 'ctywide1 'forexit1 'forexit2)
|
||||
)
|
||||
;; og:preserve-this Added to enable fast-game-starts with hero mode
|
||||
(new 'static 'continue-point
|
||||
:name "game-start-hero"
|
||||
:level 'prison
|
||||
:flags (continue-flags game-start hero-mode)
|
||||
:trans (new 'static 'vector :x 1942413.2 :y 34479.31 :z 275525.62 :w 1.0)
|
||||
:quat (new 'static 'vector :y 0.4562 :w 0.8898)
|
||||
:camera-trans (new 'static 'vector :x 1921090.8 :y 53425.766 :z 237949.75 :w 1.0)
|
||||
:camera-rot (new 'static 'inline-array vector3s 3
|
||||
(new 'static 'vector3s :data (new 'static 'array float 3 0.869 0.0 -0.4947))
|
||||
(new 'static 'vector3s :data (new 'static 'array float 3 0.0663 0.9909 0.1165))
|
||||
(new 'static 'vector3s :data (new 'static 'array float 3 0.4903 -0.134 0.8611))
|
||||
)
|
||||
:on-goto #f
|
||||
:vis-nick 'prison
|
||||
:want (new 'static 'inline-array level-buffer-state 6
|
||||
(new 'static 'level-buffer-state :name 'prison :display? 'display :force-vis? #f :force-inside? #f)
|
||||
(new 'static 'level-buffer-state :name 'forexita :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 'ctywide1 'forexit1 'forexit2)
|
||||
)
|
||||
(new 'static 'continue-point
|
||||
:name "prison-intro-start"
|
||||
:level 'prison
|
||||
|
@ -15698,4 +15723,4 @@
|
|||
(cons! *level-load-list* 'teststdd)
|
||||
(cons! *level-load-list* 'wasall)
|
||||
(cons! *level-load-list* 'stadocc)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -293,6 +293,14 @@
|
|||
)
|
||||
(cond
|
||||
((logtest? (-> arg0 flags) (continue-flags game-start))
|
||||
;; og:preserve-this Added to make fast-game-start work with hero-mode
|
||||
(when (logtest? (-> arg0 flags) (continue-flags hero-mode))
|
||||
(logior! (-> self game secrets) (game-secrets hero-mode))
|
||||
(logior! (-> self game purchase-secrets) (game-secrets hero-mode))
|
||||
;; TODO - there might be a better way to do this, the way hero-mode is set kinda feels like a side-effect
|
||||
;; `update-task-masks` gets called during the `intro-start-hero` via `setting-control::apply-settings`
|
||||
;; Which runs the following line if hero-mode is enabled
|
||||
(set! (-> *game-info* features) (game-feature gun gun-yellow gun-red gun-blue gun-dark)))
|
||||
(case *kernel-boot-message*
|
||||
(('kiosk)
|
||||
(let ((s5-5 (ppointer->handle (auto-save-command 'restore 0 0 *default-pool* #f))))
|
||||
|
|
|
@ -86,15 +86,22 @@
|
|||
arg0
|
||||
)
|
||||
|
||||
(defun progress-intro-start ((arg0 symbol))
|
||||
(defun progress-intro-start ((hero-mode? symbol))
|
||||
(set! (-> *game-info* mode) 'play)
|
||||
(if arg0
|
||||
(initialize! *game-info* 'game (the-as game-save #f) "intro-start-hero")
|
||||
(initialize! *game-info* 'game (the-as game-save #f) "intro-start")
|
||||
)
|
||||
(cond
|
||||
;; Start a new game differently if speedrunning mode is active
|
||||
((= (-> *pc-settings* speedrunner-mode?) #t)
|
||||
(if hero-mode?
|
||||
(set-category! *speedrun-info* (speedrun-category newgame-heromode))
|
||||
(set-category! *speedrun-info* (speedrun-category newgame-normal)))
|
||||
(start-run! *speedrun-info*))
|
||||
;; start the game normally
|
||||
(else
|
||||
(if hero-mode?
|
||||
(initialize! *game-info* 'game (the-as game-save #f) "intro-start-hero")
|
||||
(initialize! *game-info* 'game (the-as game-save #f) "intro-start"))))
|
||||
(set-master-mode 'game)
|
||||
0
|
||||
)
|
||||
0)
|
||||
|
||||
(defmethod init-defaults progress ((obj progress))
|
||||
"Initialize default menu settings."
|
||||
|
|
|
@ -220,6 +220,8 @@
|
|||
(define-extern pc-is-imgui-visible? (function symbol))
|
||||
(define-extern pc-rand (function int))
|
||||
|
||||
(define-extern pc-encode-utf8-string (function string string none))
|
||||
|
||||
;; Used to dump fixture data for the editor, re-enable end-to-end if you need it
|
||||
;; (define-extern has-level-been-dumped-lights? (function string symbol))
|
||||
;; (define-extern has-level-been-dumped-regions? (function string symbol))
|
||||
|
|
|
@ -809,6 +809,8 @@
|
|||
)
|
||||
)
|
||||
|
||||
(define *pc-encoded-temp-string* (new 'global 'string 2048 (the-as string #f)))
|
||||
|
||||
(kmemclose)
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
;;
|
||||
;; DO NOT change the order, appending to the end is safe!
|
||||
|
||||
(deftype autosplit-info-jak2 (structure)
|
||||
(deftype autosplit-info (structure)
|
||||
(;; Version Info
|
||||
(version-major uint16)
|
||||
(version-minor uint16)
|
||||
|
@ -127,8 +127,9 @@
|
|||
(res-stadium-burning-bush-race-class1-r uint8)
|
||||
;; TODO - orbs in level X
|
||||
;; end marker just to make things look nice in a memory view
|
||||
(end-marker uint8 4)))
|
||||
(end-marker uint8 4))
|
||||
(:methods
|
||||
(reset! (_type_) none)
|
||||
(update! (_type_) none)))
|
||||
|
||||
(define-extern *autosplit-info-jak2* autosplit-info-jak2)
|
||||
(define-extern update-autosplit-info-jak2 (function none))
|
||||
(define-extern update-autosplit-jak2-new-game (function none))
|
||||
(define-extern *autosplit-info-jak2* autosplit-info)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
;;-*-Lisp-*-
|
||||
(in-package goal)
|
||||
|
||||
(define *autosplit-info-jak2* (new 'static 'autosplit-info-jak2))
|
||||
(define *autosplit-info-jak2* (new 'static 'autosplit-info))
|
||||
(pc-init-autosplitter-struct)
|
||||
;; Setup Version
|
||||
(set! (-> *autosplit-info-jak2* version-major) 0)
|
||||
|
@ -14,16 +14,14 @@
|
|||
|
||||
(defmacro autosplit-flag-task-complete! (field-name task-name)
|
||||
"Given a field name in the autosplitter struct, and a [[game-task]] name to check, sets either a 0 or a 1"
|
||||
`(set! (-> *autosplit-info-jak2* ,field-name) (if (task-complete? *game-info* (game-task ,task-name)) 1 0)))
|
||||
`(set! (-> this ,field-name) (if (task-complete? *game-info* (game-task ,task-name)) 1 0)))
|
||||
|
||||
(defun update-autosplit-info-jak2 ()
|
||||
(defmethod update! autosplit-info ((this autosplit-info))
|
||||
;; general statistics
|
||||
(set! (-> *autosplit-info-jak2* num-orbs) (the int (-> *game-info* skill-total)))
|
||||
(set! (-> *autosplit-info-jak2* num-skullgems) (the int (-> *game-info* gem-total)))
|
||||
|
||||
(set! (-> this num-orbs) (the int (-> *game-info* skill-total)))
|
||||
(set! (-> this num-skullgems) (the int (-> *game-info* gem-total)))
|
||||
;; loading/cutscene related flags
|
||||
(set! (-> *autosplit-info-jak2* in-cutscene?) (if (movie?) 1 0))
|
||||
|
||||
(set! (-> this in-cutscene?) (if (movie?) 1 0))
|
||||
;; need resolution flags
|
||||
(autosplit-flag-task-complete! res-fortress-escape fortress-escape)
|
||||
(autosplit-flag-task-complete! res-city-help-kid city-help-kid)
|
||||
|
@ -129,10 +127,9 @@
|
|||
(autosplit-flag-task-complete! res-stadium-burning-bush-race-class3-r stadium-burning-bush-race-class3-r)
|
||||
(autosplit-flag-task-complete! res-stadium-burning-bush-race-class2-r stadium-burning-bush-race-class2-r)
|
||||
(autosplit-flag-task-complete! res-stadium-burning-bush-race-class1-r stadium-burning-bush-race-class1-r)
|
||||
|
||||
(none))
|
||||
|
||||
|
||||
(defun update-autosplit-jak2-new-game ()
|
||||
(set! (-> *autosplit-info-jak2* game-hash) (pc-get-unix-timestamp))
|
||||
(defmethod reset! autosplit-info ((this autosplit-info))
|
||||
(set! (-> this game-hash) (pc-get-unix-timestamp))
|
||||
(none))
|
||||
|
|
|
@ -5,32 +5,41 @@
|
|||
(defenum speedrun-category
|
||||
:type uint32
|
||||
;; Main Categories
|
||||
(full-game 0) ;; Full game run (any category for now, can repurpose as Any% if we split them out later)
|
||||
;; (full-game-100 1) ;; 100%
|
||||
;; (full-game-allMission 2) ;; All Missions
|
||||
|
||||
;; Individual Levels
|
||||
(il-placeholder1 100) ;; Geyser Rock IL
|
||||
(il-placeholdere3 101) ;; Sandover Village IL
|
||||
(il-placeholder3 102) ;; Sentinel Beach IL
|
||||
|
||||
|
||||
;; Extension Categories (TBD)
|
||||
(newgame-normal 0)
|
||||
(newgame-heromode 1)
|
||||
;; 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
|
||||
;; ie. removing mars tomb skip if you pick "all missions"
|
||||
)
|
||||
|
||||
(deftype speedrun-info (structure)
|
||||
((category speedrun-category)
|
||||
(display-run-info? symbol))
|
||||
(:methods
|
||||
(set-category! (_type_ speedrun-category) none)
|
||||
(start-run! (_type_) none)
|
||||
(enforce-settings! (_type_) none)
|
||||
(hide-run-info! (_type_) none)
|
||||
(update! (_type_) none)
|
||||
(draw-run-info! (_type_) none)))
|
||||
|
||||
(deftype speedrun-info-jak2 (structure)
|
||||
(
|
||||
(category speedrun-category)
|
||||
(needs-post-blackout-setup? symbol)
|
||||
(should-display? symbol)
|
||||
)
|
||||
)
|
||||
(define-extern *speedrun-info* speedrun-info)
|
||||
|
||||
(define-extern start-speedrun (function speedrun-category none))
|
||||
(define-extern is-speedrun-category? (function symbol symbol))
|
||||
(define-extern hide-speedrun-display (function none))
|
||||
(define-extern speedrun-start-full-game-run (function none))
|
||||
(define-extern setup-speedrun-post-blackout (function none))
|
||||
(define-extern speedrun-mode-update (function none))
|
||||
(define-extern speedrun-draw-settings (function none))
|
||||
(defenum speedrun-menu-command
|
||||
:type uint32
|
||||
(reset 0)
|
||||
(exit 1))
|
||||
|
||||
(deftype speedrun-menu (process-drawable)
|
||||
((popup-menu popup-menu)
|
||||
(draw-menu? symbol)
|
||||
(ignore-menu-toggle? symbol))
|
||||
(:methods
|
||||
(draw! (_type_) none))
|
||||
(:states
|
||||
idle))
|
||||
|
||||
(define-extern *speedrun-popup-menu* popup-menu)
|
||||
(define-extern *speedrun-menu* (pointer speedrun-menu))
|
||||
(define-extern speedrun-menu-init (function none :behavior speedrun-menu))
|
||||
|
|
|
@ -1,87 +1,160 @@
|
|||
;;-*-Lisp-*-
|
||||
(in-package goal)
|
||||
|
||||
(define *speedrun-info* (new 'static 'speedrun-info-jak2 :should-display? #t :needs-post-blackout-setup? #f))
|
||||
(define *speedrun-info* (new 'static 'speedrun-info))
|
||||
|
||||
(defun is-speedrun-category? ((category symbol))
|
||||
(and (-> *pc-settings* speedrunner-mode?)
|
||||
(name= category (enum->string speedrun-category (-> *speedrun-info* category)))
|
||||
)
|
||||
)
|
||||
(defmethod set-category! speedrun-info ((this speedrun-info) (category speedrun-category))
|
||||
(set! (-> this category) category)
|
||||
(none))
|
||||
|
||||
(defun start-speedrun ((category speedrun-category))
|
||||
(defmethod start-run! speedrun-info ((this speedrun-info))
|
||||
;; randomize game id so the autosplitter knows to restart
|
||||
(update-autosplit-jak2-new-game)
|
||||
;; turn on speedrun verification display and flip flag for setting up speedrun after initialize!
|
||||
(set! (-> *speedrun-info* should-display?) #t)
|
||||
;; start new game with specified checkpoint, if any (otherwise we're resetting current category)
|
||||
(when category
|
||||
(set! (-> *speedrun-info* category) category))
|
||||
;; TODO - ensure any required settings are enabled
|
||||
(set-frame-rate! *pc-settings* 60 #t)
|
||||
(none)
|
||||
)
|
||||
(reset! *autosplit-info-jak2*)
|
||||
;; turn on speedrun verification display
|
||||
(set! (-> this display-run-info?) #t)
|
||||
;; ensure any required settings are enabled
|
||||
(enforce-settings! this)
|
||||
;; finalize any category specific setup code
|
||||
(case (-> this category)
|
||||
(((speedrun-category newgame-normal))
|
||||
(initialize! *game-info* 'game (the-as game-save #f) "game-start"))
|
||||
(((speedrun-category newgame-heromode))
|
||||
(initialize! *game-info* 'game (the-as game-save #f) "game-start-hero")))
|
||||
;; enable auto saving by default, no downside on PC
|
||||
;; this has to come after the `initialize!` call as it sets it to false!
|
||||
(set! (-> *setting-control* user-default auto-save) #t)
|
||||
(none))
|
||||
|
||||
;; TODO - fix me
|
||||
(define post-blackout? #f)
|
||||
(defmethod enforce-settings! speedrun-info ((this speedrun-info))
|
||||
(set! (-> *pc-settings* ps2-actor-vis?) #t) ;; force PS2 actor visibility
|
||||
(set-frame-rate! *pc-settings* 60 #t) ;; force FPS to `60`
|
||||
(set! (-> *pc-settings* cheats) (the-as pc-cheats #x0)) ;; disable any active cheats
|
||||
(none))
|
||||
|
||||
(defun setup-speedrun-post-blackout ()
|
||||
(when post-blackout?
|
||||
(set! (-> *speedrun-info* needs-post-blackout-setup?) #f)
|
||||
(case (-> *speedrun-info* category)
|
||||
(((speedrun-category full-game))
|
||||
;; setup a full-game run here
|
||||
(none)
|
||||
)
|
||||
(else
|
||||
;;speedrun-category was not recognized, print an error to the screen and maybe play a sound.
|
||||
)
|
||||
)
|
||||
;; reset speedrun display (gets hidden on first collectable pickup)
|
||||
(set! (-> *speedrun-info* should-display?) #t)
|
||||
;; reset actors to ensure any above changes take effect
|
||||
(reset-actors 'life)
|
||||
;; autosave any changes back to file
|
||||
(auto-save-command 'auto-save 0 0 *default-pool* #f)
|
||||
)
|
||||
(none)
|
||||
)
|
||||
(defmethod hide-run-info! speedrun-info ((this speedrun-info))
|
||||
(set! (-> this display-run-info?) #f)
|
||||
(none))
|
||||
|
||||
(defun hide-speedrun-display ()
|
||||
(set! (-> *speedrun-info* should-display?) #f)
|
||||
(none)
|
||||
)
|
||||
|
||||
(defun speedrun-mode-update ()
|
||||
(defmethod update! speedrun-info ((this speedrun-info))
|
||||
"A per frame update for speedrunning related stuff"
|
||||
;; Ensure the speedrunner menu process is enabled or destroyed
|
||||
(when (and (-> *pc-settings* speedrunner-mode?)
|
||||
(not *speedrun-menu*))
|
||||
(process-spawn speedrun-menu :init speedrun-menu-init #f :to *entity-pool*))
|
||||
(when (and (not (-> *pc-settings* speedrunner-mode?))
|
||||
*speedrun-menu*)
|
||||
(deactivate (-> *speedrun-menu* 0)))
|
||||
;; do speedrunner mode things
|
||||
(when (-> *pc-settings* speedrunner-mode?)
|
||||
;; Update auto-splitter
|
||||
(update-autosplit-info-jak2)
|
||||
;; Draw info to the screen
|
||||
(speedrun-draw-settings)
|
||||
;;Disable any active cheats
|
||||
;; (set! (-> *pc-settings* cheats) (the-as pc-cheats #x0))
|
||||
;; Run after-blackout speedrun setup (if needed)
|
||||
(setup-speedrun-post-blackout)
|
||||
)
|
||||
;; Update auto-splitter struct
|
||||
(update! *autosplit-info-jak2*)
|
||||
;; see if we should stop drawing the run info (when you escape the fortress!)
|
||||
(when (task-complete? *game-info* (game-task fortress-escape))
|
||||
(set! (-> this display-run-info?) #f))
|
||||
(when (-> this display-run-info?)
|
||||
;; Draw info to the screen
|
||||
(draw-run-info! this))
|
||||
;; enforce settings even if they've changed them
|
||||
(enforce-settings! this))
|
||||
(none))
|
||||
|
||||
(defun speedrun-start-full-game-run ()
|
||||
;; start a full game speedrun, save file is already selected so don't default to first slot
|
||||
(start-speedrun (speedrun-category full-game))
|
||||
(none))
|
||||
|
||||
(defun speedrun-draw-settings ()
|
||||
(defmethod draw-run-info! speedrun-info ((this speedrun-info))
|
||||
"Draw speedrun related settings in the bottom left corner"
|
||||
(when (and (-> *pc-settings* speedrunner-mode?)
|
||||
(not (paused?))
|
||||
(-> *speedrun-info* should-display?))
|
||||
(with-dma-buffer-add-bucket ((buf (-> (current-frame) global-buf))
|
||||
(bucket-id debug-no-zbuf1))
|
||||
(draw-string-xy (string-format "OpenGOAL Version: ~S ~%Speedrun mode: ~A ~%Category: ~S ~%Is fortress escaped: ~D"
|
||||
*pc-settings-built-sha*
|
||||
(-> *pc-settings* speedrunner-mode?)
|
||||
(enum->string speedrun-category (-> *speedrun-info* category))
|
||||
(-> *autosplit-info-jak2* res-fortress-escape))
|
||||
buf 0 (- 220 (* 8 4)) (font-color progress-old-yellow) (font-flags shadow kerning))))
|
||||
(-> this display-run-info?))
|
||||
(clear *temp-string*)
|
||||
(format *temp-string* "<COLOR_WHITE>PC Cheats: <COLOR_GREEN>~D~%<COLOR_WHITE>Frame Rate: <COLOR_GREEN>~D~%<COLOR_WHITE>PS2 Actor Vis?: <COLOR_GREEN>~S~%<COLOR_WHITE>Version: <COLOR_GREEN>~S~%"
|
||||
(the-as int (-> *pc-settings* cheats))
|
||||
(-> *pc-settings* target-fps)
|
||||
(if (-> *pc-settings* ps2-actor-vis?) "true" "false")
|
||||
*pc-settings-built-sha*)
|
||||
(pc-encode-utf8-string *temp-string* *pc-encoded-temp-string*)
|
||||
(with-dma-buffer-add-bucket ((buf (-> (current-frame) global-buf)) (bucket-id debug-no-zbuf1))
|
||||
(let ((font-ctx (new 'stack 'font-context *font-default-matrix* 510 375 0.0 (font-color default) (font-flags right shadow kerning large))))
|
||||
(set! (-> font-ctx scale) 0.325)
|
||||
(draw-string-adv *pc-encoded-temp-string* buf font-ctx))))
|
||||
(none))
|
||||
|
||||
;; Speedrun Menu
|
||||
|
||||
(define *speedrun-popup-menu*
|
||||
(new 'static 'popup-menu
|
||||
:entries (new 'static 'boxed-array :type popup-menu-entry
|
||||
(new 'static 'popup-menu-button :label "Reset" :on-press (lambda () (send-event (ppointer->process *speedrun-menu*) 'invoke (speedrun-menu-command reset))))
|
||||
(new 'static 'popup-menu-button :label "Exit" :on-press (lambda () (send-event (ppointer->process *speedrun-menu*) 'invoke (speedrun-menu-command exit))))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(define *speedrun-menu* (the-as (pointer speedrun-menu) #f))
|
||||
|
||||
(defbehavior speedrun-menu-init speedrun-menu ()
|
||||
(set! *speedrun-menu* (the-as (pointer speedrun-menu) (process->ppointer self)))
|
||||
(set! (-> *speedrun-menu* 0 popup-menu) *speedrun-popup-menu*)
|
||||
(set! (-> *speedrun-menu* 0 draw-menu?) #f)
|
||||
(set! (-> *speedrun-menu* 0 ignore-menu-toggle?) #f)
|
||||
(go idle)
|
||||
(none))
|
||||
|
||||
(defmethod deactivate speedrun-menu ((this speedrun-menu))
|
||||
(set! *speedrun-menu* (the-as (pointer speedrun-menu) #f))
|
||||
((method-of-type process-drawable deactivate) this)
|
||||
(none))
|
||||
|
||||
(defstate idle (speedrun-menu)
|
||||
:event (behavior ((proc process) (arg1 int) (event-type symbol) (event event-message-block))
|
||||
(case event-type
|
||||
(('invoke)
|
||||
(case (-> event param 0)
|
||||
(((speedrun-menu-command reset))
|
||||
(start-run! *speedrun-info*))
|
||||
(((speedrun-menu-command exit))
|
||||
(set-master-mode 'game)
|
||||
(set! (-> self draw-menu?) #f))
|
||||
(else
|
||||
(format 0 "nyi: invoke ~D~%" (-> event param 0))))))
|
||||
(the-as object 0))
|
||||
:trans (behavior ()
|
||||
(none))
|
||||
:code (behavior ()
|
||||
(until #f (suspend) )
|
||||
(none))
|
||||
:post (behavior ()
|
||||
(none)))
|
||||
|
||||
(defmethod draw! speedrun-menu ((this speedrun-menu))
|
||||
;; handle opening and closing the menu
|
||||
;; allow the menu to be toggled again once one of the currents is released
|
||||
(when (and (-> this ignore-menu-toggle?)
|
||||
(or (not (cpad-hold? 0 l1)) (not (cpad-hold? 0 r1)) (not (cpad-hold? 0 select))))
|
||||
(set! (-> this ignore-menu-toggle?) #f))
|
||||
(when (and (cpad-hold? 0 l1) (cpad-hold? 0 r1) (cpad-hold? 0 select)
|
||||
(not (-> this ignore-menu-toggle?)))
|
||||
(cond
|
||||
((= *master-mode* 'game)
|
||||
(set-master-mode 'menu)
|
||||
(set! (-> this draw-menu?) #t))
|
||||
((= *master-mode* 'menu)
|
||||
(set-master-mode 'game)
|
||||
(set! (-> this draw-menu?) #f)))
|
||||
(logclear! (-> *cpad-list* cpads 0 button0-abs 0) (pad-buttons l1))
|
||||
(logclear! (-> *cpad-list* cpads 0 button0-rel 0) (pad-buttons l1))
|
||||
(logclear! (-> *cpad-list* cpads 0 button0-abs 0) (pad-buttons r1))
|
||||
(logclear! (-> *cpad-list* cpads 0 button0-rel 0) (pad-buttons r1))
|
||||
(logclear! (-> *cpad-list* cpads 0 button0-abs 0) (pad-buttons select))
|
||||
(logclear! (-> *cpad-list* cpads 0 button0-rel 0) (pad-buttons select))
|
||||
(set! (-> this ignore-menu-toggle?) #t))
|
||||
(when (-> this draw-menu?)
|
||||
;; handle any inputs for within the menu
|
||||
(cond
|
||||
((cpad-pressed? 0 triangle select)
|
||||
(set! (-> this draw-menu?) #f))
|
||||
((cpad-pressed? 0 up)
|
||||
(move-up! (-> this popup-menu)))
|
||||
((cpad-pressed? 0 down)
|
||||
(move-down! (-> this popup-menu)))
|
||||
((cpad-pressed? 0 x)
|
||||
(press! (-> this popup-menu))))
|
||||
;; draw it
|
||||
(draw! (-> this popup-menu)))
|
||||
(none))
|
||||
|
|
|
@ -161,15 +161,17 @@
|
|||
(set! (-> info time-of-day) (-> *time-of-day-context* time))
|
||||
(set! (-> info percent-complete) (calculate-percentage *game-info*))
|
||||
(set! (-> info focus-status) (if *target* (-> *target* focus-status) 0))
|
||||
;; TODO - wrapping in `with-profiler` causes an error, fix it
|
||||
;; TODO - update to new with-profiler syntax
|
||||
(pc-discord-rpc-update info)
|
||||
)
|
||||
(none))
|
||||
|
||||
(defmethod update-speedrun pc-settings-jak2 ((obj pc-settings-jak2))
|
||||
"update speedrun module"
|
||||
(when (-> *pc-settings* speedrunner-mode?)
|
||||
(speedrun-mode-update))
|
||||
;; TODO - update to new with-profiler syntax
|
||||
;; (with-profiler "speedrun-update"
|
||||
(update! *speedrun-info*)
|
||||
;;)
|
||||
(none))
|
||||
|
||||
(defmethod update-video-hacks pc-settings-jak2 ((obj pc-settings-jak2))
|
||||
|
|
25
goal_src/jak2/pc/util/popup-menu-h.gc
Normal file
25
goal_src/jak2/pc/util/popup-menu-h.gc
Normal file
|
@ -0,0 +1,25 @@
|
|||
;;-*-Lisp-*-
|
||||
(in-package goal)
|
||||
|
||||
;; A debug-menu style popup menu, a lightweight way to make a context menu that doesn't involve the progress code
|
||||
;; and isn't debug-only
|
||||
;;
|
||||
;; Currently only supports a single 1-level menu of buttons, add more features as required
|
||||
|
||||
(deftype popup-menu-entry (basic)
|
||||
((label string)
|
||||
(on-press (function none)))
|
||||
(:methods
|
||||
(draw! (_type_ font-context dma-buffer) none)))
|
||||
|
||||
(deftype popup-menu-button (popup-menu-entry) ())
|
||||
|
||||
(deftype popup-menu (basic)
|
||||
((entries (array popup-menu-entry))
|
||||
(curr-entry-index int32))
|
||||
(:methods
|
||||
(draw! (_type_) none)
|
||||
(move-up! (_type_) none)
|
||||
(move-down! (_type_) none)
|
||||
(press! (_type_) none)
|
||||
(get-widest-label (_type_ font-context) float)))
|
61
goal_src/jak2/pc/util/popup-menu.gc
Normal file
61
goal_src/jak2/pc/util/popup-menu.gc
Normal file
|
@ -0,0 +1,61 @@
|
|||
;;-*-Lisp-*-
|
||||
(in-package goal)
|
||||
|
||||
(defmethod draw! popup-menu-entry ((this popup-menu-entry) (font-ctx font-context) (dma-buf dma-buffer))
|
||||
(none))
|
||||
|
||||
(defmethod draw! popup-menu-button ((this popup-menu-button) (font-ctx font-context) (dma-buf dma-buffer))
|
||||
(let ((old-x (-> font-ctx origin x))
|
||||
(old-y (-> font-ctx origin y)))
|
||||
(pc-encode-utf8-string (-> this label) *pc-encoded-temp-string*)
|
||||
(draw-string-adv *pc-encoded-temp-string* dma-buf font-ctx)
|
||||
(set! (-> font-ctx origin x) old-x)
|
||||
(set! (-> font-ctx origin y) old-y))
|
||||
(none))
|
||||
|
||||
(defmethod draw! popup-menu ((this popup-menu))
|
||||
(let ((font-ctx (new 'debug 'font-context *font-default-matrix* 0 0 0.0 (font-color default) (font-flags shadow kerning large))))
|
||||
(set! (-> font-ctx scale) 0.35)
|
||||
(set! (-> font-ctx origin x) 15.0)
|
||||
(set! (-> font-ctx origin y) 75.0)
|
||||
(with-dma-buffer-add-bucket ((buf (-> (current-frame) global-buf)) (bucket-id debug-no-zbuf1))
|
||||
;; background border
|
||||
(draw-sprite2d-xy buf 6 64
|
||||
(+ 17 (the int (get-widest-label this font-ctx))) ;; width
|
||||
(+ 17 (* 15 (-> this entries length))) ;; height
|
||||
(new 'static 'rgba :r 255 :g 255 :b 255 :a 75))
|
||||
;; background
|
||||
(draw-sprite2d-xy buf 7 65
|
||||
(+ 15 (the int (get-widest-label this font-ctx))) ;; width
|
||||
(+ 15 (* 15 (-> this entries length))) ;; height
|
||||
(new 'static 'rgba :r 0 :g 0 :b 0 :a 255))
|
||||
;; menu contents
|
||||
(dotimes (i (-> this entries length))
|
||||
(if (= i (-> this curr-entry-index))
|
||||
(set! (-> font-ctx color) (font-color cyan))
|
||||
(set! (-> font-ctx color) (font-color default)))
|
||||
(draw! (-> this entries i) font-ctx buf)
|
||||
(set! (-> font-ctx origin y) (+ 15.0 (-> font-ctx origin y)))))
|
||||
)
|
||||
(none))
|
||||
|
||||
(defmethod move-up! popup-menu ((this popup-menu))
|
||||
(set! (-> this curr-entry-index) (max 0 (dec (-> this curr-entry-index))))
|
||||
(none))
|
||||
|
||||
(defmethod move-down! popup-menu ((this popup-menu))
|
||||
(set! (-> this curr-entry-index) (min (dec (-> this entries length)) (inc (-> this curr-entry-index))))
|
||||
(none))
|
||||
|
||||
(defmethod press! popup-menu ((this popup-menu))
|
||||
(let ((entry (-> this entries (-> this curr-entry-index))))
|
||||
((-> entry on-press)))
|
||||
(none))
|
||||
|
||||
(defmethod get-widest-label popup-menu ((this popup-menu) (font-ctx font-context))
|
||||
(let ((max-len 0.0))
|
||||
(dotimes (i (-> this entries length))
|
||||
(let ((label-len (-> (get-string-length (-> this entries i label) font-ctx) length)))
|
||||
(when (> label-len max-len)
|
||||
(set! max-len label-len))))
|
||||
max-len))
|
Loading…
Reference in a new issue