Add totalrings to gamedata

- Added to Statistics screen
- Caps at "999,999,999+".
- Controls UC_TOTALRINGS condition
- Improve description for UC_MATCHESPLAYED condition
    - Says "Rounds" now
- Improve Statistics text for playtime
    - Dynamically changes visible units of time (seconds, minutes, hours, days.......)
This commit is contained in:
toaster 2023-03-03 22:35:28 +00:00
parent 74336efc74
commit eeb6e40909
7 changed files with 85 additions and 11 deletions

View file

@ -2370,6 +2370,18 @@ static void readcondition(UINT8 set, UINT32 id, char *word2)
ty = UC_PLAYTIME + offset;
re = atoi(params[1]);
}
else if (fastcmp(params[0], "TOTALRINGS"))
{
PARAMCHECK(1);
ty = UC_TOTALRINGS;
re = atoi(params[1]);
if (re < 2 || re > GDMAX_RINGS)
{
deh_warning("Total Rings requirement %d out of range (%d - %d) for condition ID %d", re, 2, GDMAX_RINGS, id+1);
return;
}
}
else if (fastcmp(params[0], "POWERLEVEL"))
{
PARAMCHECK(2);

View file

@ -4346,12 +4346,13 @@ void G_LoadGameData(void)
// Clear things so previously read gamedata doesn't transfer
// to new gamedata
// see also M_EraseDataResponse
G_ClearRecords(); // records
M_ClearSecrets(); // emblems, unlocks, maps visited, etc
gamedata->totalplaytime = 0; // total play time (separate from all)
gamedata->matchesplayed = 0; // SRB2Kart: matches played & finished
gamedata->crashflags = 0;
gamedata->totalplaytime = 0;
gamedata->matchesplayed = 0;
gamedata->totalrings = 0;
if (M_CheckParm("-nodata"))
{
@ -4401,6 +4402,8 @@ void G_LoadGameData(void)
if (versionMinor > 1)
{
gamedata->totalrings = READUINT32(save.p);
gamedata->crashflags = READUINT8(save.p);
if (gamedata->crashflags & GDCRASH_LAST)
gamedata->crashflags |= GDCRASH_ANY;
@ -4571,7 +4574,7 @@ void G_SaveGameData(boolean dirty)
return;
}
length = (4+1+4+4+1+4+(MAXEMBLEMS+(MAXUNLOCKABLES*2)+MAXCONDITIONSETS)+4+4+2);
length = (4+1+4+4+4+1+4+(MAXEMBLEMS+(MAXUNLOCKABLES*2)+MAXCONDITIONSETS)+4+4+2);
if (gamedata->challengegrid)
{
length += gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT;
@ -4590,6 +4593,7 @@ void G_SaveGameData(boolean dirty)
WRITEUINT8(save.p, GD_VERSIONMINOR); // 1
WRITEUINT32(save.p, gamedata->totalplaytime); // 4
WRITEUINT32(save.p, gamedata->matchesplayed); // 4
WRITEUINT32(save.p, gamedata->totalrings); // 4
{
UINT8 crashflags = (gamedata->crashflags & GDCRASH_ANY);

View file

@ -5471,7 +5471,7 @@ bottomarrow:
void M_DrawStatistics(void)
{
char beststr[40];
char beststr[256];
tic_t besttime = 0;
@ -5483,12 +5483,48 @@ void M_DrawStatistics(void)
V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL);
}
beststr[0] = 0;
V_DrawThinString(20, 22, V_6WIDTHSPACE|V_ALLOWLOWERCASE|highlightflags, "Total Play Time:");
V_DrawCenteredThinString(BASEVIDWIDTH/2, 32, V_6WIDTHSPACE,
va("%i hours, %i minutes, %i seconds",
G_TicsToHours(gamedata->totalplaytime),
G_TicsToMinutes(gamedata->totalplaytime, false),
G_TicsToSeconds(gamedata->totalplaytime)));
besttime = G_TicsToHours(gamedata->totalplaytime);
if (besttime)
{
if (besttime >= 24)
{
strcat(beststr, va("%u days, ", besttime/24));
besttime %= 24;
}
strcat(beststr, va("%u hours, ", besttime));
}
besttime = G_TicsToMinutes(gamedata->totalplaytime, false);
if (besttime)
{
strcat(beststr, va("%u minutes, ", besttime));
}
strcat(beststr, va("%i seconds", G_TicsToSeconds(gamedata->totalplaytime)));
V_DrawRightAlignedThinString(BASEVIDWIDTH-20, 22, V_6WIDTHSPACE, beststr);
beststr[0] = 0;
V_DrawThinString(20, 32, V_6WIDTHSPACE|V_ALLOWLOWERCASE|highlightflags, "Total Rings:");
if (gamedata->totalrings > GDMAX_RINGS)
{
sprintf(beststr, "%c999,999,999+", '\x82');
}
else if (gamedata->totalrings >= 1000000)
{
sprintf(beststr, "%u,%u,%u", (gamedata->totalrings/1000000), (gamedata->totalrings/1000)%1000, (gamedata->totalrings%1000));
}
else if (gamedata->totalrings >= 1000)
{
sprintf(beststr, "%u,%u", (gamedata->totalrings/1000), (gamedata->totalrings%1000));
}
else
{
sprintf(beststr, "%u", gamedata->totalrings);
}
V_DrawRightAlignedThinString(BASEVIDWIDTH-20, 32, V_6WIDTHSPACE, va("%s collected", beststr));
beststr[0] = 0;
V_DrawThinString(20, 42, V_6WIDTHSPACE|V_ALLOWLOWERCASE|highlightflags, "Total Matches:");
V_DrawRightAlignedThinString(BASEVIDWIDTH-20, 42, V_6WIDTHSPACE, va("%i played", gamedata->matchesplayed));
@ -5498,6 +5534,8 @@ void M_DrawStatistics(void)
return;
}
besttime = 0;
for (i = 0; i < nummapheaders; i++)
{
if (!mapheaderinfo[i] || (mapheaderinfo[i]->menuflags & (LF2_NOTIMEATTACK|LF2_HIDEINSTATS|LF2_HIDEINMENU)))

View file

@ -624,6 +624,8 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
return (gamedata->totalplaytime >= (unsigned)cn->requirement);
case UC_MATCHESPLAYED: // Requires any level completed >= x times
return (gamedata->matchesplayed >= (unsigned)cn->requirement);
case UC_TOTALRINGS: // Requires grabbing >= x rings
return (gamedata->totalrings >= (unsigned)cn->requirement);
case UC_POWERLEVEL: // Requires power level >= x on a certain gametype
{
UINT8 i;
@ -832,7 +834,13 @@ static const char *M_GetConditionString(condition_t *cn)
G_TicsToMinutes(cn->requirement, false),
G_TicsToSeconds(cn->requirement));
case UC_MATCHESPLAYED: // Requires any level completed >= x times
return va("Play %d matches", cn->requirement);
return va("Play %d Rounds", cn->requirement);
case UC_TOTALRINGS: // Requires collecting >= x rings
if (cn->requirement >= 1000000)
return va("Collect %u,%u,%u Rings", (cn->requirement/1000000), (cn->requirement/1000)%1000, (cn->requirement%1000));
if (cn->requirement >= 1000)
return va("Collect %u,%u Rings", (cn->requirement/1000), (cn->requirement%1000));
return va("Collect %u Rings", cn->requirement);
case UC_POWERLEVEL: // Requires power level >= x on a certain gametype
return va("Get a PWR of %d in %s", cn->requirement,
(cn->extrainfo1 == PWRLV_RACE)

View file

@ -30,6 +30,7 @@ typedef enum
{
UC_PLAYTIME, // PLAYTIME [tics]
UC_MATCHESPLAYED, // SRB2Kart: MATCHESPLAYED [x played]
UC_TOTALRINGS, // TOTALRINGS [x collected]
UC_POWERLEVEL, // SRB2Kart: POWERLEVEL [power level to reach] [gametype, "0" for race, "1" for battle]
UC_GAMECLEAR, // GAMECLEAR <x times>
UC_OVERALLTIME, // OVERALLTIME [time to beat, tics]
@ -187,6 +188,9 @@ typedef enum
#define GDCRASH_ANY 0x02
#define GDCRASH_LOSERCLUB 0x04
// This is the largest number of 9s that will fit in UINT32.
#define GDMAX_RINGS 999999999
// GAMEDATA STRUCTURE
// Everything that would get saved in gamedata.dat
struct gamedata_t
@ -215,6 +219,7 @@ struct gamedata_t
// PLAY TIME
UINT32 totalplaytime;
UINT32 matchesplayed;
UINT32 totalrings;
// Funny
UINT8 crashflags;

View file

@ -53,11 +53,13 @@ static void M_EraseDataResponse(INT32 ch)
S_StartSound(NULL, sfx_itrole); // bweh heh heh
// Delete the data
// see also G_LoadGameData
if (optionsmenu.erasecontext == 2)
{
// SRB2Kart: This actually needs to be done FIRST, so that you don't immediately regain playtime/matches secrets
gamedata->totalplaytime = 0;
gamedata->matchesplayed = 0;
gamedata->totalrings = 0;
}
if (optionsmenu.erasecontext != 1)
G_ClearRecords();

View file

@ -505,6 +505,11 @@ INT32 P_GivePlayerRings(player_t *player, INT32 num_rings)
if ((gametyperules & GTR_SPHERES)) // No rings in Battle Mode
return 0;
if (gamedata && num_rings > 0 && P_IsLocalPlayer(player) && gamedata->totalrings <= GDMAX_RINGS)
{
gamedata->totalrings += num_rings;
}
test = player->rings + num_rings;
if (test > 20) // Caps at 20 rings, sorry!
num_rings -= (test-20);