summaryrefslogtreecommitdiff
path: root/soh/src/code
diff options
context:
space:
mode:
authoraMannus <mannusmenting@gmail.com>2023-05-31 00:57:45 +0200
committerGitHub <noreply@github.com>2023-05-30 18:57:45 -0400
commitb25e4d4f260735c5b61ad2971d3efd13834ccaa7 (patch)
tree65faf6a70df81261b0b878c93a30519cd1564ceb /soh/src/code
parente8eaac4d77a3751a463bdc4991d51c931a21698a (diff)
[Feature] In-game gameplay stats timer (#2910)
* Implement in-game gameplay stats timer * Change timer to render on top of everything
Diffstat (limited to 'soh/src/code')
-rw-r--r--soh/src/code/z_parameter.c102
-rw-r--r--soh/src/code/z_play.c2
2 files changed, 104 insertions, 0 deletions
diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c
index 5092dc79e..83bc7fc29 100644
--- a/soh/src/code/z_parameter.c
+++ b/soh/src/code/z_parameter.c
@@ -7,6 +7,7 @@
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
#include "libultraship/bridge.h"
+#include "soh/Enhancements/gameplaystats.h"
#ifdef _MSC_VER
#include <stdlib.h>
@@ -5979,6 +5980,107 @@ void Interface_Draw(PlayState* play) {
CLOSE_DISPS(play->state.gfxCtx);
}
+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) {
+
+ s32 X_Margins_Timer = 0;
+ if (CVarGetInteger("gIGTUseMargins", 0) != 0) {
+ if (CVarGetInteger("gIGTPosType", 0) == 0) {
+ X_Margins_Timer = Left_HUD_Margin;
+ };
+ }
+ s32 rectLeftOri = OTRGetRectDimensionFromLeftEdge(24 + X_Margins_Timer);
+ s32 rectTopOri = 73;
+ if (CVarGetInteger("gIGTPosType", 0) != 0) {
+ rectTopOri = (CVarGetInteger("gIGTPosY", 0));
+ if (CVarGetInteger("gIGTPosType", 0) == 1) { // Anchor Left
+ if (CVarGetInteger("gIGTUseMargins", 0) != 0) {
+ X_Margins_Timer = Left_HUD_Margin;
+ };
+ rectLeftOri = OTRGetRectDimensionFromLeftEdge(CVarGetInteger("gIGTPosX", 0) + X_Margins_Timer);
+ } else if (CVarGetInteger("gIGTPosType", 0) == 2) { // Anchor Right
+ if (CVarGetInteger("gIGTUseMargins", 0) != 0) {
+ X_Margins_Timer = Right_HUD_Margin;
+ };
+ rectLeftOri = OTRGetRectDimensionFromRightEdge(CVarGetInteger("gIGTPosX", 0) + X_Margins_Timer);
+ } else if (CVarGetInteger("gIGTPosType", 0) == 3) { // Anchor None
+ rectLeftOri = CVarGetInteger("gIGTPosX", 0) + 204 + X_Margins_Timer;
+ } else if (CVarGetInteger("gIGTPosType", 0) == 4) { // Hidden
+ rectLeftOri = -9999;
+ }
+ }
+
+ s32 rectLeft;
+ s32 rectTop;
+ s32 rectWidth = 8;
+ s32 rectHeightOri = 16;
+ s32 rectHeight;
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ gDPSetCombineLERP(OVERLAY_DISP++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0,
+ PRIMITIVE, 0);
+
+ gDPSetOtherMode(OVERLAY_DISP++,
+ G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_IA16 | G_TL_TILE |
+ G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
+ G_AC_NONE | G_ZS_PRIM | G_RM_XLU_SURF | G_RM_XLU_SURF2);
+
+ char* totalTimeText = GameplayStats_GetCurrentTime();
+ char* textPointer = &totalTimeText[0];
+ uint8_t textLength = strlen(textPointer);
+ uint16_t textureIndex = 0;
+
+ for (uint16_t i = 0; i < textLength; i++) {
+ if (totalTimeText[i] == ':' || totalTimeText[i] == '.') {
+ textureIndex = 10;
+ } else {
+ textureIndex = totalTimeText[i] - 48;
+ }
+
+ rectLeft = rectLeftOri + (i * 8);
+ rectTop = rectTopOri;
+ rectHeight = rectHeightOri;
+
+ // Load correct digit (or : symbol)
+ gDPLoadTextureBlock(OVERLAY_DISP++, ((u8*)digitTextures[textureIndex]), G_IM_FMT_I, G_IM_SIZ_8b, rectWidth,
+ rectHeight, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
+ G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+
+ // Create dot image from the colon image.
+ if (totalTimeText[i] == '.') {
+ rectHeight = rectHeight / 2;
+ rectTop += 5;
+ rectLeft -= 1;
+ }
+
+ // Draw text shadow
+ gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 0, 0, 0, 255);
+ gDPSetEnvColor(OVERLAY_DISP++, 255, 255, 255, 255);
+ gSPWideTextureRectangle(OVERLAY_DISP++, rectLeft << 2, rectTop << 2, (rectLeft + rectWidth) << 2,
+ (rectTop + rectHeight) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
+
+ // 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 {
+ gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, 255);
+ }
+
+ // Offset text so underlaying shadow is to the bottom right of the text.
+ rectLeft -= 1;
+ rectTop -= 1;
+
+ gSPWideTextureRectangle(OVERLAY_DISP++, rectLeft << 2, rectTop << 2, (rectLeft + rectWidth) << 2,
+ (rectTop + rectHeight) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+ }
+}
+
void Interface_Update(PlayState* play) {
static u8 D_80125B60 = 0;
static s16 sPrevTimeIncrement = 0;
diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c
index a3d275390..8c5ebb950 100644
--- a/soh/src/code/z_play.c
+++ b/soh/src/code/z_play.c
@@ -1714,6 +1714,8 @@ void Play_Draw(PlayState* play) {
}
CLOSE_DISPS(gfxCtx);
+
+ Interface_DrawTotalGameplayTimer(play);
}
time_t Play_GetRealTime() {