mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Character win records
Track wins per character. - If you have an existing gamedata of minor version 2 or earlier, attempt to import your last-used profile's wins onto the character you last used on that profile, so you're not starting from nothing. It's not quite accurate, but it's something. - Much like map headers and cups, these are also tracked in an unloaded_skins_t linked list. That work was done in this commit because gamedata is actually loaded before even base-game characters, which is annoying but at least confirmed it was working quicker. - TEMPORARY: Your per-character wins are displayed in your latest-log.txt, in lieu of an update to the in-game statistics menu
This commit is contained in:
parent
aa35e249d5
commit
1527471678
8 changed files with 221 additions and 4 deletions
15
src/d_main.c
15
src/d_main.c
|
|
@ -1851,6 +1851,21 @@ void D_SRB2Main(void)
|
||||||
{
|
{
|
||||||
PR_ApplyProfile(cv_ttlprofilen.value, 0);
|
PR_ApplyProfile(cv_ttlprofilen.value, 0);
|
||||||
|
|
||||||
|
if (gamedata->importprofilewins == true)
|
||||||
|
{
|
||||||
|
profile_t *pr = PR_GetProfile(cv_ttlprofilen.value);
|
||||||
|
if (pr != NULL)
|
||||||
|
{
|
||||||
|
INT32 importskin = R_SkinAvailable(pr->skinname);
|
||||||
|
if (importskin != -1)
|
||||||
|
{
|
||||||
|
CONS_Printf(" Wins for profile \"%s\" imported onto character \"%s\"\n", pr->profilename, skins[importskin].name);
|
||||||
|
skins[importskin].records.wins = pr->wins;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gamedata->importprofilewins = false;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 1; i < cv_splitplayers.value; i++)
|
for (i = 1; i < cv_splitplayers.value; i++)
|
||||||
{
|
{
|
||||||
PR_ApplyProfile(cv_lastprofile[i].value, i);
|
PR_ApplyProfile(cv_lastprofile[i].value, i);
|
||||||
|
|
|
||||||
132
src/g_game.c
132
src/g_game.c
|
|
@ -453,6 +453,11 @@ void G_ClearRecords(void)
|
||||||
{
|
{
|
||||||
UINT16 i;
|
UINT16 i;
|
||||||
|
|
||||||
|
for (i = 0; i < numskins; i++)
|
||||||
|
{
|
||||||
|
memset(&skins[i].records, 0, sizeof(skins[i].records));
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < nummapheaders; i++)
|
for (i = 0; i < nummapheaders; i++)
|
||||||
{
|
{
|
||||||
memset(&mapheaderinfo[i]->records, 0, sizeof(recorddata_t));
|
memset(&mapheaderinfo[i]->records, 0, sizeof(recorddata_t));
|
||||||
|
|
@ -464,6 +469,14 @@ void G_ClearRecords(void)
|
||||||
memset(&cup->windata, 0, sizeof(cup->windata));
|
memset(&cup->windata, 0, sizeof(cup->windata));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unloaded_skin_t *unloadedskin, *nextunloadedskin = NULL;
|
||||||
|
for (unloadedskin = unloadedskins; unloadedskin; unloadedskin = nextunloadedskin)
|
||||||
|
{
|
||||||
|
nextunloadedskin = unloadedskin->next;
|
||||||
|
Z_Free(unloadedskin);
|
||||||
|
}
|
||||||
|
unloadedskins = NULL;
|
||||||
|
|
||||||
unloaded_mapheader_t *unloadedmap, *nextunloadedmap = NULL;
|
unloaded_mapheader_t *unloadedmap, *nextunloadedmap = NULL;
|
||||||
for (unloadedmap = unloadedmapheaders; unloadedmap; unloadedmap = nextunloadedmap)
|
for (unloadedmap = unloadedmapheaders; unloadedmap; unloadedmap = nextunloadedmap)
|
||||||
{
|
{
|
||||||
|
|
@ -4775,6 +4788,7 @@ void G_LoadGameData(void)
|
||||||
savebuffer_t save = {0};
|
savebuffer_t save = {0};
|
||||||
|
|
||||||
//For records
|
//For records
|
||||||
|
UINT32 numgamedataskins;
|
||||||
UINT32 numgamedatamapheaders;
|
UINT32 numgamedatamapheaders;
|
||||||
UINT32 numgamedatacups;
|
UINT32 numgamedatacups;
|
||||||
|
|
||||||
|
|
@ -4940,6 +4954,58 @@ void G_LoadGameData(void)
|
||||||
gamedata->timesBeaten = READUINT32(save.p);
|
gamedata->timesBeaten = READUINT32(save.p);
|
||||||
|
|
||||||
// Main records
|
// Main records
|
||||||
|
|
||||||
|
if (versionMinor < 3)
|
||||||
|
gamedata->importprofilewins = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numgamedataskins = READUINT32(save.p);
|
||||||
|
|
||||||
|
for (i = 0; i < numgamedataskins; i++)
|
||||||
|
{
|
||||||
|
char skinname[SKINNAMESIZE+1];
|
||||||
|
INT32 skin;
|
||||||
|
|
||||||
|
READSTRINGN(save.p, skinname, SKINNAMESIZE);
|
||||||
|
skin = R_SkinAvailable(skinname);
|
||||||
|
|
||||||
|
skinrecord_t dummyrecord;
|
||||||
|
|
||||||
|
dummyrecord.wins = READUINT32(save.p);
|
||||||
|
|
||||||
|
CONS_Printf(" (TEMPORARY DISPLAY) skinname is \"%s\", has %u wins\n", skinname, dummyrecord.wins);
|
||||||
|
|
||||||
|
if (skin != -1)
|
||||||
|
{
|
||||||
|
// We found a skin, so assign the win.
|
||||||
|
|
||||||
|
M_Memcpy(&skins[skin].records, &dummyrecord, sizeof(skinrecord_t));
|
||||||
|
}
|
||||||
|
else if (dummyrecord.wins)
|
||||||
|
{
|
||||||
|
// Invalid, but we don't want to lose all the juicy statistics.
|
||||||
|
// Instead, update a FILO linked list of "unloaded skins".
|
||||||
|
|
||||||
|
unloaded_skin_t *unloadedskin =
|
||||||
|
Z_Malloc(
|
||||||
|
sizeof(unloaded_skin_t),
|
||||||
|
PU_STATIC, NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
// Establish properties, for later retrieval on file add.
|
||||||
|
strlcpy(unloadedskin->name, skinname, sizeof(unloadedskin->name));
|
||||||
|
unloadedskin->namehash = quickncasehash(unloadedskin->name, SKINNAMESIZE);
|
||||||
|
|
||||||
|
// Insert at the head, just because it's convenient.
|
||||||
|
unloadedskin->next = unloadedskins;
|
||||||
|
unloadedskins = unloadedskin;
|
||||||
|
|
||||||
|
// Finally, copy into.
|
||||||
|
M_Memcpy(&unloadedskin->records, &dummyrecord, sizeof(skinrecord_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
numgamedatamapheaders = READUINT32(save.p);
|
numgamedatamapheaders = READUINT32(save.p);
|
||||||
|
|
||||||
for (i = 0; i < numgamedatamapheaders; i++)
|
for (i = 0; i < numgamedatamapheaders; i++)
|
||||||
|
|
@ -5157,6 +5223,36 @@ void G_SaveGameData(void)
|
||||||
length += gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT;
|
length += gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UINT32 numgamedataskins = 0;
|
||||||
|
unloaded_skin_t *unloadedskin;
|
||||||
|
|
||||||
|
for (i = 0; i < numskins; i++)
|
||||||
|
{
|
||||||
|
// It's safe to assume a skin with no wins will have no other data worth keeping
|
||||||
|
if (skins[i].records.wins == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
numgamedataskins++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unloadedskin = unloadedskins; unloadedskin; unloadedskin = unloadedskin->next)
|
||||||
|
{
|
||||||
|
// Ditto, with the exception that we should warn about it.
|
||||||
|
if (unloadedskin->records.wins == 0)
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_WARNING, "Unloaded skin \"%s\" has no wins!\n", unloadedskin->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
numgamedataskins++;
|
||||||
|
}
|
||||||
|
|
||||||
|
length += 4 + (numgamedataskins * (SKINNAMESIZE+4));
|
||||||
|
|
||||||
|
|
||||||
UINT32 numgamedatamapheaders = 0;
|
UINT32 numgamedatamapheaders = 0;
|
||||||
unloaded_mapheader_t *unloadedmap;
|
unloaded_mapheader_t *unloadedmap;
|
||||||
|
|
||||||
|
|
@ -5313,6 +5409,42 @@ void G_SaveGameData(void)
|
||||||
WRITEUINT32(save.p, gamedata->timesBeaten); // 4
|
WRITEUINT32(save.p, gamedata->timesBeaten); // 4
|
||||||
|
|
||||||
// Main records
|
// Main records
|
||||||
|
|
||||||
|
WRITEUINT32(save.p, numgamedataskins); // 4
|
||||||
|
|
||||||
|
{
|
||||||
|
// numgamedataskins * (SKINNAMESIZE+4)
|
||||||
|
|
||||||
|
for (i = 0; i < numskins; i++)
|
||||||
|
{
|
||||||
|
if (skins[i].records.wins == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
WRITESTRINGN(save.p, skins[i].name, SKINNAMESIZE);
|
||||||
|
|
||||||
|
WRITEUINT32(save.p, skins[i].records.wins);
|
||||||
|
|
||||||
|
if (--numgamedataskins == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numgamedataskins)
|
||||||
|
{
|
||||||
|
for (unloadedskin = unloadedskins; unloadedskin; unloadedskin = unloadedskin->next)
|
||||||
|
{
|
||||||
|
if (unloadedskin->records.wins == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
WRITESTRINGN(save.p, unloadedskin->name, SKINNAMESIZE);
|
||||||
|
|
||||||
|
WRITEUINT32(save.p, unloadedskin->records.wins);
|
||||||
|
|
||||||
|
if (--numgamedataskins == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WRITEUINT32(save.p, numgamedatamapheaders); // 4
|
WRITEUINT32(save.p, numgamedatamapheaders); // 4
|
||||||
|
|
||||||
if (numgamedatamapheaders)
|
if (numgamedatamapheaders)
|
||||||
|
|
|
||||||
|
|
@ -531,6 +531,8 @@ void M_ClearStats(void)
|
||||||
gamedata->everseenspecial = false;
|
gamedata->everseenspecial = false;
|
||||||
gamedata->evercrashed = false;
|
gamedata->evercrashed = false;
|
||||||
gamedata->musicflags = 0;
|
gamedata->musicflags = 0;
|
||||||
|
|
||||||
|
gamedata->importprofilewins = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void M_ClearSecrets(void)
|
void M_ClearSecrets(void)
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,9 @@ struct gamedata_t
|
||||||
boolean everseenspecial;
|
boolean everseenspecial;
|
||||||
boolean evercrashed;
|
boolean evercrashed;
|
||||||
UINT8 musicflags;
|
UINT8 musicflags;
|
||||||
|
|
||||||
|
// BACKWARDS COMPAT ASSIST
|
||||||
|
boolean importprofilewins;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern gamedata_t *gamedata;
|
extern gamedata_t *gamedata;
|
||||||
|
|
|
||||||
10
src/p_user.c
10
src/p_user.c
|
|
@ -1355,13 +1355,21 @@ void P_DoPlayerExit(player_t *player, pflags_t flags)
|
||||||
G_UpdateRecords();
|
G_UpdateRecords();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!losing)
|
||||||
|
{
|
||||||
profile_t *pr = PR_GetPlayerProfile(player);
|
profile_t *pr = PR_GetPlayerProfile(player);
|
||||||
if (pr != NULL && !losing)
|
if (pr != NULL)
|
||||||
{
|
{
|
||||||
pr->wins++;
|
pr->wins++;
|
||||||
PR_SaveProfiles();
|
PR_SaveProfiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (P_IsLocalPlayer(player) && player->skin < numskins)
|
||||||
|
{
|
||||||
|
skins[player->skin].records.wins++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
player->karthud[khud_cardanimation] = 0; // srb2kart: reset battle animation
|
player->karthud[khud_cardanimation] = 0; // srb2kart: reset battle animation
|
||||||
|
|
||||||
if (player == &players[consoleplayer])
|
if (player == &players[consoleplayer])
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@
|
||||||
INT32 numskins = 0;
|
INT32 numskins = 0;
|
||||||
skin_t skins[MAXSKINS];
|
skin_t skins[MAXSKINS];
|
||||||
|
|
||||||
|
unloaded_skin_t *unloadedskins = NULL;
|
||||||
|
|
||||||
// FIXTHIS: don't work because it must be inistilised before the config load
|
// FIXTHIS: don't work because it must be inistilised before the config load
|
||||||
//#define SKINVALUES
|
//#define SKINVALUES
|
||||||
#ifdef SKINVALUES
|
#ifdef SKINVALUES
|
||||||
|
|
@ -125,6 +127,8 @@ static void Sk_SetDefaultValue(skin_t *skin)
|
||||||
|
|
||||||
skin->highresscale = FRACUNIT;
|
skin->highresscale = FRACUNIT;
|
||||||
|
|
||||||
|
// no specific memset for skinrecord_t as it's already nuked by the full skin_t wipe
|
||||||
|
|
||||||
for (i = 0; i < sfx_skinsoundslot0; i++)
|
for (i = 0; i < sfx_skinsoundslot0; i++)
|
||||||
if (S_sfx[i].skinsound != -1)
|
if (S_sfx[i].skinsound != -1)
|
||||||
skin->soundsid[S_sfx[i].skinsound] = i;
|
skin->soundsid[S_sfx[i].skinsound] = i;
|
||||||
|
|
@ -1006,6 +1010,38 @@ next_token:
|
||||||
// Finally, conclude by setting up final properties.
|
// Finally, conclude by setting up final properties.
|
||||||
skin->namehash = quickncasehash(skin->name, SKINNAMESIZE);
|
skin->namehash = quickncasehash(skin->name, SKINNAMESIZE);
|
||||||
|
|
||||||
|
{
|
||||||
|
// Check to see if we have any custom skin wins data that we could substitute in.
|
||||||
|
unloaded_skin_t *unloadedskin, *unloadedprev = NULL;
|
||||||
|
for (unloadedskin = unloadedskins; unloadedskin; unloadedprev = unloadedskin, unloadedskin = unloadedskin->next)
|
||||||
|
{
|
||||||
|
if (unloadedskin->namehash != skin->namehash)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcasecmp(skin->name, unloadedskin->name) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Copy in wins, etc.
|
||||||
|
M_Memcpy(&skin->records, &unloadedskin->records, sizeof(skin->records));
|
||||||
|
|
||||||
|
// Remove this entry from the chain.
|
||||||
|
if (unloadedprev)
|
||||||
|
{
|
||||||
|
unloadedprev->next = unloadedskin->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unloadedskins = unloadedskin->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, free.
|
||||||
|
Z_Free(unloadedskin);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
numskins++;
|
numskins++;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,11 @@ extern "C" {
|
||||||
#define DEFAULTSKIN3 "sonic" // third player
|
#define DEFAULTSKIN3 "sonic" // third player
|
||||||
#define DEFAULTSKIN4 "knuckles" // fourth player
|
#define DEFAULTSKIN4 "knuckles" // fourth player
|
||||||
|
|
||||||
|
struct skinrecord_t
|
||||||
|
{
|
||||||
|
UINT32 wins;
|
||||||
|
};
|
||||||
|
|
||||||
/// The skin_t struct
|
/// The skin_t struct
|
||||||
struct skin_t
|
struct skin_t
|
||||||
{
|
{
|
||||||
|
|
@ -59,6 +64,8 @@ struct skin_t
|
||||||
|
|
||||||
fixed_t highresscale; // scale of highres, default is 0.5
|
fixed_t highresscale; // scale of highres, default is 0.5
|
||||||
|
|
||||||
|
skinrecord_t records;
|
||||||
|
|
||||||
char rivals[SKINRIVALS][SKINNAMESIZE+1]; // Your top 3 rivals for GP mode. Uses names so that you can reference skins that aren't added
|
char rivals[SKINRIVALS][SKINNAMESIZE+1]; // Your top 3 rivals for GP mode. Uses names so that you can reference skins that aren't added
|
||||||
|
|
||||||
// specific sounds per skin
|
// specific sounds per skin
|
||||||
|
|
@ -69,6 +76,18 @@ struct skin_t
|
||||||
spriteinfo_t sprinfo[NUMPLAYERSPRITES*2];
|
spriteinfo_t sprinfo[NUMPLAYERSPRITES*2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct unloaded_skin_t
|
||||||
|
{
|
||||||
|
char name[SKINNAMESIZE+1];
|
||||||
|
UINT32 namehash;
|
||||||
|
|
||||||
|
skinrecord_t records;
|
||||||
|
|
||||||
|
unloaded_skin_t *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern unloaded_skin_t *unloadedskins;
|
||||||
|
|
||||||
enum facepatches {
|
enum facepatches {
|
||||||
FACE_RANK = 0,
|
FACE_RANK = 0,
|
||||||
FACE_WANTED,
|
FACE_WANTED,
|
||||||
|
|
|
||||||
|
|
@ -385,7 +385,9 @@ TYPEDEF (visffloor_t);
|
||||||
TYPEDEF (portal_t);
|
TYPEDEF (portal_t);
|
||||||
|
|
||||||
// r_skins.h
|
// r_skins.h
|
||||||
|
TYPEDEF (skinrecord_t);
|
||||||
TYPEDEF (skin_t);
|
TYPEDEF (skin_t);
|
||||||
|
TYPEDEF (unloaded_skin_t);
|
||||||
|
|
||||||
// r_splats.h
|
// r_splats.h
|
||||||
TYPEDEF (floorsplat_t);
|
TYPEDEF (floorsplat_t);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue