[Feature] In-game gameplay stats timer (#2910)

* Implement in-game gameplay stats timer

* Change timer to render on top of everything
This commit is contained in:
aMannus 2023-05-31 00:57:45 +02:00 committed by GitHub
commit b25e4d4f26
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 134 additions and 5 deletions

View file

@ -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;