mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Statistics menu
Relatively quick port from v1., but with under-the-hood changes to match the Emblem/Medal and Extra Medal reworks. We can make it prettier (and contain more data) later.
This commit is contained in:
parent
2fbbe52ded
commit
42f4f28e06
6 changed files with 362 additions and 16 deletions
14
src/k_menu.h
14
src/k_menu.h
|
|
@ -405,8 +405,9 @@ extern menu_t MISC_ManualDef;
|
|||
extern menuitem_t MISC_Addons[];
|
||||
extern menu_t MISC_AddonsDef;
|
||||
|
||||
extern menuitem_t MISC_Challenges[];
|
||||
extern menuitem_t MISC_ChallengesStatsDummyMenu[];
|
||||
extern menu_t MISC_ChallengesDef;
|
||||
extern menu_t MISC_StatisticsDef;
|
||||
|
||||
// We'll need this since we're gonna have to dynamically enable and disable options depending on which state we're in.
|
||||
typedef enum
|
||||
|
|
@ -1124,6 +1125,17 @@ void M_DrawChallenges(void);
|
|||
void M_ChallengesTick(void);
|
||||
boolean M_ChallengesInputs(INT32 ch);
|
||||
|
||||
extern struct statisticsmenu_s {
|
||||
INT32 location;
|
||||
INT32 nummaps;
|
||||
INT32 maxscroll;
|
||||
UINT16 *maplist;
|
||||
} statisticsmenu;
|
||||
|
||||
void M_Statistics(INT32 choice);
|
||||
void M_DrawStatistics(void);
|
||||
boolean M_StatisticsInputs(INT32 ch);
|
||||
|
||||
// These defines make it a little easier to make menus
|
||||
#define DEFAULTMENUSTYLE(source, prev, x, y)\
|
||||
{\
|
||||
|
|
|
|||
|
|
@ -1503,7 +1503,7 @@ menuitem_t EXTRAS_Main[] =
|
|||
NULL, {.routine = M_ReplayHut}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "Statistics", "Look back on some of your greatest achievements such as your playtime and wins!",
|
||||
NULL, {NULL}, 0, 0},
|
||||
NULL, {.routine = M_Statistics}, 0, 0},
|
||||
};
|
||||
|
||||
// the extras menu essentially reuses the options menu stuff
|
||||
|
|
@ -1746,16 +1746,16 @@ menu_t MISC_AddonsDef = {
|
|||
};
|
||||
|
||||
// Challenges.
|
||||
menuitem_t MISC_ChallengesMenu[] =
|
||||
menuitem_t MISC_ChallengesStatsDummyMenu[] =
|
||||
{
|
||||
{IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0},
|
||||
};
|
||||
|
||||
menu_t MISC_ChallengesDef = {
|
||||
sizeof (MISC_ChallengesMenu)/sizeof (menuitem_t),
|
||||
sizeof (MISC_ChallengesStatsDummyMenu)/sizeof (menuitem_t),
|
||||
&MainDef,
|
||||
0,
|
||||
MISC_ChallengesMenu,
|
||||
MISC_ChallengesStatsDummyMenu,
|
||||
BASEVIDWIDTH/2, 32,
|
||||
0, 0,
|
||||
98, 0,
|
||||
|
|
@ -1765,3 +1765,18 @@ menu_t MISC_ChallengesDef = {
|
|||
NULL,
|
||||
M_ChallengesInputs,
|
||||
};
|
||||
|
||||
menu_t MISC_StatisticsDef = {
|
||||
sizeof (MISC_ChallengesStatsDummyMenu)/sizeof (menuitem_t),
|
||||
&MainDef,
|
||||
0,
|
||||
MISC_ChallengesStatsDummyMenu,
|
||||
280, 185,
|
||||
0, 0,
|
||||
98, 0,
|
||||
M_DrawStatistics,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
M_StatisticsInputs,
|
||||
};
|
||||
|
|
|
|||
227
src/k_menudraw.c
227
src/k_menudraw.c
|
|
@ -4461,6 +4461,8 @@ void M_DrawAddons(void)
|
|||
|
||||
#undef addonsseperation
|
||||
|
||||
// Challenges Menu
|
||||
|
||||
#define challengesbordercolor 27
|
||||
|
||||
static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, boolean hili)
|
||||
|
|
@ -4894,3 +4896,228 @@ challengedesc:
|
|||
V_DrawCenteredString(BASEVIDWIDTH/2, 120 + 32, V_ALLOWLOWERCASE, challengesmenu.unlockcondition);
|
||||
}
|
||||
}
|
||||
|
||||
// Statistics menu
|
||||
|
||||
#define STATSSTEP 10
|
||||
|
||||
static void M_DrawMapMedals(INT32 mapnum, INT32 x, INT32 y)
|
||||
{
|
||||
UINT8 lasttype = UINT8_MAX, curtype;
|
||||
emblem_t *emblem = M_GetLevelEmblems(mapnum);
|
||||
|
||||
while (emblem)
|
||||
{
|
||||
switch (emblem->type)
|
||||
{
|
||||
case ET_TIME:
|
||||
curtype = 1;
|
||||
break;
|
||||
case ET_GLOBAL:
|
||||
{
|
||||
if (emblem->flags & GE_NOTMEDAL)
|
||||
{
|
||||
emblem = M_GetLevelEmblems(-1);
|
||||
continue;
|
||||
}
|
||||
curtype = 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
curtype = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Shift over if emblem is of a different discipline
|
||||
if (lasttype != UINT8_MAX && lasttype != curtype)
|
||||
x -= 4;
|
||||
lasttype = curtype;
|
||||
|
||||
if (gamedata->collected[emblem-emblemlocations])
|
||||
V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE),
|
||||
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_MENUCACHE));
|
||||
else
|
||||
V_DrawSmallScaledPatch(x, y, 0, W_CachePatchName("NEEDIT", PU_CACHE));
|
||||
|
||||
emblem = M_GetLevelEmblems(-1);
|
||||
x -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void M_DrawStatsMaps(void)
|
||||
{
|
||||
INT32 y = 80, i = -1;
|
||||
INT16 mnum;
|
||||
boolean dotopname = true, dobottomarrow = (statisticsmenu.location < statisticsmenu.maxscroll);
|
||||
INT32 location = statisticsmenu.location;
|
||||
|
||||
if (location)
|
||||
V_DrawCharacter(10, y-(skullAnimCounter/5),
|
||||
'\x1A' | highlightflags, false); // up arrow
|
||||
|
||||
while (statisticsmenu.maplist[++i] != NEXTMAP_INVALID)
|
||||
{
|
||||
if (location)
|
||||
{
|
||||
--location;
|
||||
continue;
|
||||
}
|
||||
else if (dotopname)
|
||||
{
|
||||
V_DrawThinString(20, y, highlightflags, "LEVEL NAME");
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH-20, y, highlightflags, "MEDALS");
|
||||
y += STATSSTEP;
|
||||
dotopname = false;
|
||||
}
|
||||
|
||||
mnum = statisticsmenu.maplist[i]+1;
|
||||
M_DrawMapMedals(mnum, 291, y);
|
||||
|
||||
{
|
||||
char *title = G_BuildMapTitle(mnum);
|
||||
V_DrawThinString(20, y, 0, title);
|
||||
Z_Free(title);
|
||||
}
|
||||
|
||||
y += STATSSTEP;
|
||||
|
||||
if (y >= BASEVIDHEIGHT-STATSSTEP)
|
||||
goto bottomarrow;
|
||||
}
|
||||
if (dotopname && !location)
|
||||
{
|
||||
V_DrawString(20, y, highlightflags, "LEVEL NAME");
|
||||
V_DrawString(256, y, highlightflags, "MEDALS");
|
||||
y += STATSSTEP;
|
||||
}
|
||||
else if (location)
|
||||
--location;
|
||||
|
||||
// Extra Emblem headers
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
if (i == 1)
|
||||
{
|
||||
V_DrawThinString(20, y, highlightflags, "EXTRA MEDALS");
|
||||
if (location)
|
||||
{
|
||||
y += STATSSTEP;
|
||||
location++;
|
||||
}
|
||||
}
|
||||
if (location)
|
||||
{
|
||||
--location;
|
||||
continue;
|
||||
}
|
||||
|
||||
y += STATSSTEP;
|
||||
|
||||
if (y >= BASEVIDHEIGHT-STATSSTEP)
|
||||
goto bottomarrow;
|
||||
}
|
||||
|
||||
// Extra Emblems
|
||||
for (i = 0; i < MAXUNLOCKABLES; i++)
|
||||
{
|
||||
if (unlockables[i].type != SECRET_EXTRAMEDAL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (location)
|
||||
{
|
||||
--location;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i >= 0)
|
||||
{
|
||||
if (gamedata->unlocked[i])
|
||||
{
|
||||
UINT16 color = min(unlockables[i].color, numskincolors-1);
|
||||
if (!color)
|
||||
color = SKINCOLOR_GOLD;
|
||||
V_DrawSmallMappedPatch(291, y+1, 0, W_CachePatchName("GOTITA", PU_CACHE),
|
||||
R_GetTranslationColormap(TC_DEFAULT, color, GTC_MENUCACHE));
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawSmallScaledPatch(291, y+1, 0, W_CachePatchName("NEEDIT", PU_CACHE));
|
||||
}
|
||||
|
||||
V_DrawThinString(20, y, 0, va("%s", unlockables[i].name));
|
||||
}
|
||||
|
||||
y += STATSSTEP;
|
||||
|
||||
if (y >= BASEVIDHEIGHT-STATSSTEP)
|
||||
goto bottomarrow;
|
||||
}
|
||||
bottomarrow:
|
||||
if (dobottomarrow)
|
||||
V_DrawCharacter(10, y-STATSSTEP + (skullAnimCounter/5),
|
||||
'\x1B' | highlightflags, false); // down arrow
|
||||
}
|
||||
|
||||
void M_DrawStatistics(void)
|
||||
{
|
||||
char beststr[40];
|
||||
|
||||
tic_t besttime = 0;
|
||||
|
||||
INT32 i;
|
||||
INT32 mapsunfinished = 0;
|
||||
|
||||
{
|
||||
patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE);
|
||||
V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL);
|
||||
}
|
||||
|
||||
V_DrawThinString(20, 22, V_ALLOWLOWERCASE|highlightflags, "Total Play Time:");
|
||||
V_DrawCenteredThinString(BASEVIDWIDTH/2, 32, 0,
|
||||
va("%i hours, %i minutes, %i seconds",
|
||||
G_TicsToHours(gamedata->totalplaytime),
|
||||
G_TicsToMinutes(gamedata->totalplaytime, false),
|
||||
G_TicsToSeconds(gamedata->totalplaytime)));
|
||||
V_DrawThinString(20, 42, V_ALLOWLOWERCASE|highlightflags, "Total Matches:");
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH-20, 42, 0, va("%i played", gamedata->matchesplayed));
|
||||
|
||||
if (!statisticsmenu.maplist)
|
||||
{
|
||||
V_DrawCenteredThinString(BASEVIDWIDTH/2, 62, V_ALLOWLOWERCASE, "No maps!?");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < nummapheaders; i++)
|
||||
{
|
||||
if (!mapheaderinfo[i] || (mapheaderinfo[i]->menuflags & (LF2_NOTIMEATTACK|LF2_HIDEINSTATS|LF2_HIDEINMENU)))
|
||||
continue;
|
||||
|
||||
if (!mapheaderinfo[i]->mainrecord || mapheaderinfo[i]->mainrecord->time <= 0)
|
||||
{
|
||||
mapsunfinished++;
|
||||
continue;
|
||||
}
|
||||
|
||||
besttime += mapheaderinfo[i]->mainrecord->time;
|
||||
}
|
||||
|
||||
V_DrawThinString(20, 60, V_ALLOWLOWERCASE, "Combined time records:");
|
||||
|
||||
sprintf(beststr, "%i:%02i:%02i.%02i", G_TicsToHours(besttime), G_TicsToMinutes(besttime, false), G_TicsToSeconds(besttime), G_TicsToCentiseconds(besttime));
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH-20, 60, V_ALLOWLOWERCASE|(mapsunfinished ? V_REDMAP : 0), beststr);
|
||||
|
||||
if (mapsunfinished)
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH-20, 70, V_ALLOWLOWERCASE|V_REDMAP, va("(%d unfinished)", mapsunfinished));
|
||||
else
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH-20, 70, V_ALLOWLOWERCASE, "(complete)");
|
||||
|
||||
V_DrawThinString(32, 70, 0, va("x %d/%d", M_CountMedals(false, false), M_CountMedals(true, false)));
|
||||
V_DrawSmallMappedPatch(20, 70, 0, W_CachePatchName("GOTITA", PU_CACHE),
|
||||
R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_GOLD, GTC_MENUCACHE));
|
||||
|
||||
M_DrawStatsMaps();
|
||||
}
|
||||
|
||||
#undef STATSSTEP
|
||||
|
|
|
|||
|
|
@ -6853,6 +6853,8 @@ void M_Manual(INT32 choice)
|
|||
M_SetupNextMenu(&MISC_ManualDef, true);
|
||||
}
|
||||
|
||||
// Challenges menu
|
||||
|
||||
struct challengesmenu_s challengesmenu;
|
||||
|
||||
menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu)
|
||||
|
|
@ -7385,3 +7387,90 @@ boolean M_ChallengesInputs(INT32 ch)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Statistics menu
|
||||
|
||||
struct statisticsmenu_s statisticsmenu;
|
||||
|
||||
void M_Statistics(INT32 choice)
|
||||
{
|
||||
UINT16 i = 0;
|
||||
|
||||
(void)choice;
|
||||
|
||||
statisticsmenu.maplist = Z_Malloc(sizeof(UINT16) * nummapheaders, PU_STATIC, NULL);
|
||||
statisticsmenu.nummaps = 0;
|
||||
|
||||
for (i = 0; i < nummapheaders; i++)
|
||||
{
|
||||
if (!mapheaderinfo[i])
|
||||
continue;
|
||||
|
||||
if (mapheaderinfo[i]->menuflags & (LF2_NOTIMEATTACK|LF2_HIDEINSTATS|LF2_HIDEINMENU))
|
||||
continue;
|
||||
|
||||
if (M_MapLocked(i+1))
|
||||
continue;
|
||||
|
||||
statisticsmenu.maplist[statisticsmenu.nummaps++] = i;
|
||||
}
|
||||
statisticsmenu.maplist[statisticsmenu.nummaps] = NEXTMAP_INVALID;
|
||||
statisticsmenu.maxscroll = (statisticsmenu.nummaps + M_CountMedals(true, true) + 2) - 10;
|
||||
statisticsmenu.location = 0;
|
||||
|
||||
if (statisticsmenu.maxscroll < 0)
|
||||
{
|
||||
statisticsmenu.maxscroll = 0;
|
||||
}
|
||||
|
||||
MISC_StatisticsDef.prevMenu = currentMenu;
|
||||
M_SetupNextMenu(&MISC_StatisticsDef, false);
|
||||
}
|
||||
|
||||
boolean M_StatisticsInputs(INT32 ch)
|
||||
{
|
||||
const UINT8 pid = 0;
|
||||
|
||||
(void)ch;
|
||||
|
||||
if (M_MenuBackPressed(pid))
|
||||
{
|
||||
M_GoBack(0);
|
||||
M_SetMenuDelay(pid);
|
||||
|
||||
Z_Free(statisticsmenu.maplist);
|
||||
statisticsmenu.maplist = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (M_MenuExtraPressed(pid))
|
||||
{
|
||||
if (statisticsmenu.location > 0)
|
||||
{
|
||||
statisticsmenu.location = 0;
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
}
|
||||
else if (menucmd[pid].dpad_ud > 0)
|
||||
{
|
||||
if (statisticsmenu.location < statisticsmenu.maxscroll)
|
||||
{
|
||||
statisticsmenu.location++;
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
}
|
||||
else if (menucmd[pid].dpad_ud < 0)
|
||||
{
|
||||
if (statisticsmenu.location > 0)
|
||||
{
|
||||
statisticsmenu.location--;
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
23
src/m_cond.c
23
src/m_cond.c
|
|
@ -1123,17 +1123,20 @@ boolean M_MapLocked(INT32 mapnum)
|
|||
return false;
|
||||
}
|
||||
|
||||
INT32 M_CountMedals(boolean all)
|
||||
INT32 M_CountMedals(boolean all, boolean extraonly)
|
||||
{
|
||||
INT32 found = 0, i;
|
||||
for (i = 0; i < numemblems; ++i)
|
||||
if (!extraonly)
|
||||
{
|
||||
if ((emblemlocations[i].type == ET_GLOBAL)
|
||||
&& (emblemlocations[i].flags & GE_NOTMEDAL))
|
||||
continue;
|
||||
if (!all && !gamedata->collected[i])
|
||||
continue;
|
||||
found++;
|
||||
for (i = 0; i < numemblems; ++i)
|
||||
{
|
||||
if ((emblemlocations[i].type == ET_GLOBAL)
|
||||
&& (emblemlocations[i].flags & GE_NOTMEDAL))
|
||||
continue;
|
||||
if (!all && !gamedata->collected[i])
|
||||
continue;
|
||||
found++;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAXUNLOCKABLES; ++i)
|
||||
{
|
||||
|
|
@ -1404,8 +1407,8 @@ emblem_t *M_GetLevelEmblems(INT32 mapnum)
|
|||
|
||||
skincolornum_t M_GetEmblemColor(emblem_t *em)
|
||||
{
|
||||
if (!em || em->color >= numskincolors)
|
||||
return SKINCOLOR_NONE;
|
||||
if (!em || !em->color || em->color >= numskincolors)
|
||||
return SKINCOLOR_GOLD;
|
||||
return em->color;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ boolean M_CheckNetUnlockByID(UINT8 unlockid);
|
|||
boolean M_SecretUnlocked(INT32 type, boolean local);
|
||||
boolean M_CupLocked(cupheader_t *cup);
|
||||
boolean M_MapLocked(INT32 mapnum);
|
||||
INT32 M_CountMedals(boolean all);
|
||||
INT32 M_CountMedals(boolean all, boolean extraonly);
|
||||
|
||||
// Emblem shit
|
||||
emblem_t *M_GetLevelEmblems(INT32 mapnum);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue