skinreference_t

Please note this is incompatible with gamedata from previous commits on this branch. As always, keep a backup of your last stable gamedata.

A system for record data to point to either loaded or unloaded skins.
- When writing to gamedata, stores a funny internal reference id on skinrecord_t.
- This ID is then used when writing out subsequent references ala mobjnum.
- As an example, has been attached to cup windata.
    - Also assigned based on profile skin when gamedata importprofilewins event is occouring.
    - Set to your current skin if you complete a Cup, OR if you get equal or better on any existing Cup.
- Successfully reassigned alongside unloadedskin records when a skin is added.
- TEMPORARY: Character ownership of Cup wins are displayed in your latest-log.txt, in lieu of an update to the cupgrid
This commit is contained in:
toaster 2023-05-29 17:16:53 +01:00
parent a36213c435
commit 989070c3f1
7 changed files with 150 additions and 9 deletions

View file

@ -1859,10 +1859,36 @@ void D_SRB2Main(void)
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;
cupheader_t *cup;
for (cup = kartcupheaders; cup; cup = cup->next)
{
for (i = 0; i < KARTGP_MAX; i++)
{
if (cup->windata[i].best_placement == 0)
continue;
cup->windata[i].best_skin.id = importskin;
cup->windata[i].best_skin.unloaded = NULL;
}
}
unloaded_cupheader_t *unloadedcup;
for (unloadedcup = unloadedcupheaders; unloadedcup; unloadedcup = unloadedcup->next)
{
for (i = 0; i < KARTGP_MAX; i++)
{
if (unloadedcup->windata[i].best_placement == 0)
continue;
unloadedcup->windata[i].best_skin.id = importskin;
unloadedcup->windata[i].best_skin.unloaded = NULL;
}
}
CONS_Printf(" Wins for profile \"%s\" imported onto character \"%s\"\n", pr->profilename, skins[importskin].name);
}
}
gamedata->importprofilewins = false;
}

View file

@ -116,6 +116,9 @@ extern preciptype_t curWeather;
struct skinrecord_t
{
UINT32 wins;
// Purely assistive in gamedata save processes
UINT32 _saveid;
};
struct unloaded_skin_t
@ -130,6 +133,12 @@ struct unloaded_skin_t
extern unloaded_skin_t *unloadedskins;
struct skinreference_t
{
unloaded_skin_t *unloaded;
UINT8 id;
};
// mapvisited is now a set of flags that says what we've done in the map.
#define MV_VISITED (1)
#define MV_BEATEN (1<<1)
@ -168,6 +177,7 @@ struct cupwindata_t
UINT8 best_placement;
gp_rank_e best_grade;
boolean got_emerald;
skinreference_t best_skin;
};
// Set if homebrew PWAD stuff has been added.

View file

@ -4466,6 +4466,7 @@ static void G_DoCompleted(void)
grandprixinfo.rank.prisons += numtargets;
grandprixinfo.rank.position = MAXPLAYERS;
grandprixinfo.rank.skin = MAXSKINS;
for (i = 0; i < MAXPLAYERS; i++)
{
@ -4495,7 +4496,12 @@ static void G_DoCompleted(void)
if (players[i].bot == false)
{
grandprixinfo.rank.position = min(grandprixinfo.rank.position, K_GetPodiumPosition(&players[i]));
UINT8 podiumposition = K_GetPodiumPosition(&players[i]);
if (podiumposition <= grandprixinfo.rank.position)
{
grandprixinfo.rank.position = podiumposition;
grandprixinfo.rank.skin = players[i].skin;
}
}
}
}
@ -4955,6 +4961,8 @@ void G_LoadGameData(void)
// Main records
skinreference_t *tempskinreferences = NULL;
if (versionMinor < 3)
{
gamedata->importprofilewins = true;
@ -4966,6 +4974,11 @@ void G_LoadGameData(void)
if (numgamedataskins)
{
tempskinreferences = Z_Malloc(
numgamedataskins * sizeof (skinreference_t),
PU_STATIC,
NULL
);
for (i = 0; i < numgamedataskins; i++)
{
@ -4978,15 +4991,20 @@ void G_LoadGameData(void)
skinrecord_t dummyrecord;
dummyrecord.wins = READUINT32(save.p);
dummyrecord._saveid = i;
CONS_Printf(" (TEMPORARY DISPLAY) skinname is \"%s\", has %u wins\n", skinname, dummyrecord.wins);
tempskinreferences[i].id = MAXSKINS;
if (skin != -1)
{
// We found a skin, so assign the win.
M_Memcpy(&skins[skin].records, &dummyrecord, sizeof(skinrecord_t));
tempskinreferences[i].id = skin;
tempskinreferences[i].unloaded = NULL;
}
else if (dummyrecord.wins)
{
@ -5009,6 +5027,8 @@ void G_LoadGameData(void)
// Finally, copy into.
M_Memcpy(&unloadedskin->records, &dummyrecord, sizeof(skinrecord_t));
tempskinreferences[i].unloaded = unloadedskin;
}
}
}
@ -5100,6 +5120,23 @@ void G_LoadGameData(void)
dummywindata[j].best_grade = (rtemp & 0x70)>>4;
if (rtemp & 0x80)
dummywindata[j].got_emerald = true;
dummywindata[j].best_skin.id = MAXSKINS;
dummywindata[j].best_skin.unloaded = NULL;
if (versionMinor >= 3)
{
UINT32 _saveid = READUINT32(save.p);
if (_saveid < numgamedataskins)
{
const char *charstr = NULL;
if (tempskinreferences[_saveid].unloaded)
charstr = tempskinreferences[_saveid].unloaded->name;
else
charstr = skins[tempskinreferences[_saveid].id].name;
CONS_Printf(" (TEMPORARY DISPLAY) Cup \"%s\" difficulty %u was completed by skin \"%s\"\n", cupname, j, charstr);
M_Memcpy(&dummywindata[j].best_skin, &tempskinreferences[_saveid], sizeof(dummywindata[j].best_skin));
}
}
}
if (versionMinor < 3 && dummywindata[0].best_placement == 0)
@ -5139,6 +5176,9 @@ void G_LoadGameData(void)
}
}
if (tempskinreferences)
Z_Free(tempskinreferences);
// done
P_SaveBufferFree(&save);
@ -5325,7 +5365,7 @@ void G_SaveGameData(void)
}
}
length += 4 + (numgamedatacups * (MAXCUPNAME+4));
length += 4 + (numgamedatacups * (MAXCUPNAME + 4*(1+4)));
if (P_SaveBufferAlloc(&save, length) == false)
@ -5423,6 +5463,8 @@ void G_SaveGameData(void)
{
// numgamedataskins * (SKINNAMESIZE+4)
UINT32 maxid = 0;
for (i = 0; i < numskins; i++)
{
if (skins[i].records.wins == 0)
@ -5432,11 +5474,12 @@ void G_SaveGameData(void)
WRITEUINT32(save.p, skins[i].records.wins);
if (--numgamedataskins == 0)
skins[i].records._saveid = maxid;
if (++maxid == numgamedataskins)
break;
}
if (numgamedataskins)
if (maxid < numgamedataskins)
{
for (unloadedskin = unloadedskins; unloadedskin; unloadedskin = unloadedskin->next)
{
@ -5447,12 +5490,23 @@ void G_SaveGameData(void)
WRITEUINT32(save.p, unloadedskin->records.wins);
if (--numgamedataskins == 0)
unloadedskin->records._saveid = maxid;
if (++maxid == numgamedataskins)
break;
}
}
}
#define GETSKINREFSAVEID(ref, var) \
{ \
if (ref.unloaded != NULL) \
var = ref.unloaded->records._saveid;\
else if (ref.id < numskins)\
var = skins[ref.id].records._saveid; \
else \
var = UINT32_MAX; \
}
WRITEUINT32(save.p, numgamedatamapheaders); // 4
if (numgamedatamapheaders)
@ -5507,7 +5561,7 @@ void G_SaveGameData(void)
if (numgamedatacups)
{
// numgamedatacups * (MAXCUPNAME+4)
// numgamedatacups * (MAXCUPNAME + 4*(1+4))
#define WRITECUPWINDATA(maybeunloadedcup) \
for (i = 0; i < KARTGP_MAX; i++) \
@ -5518,6 +5572,10 @@ void G_SaveGameData(void)
btemp |= 0x80; \
\
WRITEUINT8(save.p, btemp); \
\
GETSKINREFSAVEID(maybeunloadedcup->windata[i].best_skin, j); \
\
WRITEUINT32(save.p, j); \
}
for (cup = kartcupheaders; cup; cup = cup->next)
@ -5552,6 +5610,8 @@ void G_SaveGameData(void)
#undef WRITECUPWINDATA
}
#undef GETSKINREFSAVEID
length = save.p - save.buffer;
FIL_WriteFile(va(pandf, srb2home, gamedatafilename), save.buffer, length);

View file

@ -330,21 +330,37 @@ void K_ResetCeremony(void)
// who's just won on Normal from feeling obligated to complete Easy too.
for (; i >= 0; i--)
{
boolean anymerit = false;
if ((grandprixinfo.cup->windata[i].best_placement == 0) // First run
|| (podiumData.rank.position < grandprixinfo.cup->windata[i].best_placement)) // Later, better run
|| (podiumData.rank.position <= grandprixinfo.cup->windata[i].best_placement)) // Later, better run
{
grandprixinfo.cup->windata[i].best_placement = podiumData.rank.position;
// The following will not occur in unmodified builds, but pre-emptively sanitise gamedata if someone just changes MAXPLAYERS and calls it a day
if (grandprixinfo.cup->windata[i].best_placement > 0x0F)
grandprixinfo.cup->windata[i].best_placement = 0x0F;
anymerit = true;
}
if (podiumData.grade > grandprixinfo.cup->windata[i].best_grade)
if (podiumData.grade >= grandprixinfo.cup->windata[i].best_grade)
{
grandprixinfo.cup->windata[i].best_grade = podiumData.grade;
anymerit = true;
}
if (podiumData.rank.specialWon == true)
{
grandprixinfo.cup->windata[i].got_emerald = true;
anymerit = true;
}
if (anymerit == true)
{
grandprixinfo.cup->windata[i].best_skin.id = podiumData.rank.skin;
grandprixinfo.cup->windata[i].best_skin.unloaded = NULL;
}
}
// Save before playing the noise

View file

@ -26,6 +26,7 @@ struct gpRank_t
UINT8 totalPlayers;
UINT8 position;
UINT8 skin;
UINT32 winPoints;
UINT32 totalPoints;

View file

@ -1034,6 +1034,33 @@ next_token:
unloadedskins = unloadedskin->next;
}
// Now... we assign everything which used this pointer the new skin id.
UINT8 i;
cupheader_t *cup;
for (cup = kartcupheaders; cup; cup = cup->next)
{
for (i = 0; i < KARTGP_MAX; i++)
{
if (cup->windata[i].best_skin.unloaded != unloadedskin)
continue;
cup->windata[i].best_skin.id = numskins;
cup->windata[i].best_skin.unloaded = NULL;
}
}
unloaded_cupheader_t *unloadedcup;
for (unloadedcup = unloadedcupheaders; unloadedcup; unloadedcup = unloadedcup->next)
{
for (i = 0; i < KARTGP_MAX; i++)
{
if (unloadedcup->windata[i].best_skin.unloaded != unloadedskin)
continue;
unloadedcup->windata[i].best_skin.id = numskins;
unloadedcup->windata[i].best_skin.unloaded = NULL;
}
}
// Finally, free.
Z_Free(unloadedskin);

View file

@ -115,6 +115,7 @@ TYPEDEF (skincolor_t);
TYPEDEF (precipprops_t);
TYPEDEF (skinrecord_t);
TYPEDEF (unloaded_skin_t);
TYPEDEF (skinreference_t);
TYPEDEF (recorddata_t);
TYPEDEF (cupwindata_t);
TYPEDEF (scene_t);