summaryrefslogtreecommitdiff
path: root/soh/src/code
diff options
context:
space:
mode:
authoraMannus <mannusmenting@gmail.com>2023-06-02 03:40:10 +0200
committerGitHub <noreply@github.com>2023-06-01 21:40:10 -0400
commit2957dc61c37bb5f764a44d87951b8001724d2df7 (patch)
treeefe96966485706222eebb286dbb1552ddd45f580 /soh/src/code
parentfdf9086b2a900e0539f68952f01cc81fd7c6cd86 (diff)
[Feature] Boss Rush (#2923)
* Ganon(dorf) cutscene skips * Remove leftover code * Load into chamber of sages * Fix loading into chamber without fast file select * Boss warps in chamber done * Change warps back to chamber * Initial proof of concept done * ganon(dorf) cutscene skips * Code cleanup & auto age equipment * Gameplay stats timer + tweaks * Scuffed timer * Better timer * remove arena props + fix arena exits * Fix blue warps * Attempt to fix build * Fix build again * And again.. * Try no. 9001 * Handle dying and saving * Child link face fire medallion * Fix build * Fix warps after reset/death * Disable doors and move player spawns in boss rooms * Fix boss rush logo rendering * Start of ingame options menu * File Select cleanup * Fix build * Render char text PoC * Move functions to be more generic * Fix build * Fix other builds * Initial text scaling/kerning * Special characters prep * All special characters work now * Attempt to fix build * Fix build question mark * Finish all kerning * Start of ingame options menu with vertical scrolling * Barebones functional options menu * More options menu progress * More visual elements for options menu * Options menu visual changes, implement all options, tons of cleanup * Cleanup and comments * Shorter enums * More options * Change default heart count * Finish French translations * Implement timer in cosmetics editor * Uncomment timer requirement * Variable name change * German translation & small UI tweaks * Animated up/down arrows in options UI * Better arrows in options UI * Cleaner timer + make it usable for general gameplay * More cleanup + ganon & ganondorf boss option * Implement never heal option * Slight up arrow in options UI tweak * Add BGS option * Reintroduce ganondorf cutscene skip * Change encoding to UTF on bossrush.cpp * Fix build hopefully * Fixed static variables leading to options not properly resetting * Fix BR completed timestamp * Change timer to render on top of everything * Offset final BR time by 0.1 second from boss timestamps * Add missing check for boss rush * Implement soh_assets.h * Revert merge mistake * Fix special characters with UTF-8 * Fix build * here's the fix you can merge from your phone * Fix quest select crash with oot.otr only * Use OoT's kerning * Fix HD textures on options menu * Fix special character kerning * "Heal every boss" fixes * Seperate headers + bunny hood option * Remove GetUnixTimestamp() externing * Clean up extern "C"'s * Address review comments * Fix build question mark * Remove accidental styling change --------- Co-authored-by: briaguya <briaguya@alice>
Diffstat (limited to 'soh/src/code')
-rw-r--r--soh/src/code/z_kaleido_scope_call.c3
-rw-r--r--soh/src/code/z_kanfont.c4
-rw-r--r--soh/src/code/z_message_PAL.c4
-rw-r--r--soh/src/code/z_parameter.c88
-rw-r--r--soh/src/code/z_play.c3
-rw-r--r--soh/src/code/z_sram.c4
6 files changed, 97 insertions, 9 deletions
diff --git a/soh/src/code/z_kaleido_scope_call.c b/soh/src/code/z_kaleido_scope_call.c
index 5d1f6937d..6f0648e08 100644
--- a/soh/src/code/z_kaleido_scope_call.c
+++ b/soh/src/code/z_kaleido_scope_call.c
@@ -56,7 +56,8 @@ void KaleidoScopeCall_Update(PlayState* play) {
KaleidoMgrOverlay* kaleidoScopeOvl = &gKaleidoMgrOverlayTable[KALEIDO_OVL_KALEIDO_SCOPE];
PauseContext* pauseCtx = &play->pauseCtx;
- if (!gSaveContext.sohStats.gameComplete) {
+ if (!gSaveContext.sohStats.gameComplete &&
+ (!gSaveContext.isBossRush || !gSaveContext.isBossRushPaused)) {
gSaveContext.sohStats.pauseTimer++;
}
diff --git a/soh/src/code/z_kanfont.c b/soh/src/code/z_kanfont.c
index 2dd9cda80..217ef3c0a 100644
--- a/soh/src/code/z_kanfont.c
+++ b/soh/src/code/z_kanfont.c
@@ -177,6 +177,10 @@ void Font_LoadChar(Font* font, u8 character, u16 codePointIndex) {
memcpy(&font->charTexBuf[codePointIndex], fntTbl[character], strlen(fntTbl[character]) + 1);
}
+void* Font_FetchCharTexture(u8 character) {
+ return fntTbl[character];
+}
+
/**
* Loads a message box icon from message_static, such as the ending triangle/square or choice arrow into the
* icon buffer.
diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c
index 762e06b55..881637d8d 100644
--- a/soh/src/code/z_message_PAL.c
+++ b/soh/src/code/z_message_PAL.c
@@ -709,6 +709,10 @@ f32 sFontWidths[144] = {
14.0f, // ?
};
+f32 Message_GetCharacterWidth(unsigned char characterIndex) {
+ return sFontWidths[characterIndex] * (R_TEXT_CHAR_SCALE / 100.0f);
+}
+
u16 Message_DrawItemIcon(PlayState* play, u16 itemId, Gfx** p, u16 i) {
s32 pad;
Gfx* gfx = *p;
diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c
index 83bc7fc29..83066aff4 100644
--- a/soh/src/code/z_parameter.c
+++ b/soh/src/code/z_parameter.c
@@ -8,6 +8,8 @@
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
#include "libultraship/bridge.h"
#include "soh/Enhancements/gameplaystats.h"
+#include "soh/Enhancements/boss-rush/BossRushTypes.h"
+#include "soh/Enhancements/custom-message/CustomMessageInterfaceAddon.h"
#ifdef _MSC_VER
#include <stdlib.h>
@@ -882,7 +884,8 @@ void func_80083108(PlayState* play) {
Interface_ChangeAlpha(12);
}
}
- } else if (play->sceneNum == SCENE_KENJYANOMA) {
+ // Don't hide the HUD in the Chamber of Sages when in Boss Rush.
+ } else if (play->sceneNum == SCENE_KENJYANOMA && !gSaveContext.isBossRush) {
Interface_ChangeAlpha(1);
} else if (play->sceneNum == SCENE_TURIBORI) {
gSaveContext.unk_13E7 = 2;
@@ -4942,7 +4945,10 @@ void Interface_Draw(PlayState* play) {
PosX_RC = PosX_RC_ori;
}
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, rColor.r, rColor.g, rColor.b, interfaceCtx->magicAlpha);
- OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gRupeeCounterIconTex, 16, 16, PosX_RC, PosY_RC, 16, 16, 1 << 10, 1 << 10);
+ // Draw Rupee icon. Hide in Boss Rush.
+ if (!gSaveContext.isBossRush) {
+ OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gRupeeCounterIconTex, 16, 16, PosX_RC, PosY_RC, 16, 16, 1 << 10, 1 << 10);
+ }
switch (play->sceneNum) {
case SCENE_BMORI1:
@@ -5057,10 +5063,12 @@ void Interface_Draw(PlayState* play) {
svar2 = rupeeDigitsFirst[CUR_UPG_VALUE(UPG_WALLET)];
svar5 = rupeeDigitsCount[CUR_UPG_VALUE(UPG_WALLET)];
- for (svar1 = 0, svar3 = 16; svar1 < svar5; svar1++, svar2++, svar3 += 8) {
- OVERLAY_DISP =
- Gfx_TextureI8(OVERLAY_DISP, ((u8*)digitTextures[interfaceCtx->counterDigits[svar2]]), 8, 16,
- PosX_RC+svar3, PosY_RC, 8, 16, 1 << 10, 1 << 10);
+ // Draw Rupee Counter. Hide in Boss Rush.
+ if (!gSaveContext.isBossRush) {
+ for (svar1 = 0, svar3 = 16; svar1 < svar5; svar1++, svar2++, svar3 += 8) {
+ OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, ((u8*)digitTextures[interfaceCtx->counterDigits[svar2]]),
+ 8, 16, PosX_RC + svar3, PosY_RC, 8, 16, 1 << 10, 1 << 10);
+ }
}
}
else {
@@ -5983,7 +5991,8 @@ void Interface_Draw(PlayState* play) {
void Interface_DrawTotalGameplayTimer(PlayState* play) {
// Draw timer based on the Gameplay Stats total time.
- if (CVarGetInteger("gGameplayStats.ShowIngameTimer", 0) && gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2) {
+ if ((gSaveContext.isBossRush && gSaveContext.bossRushOptions[BR_OPTIONS_TIMER] == BR_CHOICE_TIMER_YES) ||
+ (CVarGetInteger("gGameplayStats.ShowIngameTimer", 0) && gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2)) {
s32 X_Margins_Timer = 0;
if (CVarGetInteger("gIGTUseMargins", 0) != 0) {
@@ -6065,6 +6074,8 @@ void Interface_DrawTotalGameplayTimer(PlayState* play) {
// Draw regular text. Change color based on if the timer is paused, running or the game is completed.
if (gSaveContext.sohStats.gameComplete) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 120, 255, 0, 255);
+ } else if (gSaveContext.isBossRushPaused) {
+ gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 150, 150, 150, 255);
} else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, 255);
}
@@ -6483,3 +6494,66 @@ void Interface_Update(PlayState* play) {
}
}
}
+
+void Interface_DrawTextCharacter(GraphicsContext* gfx, int16_t x, int16_t y, void* texture, uint16_t colorR,
+ uint16_t colorG, uint16_t colorB, uint16_t colorA, float textScale, uint8_t textShadow) {
+
+ int32_t scale = R_TEXT_CHAR_SCALE * textScale;
+ int32_t sCharTexSize = (scale / 100.0f) * 16.0f;
+ int32_t sCharTexScale = 1024.0f / (scale / 100.0f);
+
+ OPEN_DISPS(gfx);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPLoadTextureBlock_4b(POLY_OPA_DISP++, texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0,
+ G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+
+ if (textShadow) {
+ // Draw drop shadow
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0, 0, 0, colorA);
+ gSPTextureRectangle(POLY_OPA_DISP++, (x + R_TEXT_DROP_SHADOW_OFFSET) << 2, (y + R_TEXT_DROP_SHADOW_OFFSET) << 2,
+ (x + R_TEXT_DROP_SHADOW_OFFSET + sCharTexSize) << 2,
+ (y + R_TEXT_DROP_SHADOW_OFFSET + sCharTexSize) << 2, G_TX_RENDERTILE, 0, 0, sCharTexScale,
+ sCharTexScale);
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ // Draw normal text
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, colorR, colorG, colorB, colorA);
+ gSPTextureRectangle(POLY_OPA_DISP++, x << 2, y << 2, (x + sCharTexSize) << 2, (y + sCharTexSize) << 2,
+ G_TX_RENDERTILE, 0, 0, sCharTexScale, sCharTexScale);
+
+ CLOSE_DISPS(gfx);
+}
+
+uint16_t Interface_DrawTextLine(GraphicsContext* gfx, char text[], int16_t x, int16_t y, uint16_t colorR,
+ uint16_t colorG, uint16_t colorB, uint16_t colorA, float textScale, uint8_t textShadow) {
+
+ uint16_t textureIndex;
+ uint16_t kerningOffset = 0;
+ uint16_t lineOffset = 0;
+ void* texture;
+ const char* processedText = Interface_ReplaceSpecialCharacters(text);
+ uint8_t textLength = strlen(processedText);
+
+ for (uint16_t i = 0; i < textLength; i++) {
+ if (processedText[i] == '\n') {
+ lineOffset += 15 * textScale;
+ kerningOffset = 0;
+ } else {
+ textureIndex = processedText[i] - 32;
+
+ if (textureIndex != 0) {
+ texture = Font_FetchCharTexture(textureIndex);
+ Interface_DrawTextCharacter(gfx, x + kerningOffset, y + lineOffset, texture, colorR, colorG, colorB,
+ colorA, textScale, textShadow);
+ }
+ kerningOffset += (uint16_t)(Message_GetCharacterWidth(textureIndex) * textScale);
+ }
+ }
+
+ return kerningOffset;
+}
diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c
index 44e5442db..f4d0cdbe6 100644
--- a/soh/src/code/z_play.c
+++ b/soh/src/code/z_play.c
@@ -1170,7 +1170,8 @@ void Play_Update(PlayState* play) {
play->gameplayFrames++;
// Gameplay stat tracking
- if (!gSaveContext.sohStats.gameComplete) {
+ if (!gSaveContext.sohStats.gameComplete &&
+ (!gSaveContext.isBossRush || (gSaveContext.isBossRush && !gSaveContext.isBossRushPaused))) {
gSaveContext.sohStats.playTimer++;
gSaveContext.sohStats.sceneTimer++;
gSaveContext.sohStats.roomTimer++;
diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c
index 1735a2eb9..ce5651539 100644
--- a/soh/src/code/z_sram.c
+++ b/soh/src/code/z_sram.c
@@ -29,6 +29,10 @@ void Sram_InitDebugSave(void) {
Save_InitFile(true);
}
+void Sram_InitBossRushSave(void) {
+ Save_InitFile(false);
+}
+
/**
* Copy save currently on the buffer to Save Context and complete various tasks to open the save.
* This includes: