From d98111737bcd362918ce97f1e8e0e85138eb0323 Mon Sep 17 00:00:00 2001 From: "lzehetgruber@mailbox.org" Date: Sat, 11 Mar 2023 17:10:46 +0100 Subject: [PATCH] pb-system: add ranks --- src/game/hud.c | 21 +++++++++++++- src/game/ingame_menu.c | 23 +++++++++++++++ src/game/print.c | 64 ++++++++++++++++++++++++++++++++++++++++++ src/game/print.h | 51 +++++++++++++++++++++++++++++++++ 4 files changed, 158 insertions(+), 1 deletion(-) diff --git a/src/game/hud.c b/src/game/hud.c index 268a30f9..fc6d35ad 100644 --- a/src/game/hud.c +++ b/src/game/hud.c @@ -345,6 +345,19 @@ void render_hud_timer(u16 timeInFrames, u8 timerIdx, const char *prefix, u32 dis gSPDisplayList(gDisplayListHead++, dl_hud_img_end); } +/** + * Displays a rank in the top-left + */ +void render_hud_rank(struct RankDisplay rank, u8 timerIdx, u32 distFromLeftEdge, const char *prefix, + u32 prefixLength) { + s32 yPos; + char rankStr[2] = { '\0', '\0' }; + rankStr[0] = rank.asChar; + yPos = 184 - get_y_pos(timerIdx); + print_text(GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(distFromLeftEdge), yPos, prefix); + print_text(GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(distFromLeftEdge + prefixLength), yPos, rankStr); +} + /** * Sets HUD status camera value depending of the actions * defined in update_camera_status. @@ -454,8 +467,14 @@ void render_hud(void) { best_time = save_file_get_best_time(COURSE_NUM_TO_INDEX(gCurrCourseNum), gTimer.collectedStarId); render_hud_timer(best_time, 1, "PB", 120); + render_hud_rank(time_to_rank(gTimer.time, COURSE_NUM_TO_INDEX(gCurrCourseNum), + gTimer.collectedStarId), + 0, 10, "RANK", 60); + render_hud_rank(time_to_rank(best_time, COURSE_NUM_TO_INDEX(gCurrCourseNum), + gTimer.collectedStarId), + 1, 35, "PB", 35); } - } else if (hudDisplayFlags & HUD_DISPLAY_FLAG_TIMER) { + } else if (hudDisplayFlags & HUD_DISPLAY_FLAG_PSS_TIMER) { char *prefix; u32 distFromRightEdge; #ifdef VERSION_EU diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index e9314fc9..b764129d 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -2216,8 +2216,20 @@ u8 gTextCourse[][7] = { void render_scores_hud_lut(u8 courseIndex) { int i; + u8 rankText[2] = { 0xFF, 0xFF }; print_hud_my_sob(courseIndex, 178, 103); print_hud_my_score_stars(gCurrSaveFileNum - 1, courseIndex, 118, 103); + for (i = 0; i < 7; i++) { + const s16 x = 30 + i * 40; + const s16 y = 32; + if (save_file_best_time_exists(courseIndex, i)) { + rankText[0] = time_to_rank(save_file_get_best_time(courseIndex, i), courseIndex, i) + .asU8; // TODO use couseIndex or num everywhere + } else { + rankText[0] = RANK_NONE_2; + } + print_hud_lut_string(HUD_LUT_GLOBAL, x, y, rankText); + } } void render_pause_scores(void) { @@ -2479,6 +2491,7 @@ void print_hud_pause_colorful_str(void) { void render_pause_castle_course_stars(s16 x, s16 y, s16 fileIndex, s16 courseIndex) { u16 starIdx = 0; u8 starStr[COURSE_STAGES_COUNT * 2]; + u8 rankStr[NUM_SCORES_PER_STAGE * 3]; u8 starFlags = save_file_get_star_flags(fileIndex, courseIndex); @@ -2488,13 +2501,23 @@ void render_pause_castle_course_stars(s16 x, s16 y, s16 fileIndex, s16 courseInd } else { starStr[starIdx * 2] = DIALOG_CHAR_STAR_OPEN; } + if (save_file_best_time_exists(courseIndex, starIdx)) { + rankStr[starIdx * 3] = + time_to_rank(save_file_get_best_time(courseIndex, starIdx), courseIndex, starIdx).asU8; + } else { + rankStr[starIdx * 3] = RANK_NONE; + } starStr[starIdx * 2 + 1] = DIALOG_CHAR_SPACE; + rankStr[starIdx * 3 + 1] = DIALOG_CHAR_SPACE; + rankStr[starIdx * 3 + 2] = DIALOG_CHAR_SPACE; } starStr[starIdx * 2] = DIALOG_CHAR_TERMINATOR; + rankStr[starIdx * 3] = DIALOG_CHAR_TERMINATOR; print_generic_string(x + 5, y, starStr); + print_generic_string(x + 3, y - 16, rankStr); } u8 hudDialogApostrophe[] = { 0x3E, 0xFF }; diff --git a/src/game/print.c b/src/game/print.c index c1b3b7b5..04ca6f44 100644 --- a/src/game/print.c +++ b/src/game/print.c @@ -6,6 +6,7 @@ #include "memory.h" #include "print.h" #include "segment2.h" +#include "course_table.h" /** * This file handles printing and formatting the colorful text that @@ -469,3 +470,66 @@ struct TimerDisplay frames_to_display_time(u16 timeInFrames) { t.fracSecs = timerFracSecs; return t; } + +// Hardcoded Rank Definitions +u32 course_idx_to_rank_idx_map[2][2] = { { COURSE_NUM_TO_INDEX(1) /*COURSE_BOB*/, 1 }, + { COURSE_NUM_TO_INDEX(2) /*COURSE_WF*/, 2 } }; + +u32 course_idx_to_rank_idx(u32 courseIdx) { + u32 i; + for (i = 0; i < sizeof(course_idx_to_rank_idx_map) / sizeof(course_idx_to_rank_idx_map[0]); i++) { + if (courseIdx == course_idx_to_rank_idx_map[i][0]) { + return course_idx_to_rank_idx_map[i][1]; + } + } + return 0; +} + +short rank_times[3][7][4] = { + // fallback + { { _40s(0), _40s(0), _40s(0), _40s(0) }, + { _40s(0), _40s(0), _40s(0), _40s(0) }, + { _40s(0), _40s(0), _40s(0), _40s(0) }, + { _40s(0), _40s(0), _40s(0), _40s(0) }, + { _40s(0), _40s(0), _40s(0), _40s(0) }, + { _40s(0), _40s(0), _40s(0), _40s(0) }, + { _40s(0), _40s(0), _40s(0), _40s(0) } }, + // level 1 + { { _7s(6), _8s(0), _10s(20), _12s(0) }, + { _4s(22), _6s(0), _8s(0), _10s(0) }, + { _7s(28), _8s(0), _9s(0), _12s(0) }, + { _14s(27), _16s(0), _20s(0), _25s(0) }, + { _20s(0), _22s(0), _25s(0), _30s(0) }, + { _30s(0), _32s(0), _35s(0), _40s(0) }, + { _25s(0), _28s(0), _30s(0), _35s(0) } }, + // level 2 + { { _1s(0), _10s(0), _20s(0), _30s(0) }, + { _1s(0), _10s(0), _20s(0), _30s(0) }, + { _1s(0), _10s(0), _20s(0), _30s(0) }, + { _1s(0), _10s(0), _20s(0), _30s(0) }, + { _1s(0), _10s(0), _20s(0), _30s(0) }, + { _1s(0), _10s(0), _20s(0), _30s(0) }, + { _1s(0), _10s(0), _20s(0), _30s(0) } } +}; + +struct RankDisplay time_to_rank(u16 timeInFrames, s16 courseIdx, s8 starId) { + struct RankDisplay rank; + short *scores = rank_times[course_idx_to_rank_idx(courseIdx)][starId]; + if (timeInFrames < scores[0]) { + rank.asChar = 'S'; + rank.asU8 = 0x1C; + } else if (timeInFrames < scores[1]) { + rank.asChar = 'A'; + rank.asU8 = 0x0A; + } else if (timeInFrames < scores[2]) { + rank.asChar = 'B'; + rank.asU8 = 0x0B; + } else if (timeInFrames < scores[3]) { + rank.asChar = 'C'; + rank.asU8 = 0x0C; + } else { + rank.asChar = 'D'; + rank.asU8 = 0x0D; + } + return rank; +} diff --git a/src/game/print.h b/src/game/print.h index 8323eade..5b6e72f1 100644 --- a/src/game/print.h +++ b/src/game/print.h @@ -25,16 +25,67 @@ #define GLYPH_DOUBLE_QUOTE 57 #define GLYPH_UMLAUT 58 +#define FPS 30 +#define _1s(frames) (FPS * 1 + frames) +#define _2s(frames) (FPS * 2 + frames) +#define _3s(frames) (FPS * 3 + frames) +#define _4s(frames) (FPS * 4 + frames) +#define _5s(frames) (FPS * 5 + frames) +#define _6s(frames) (FPS * 6 + frames) +#define _7s(frames) (FPS * 7 + frames) +#define _8s(frames) (FPS * 8 + frames) +#define _9s(frames) (FPS * 9 + frames) +#define _10s(frames) (FPS * 10 + frames) +#define _11s(frames) (FPS * 11 + frames) +#define _12s(frames) (FPS * 12 + frames) +#define _13s(frames) (FPS * 13 + frames) +#define _14s(frames) (FPS * 14 + frames) +#define _15s(frames) (FPS * 15 + frames) +#define _16s(frames) (FPS * 16 + frames) +#define _17s(frames) (FPS * 17 + frames) +#define _18s(frames) (FPS * 18 + frames) +#define _19s(frames) (FPS * 19 + frames) +#define _20s(frames) (FPS * 20 + frames) +#define _21s(frames) (FPS * 21 + frames) +#define _22s(frames) (FPS * 22 + frames) +#define _23s(frames) (FPS * 23 + frames) +#define _24s(frames) (FPS * 24 + frames) +#define _25s(frames) (FPS * 25 + frames) +#define _26s(frames) (FPS * 26 + frames) +#define _27s(frames) (FPS * 27 + frames) +#define _28s(frames) (FPS * 28 + frames) +#define _29s(frames) (FPS * 29 + frames) +#define _30s(frames) (FPS * 30 + frames) +#define _31s(frames) (FPS * 31 + frames) +#define _32s(frames) (FPS * 32 + frames) +#define _33s(frames) (FPS * 33 + frames) +#define _34s(frames) (FPS * 34 + frames) +#define _35s(frames) (FPS * 35 + frames) +#define _36s(frames) (FPS * 36 + frames) +#define _37s(frames) (FPS * 37 + frames) +#define _38s(frames) (FPS * 38 + frames) +#define _39s(frames) (FPS * 39 + frames) +#define _40s(frames) (FPS * 40 + frames) + +#define RANK_NONE 0x9F +#define RANK_NONE_2 GLYPH_MULTIPLY + struct TimerDisplay { u16 mins; u16 secs; u16 fracSecs; }; +struct RankDisplay { + char asChar; + u8 asU8; +}; + void print_text_fmt_int(s32 x, s32 y, const char *str, s32 n); void print_text(s32 x, s32 y, const char *str); void print_text_centered(s32 x, s32 y, const char *str); void render_text_labels(void); struct TimerDisplay frames_to_display_time(u16 timeInFrames); +struct RankDisplay time_to_rank(u16 timeInFrames, s16 courseIdx, s8 starId); #endif // PRINT_H