From 989070c3f10d9ca5e11e93dcaa43c609701cc7b7 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 29 May 2023 17:16:53 +0100 Subject: [PATCH] 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 --- src/d_main.c | 28 +++++++++++++++++++- src/doomstat.h | 10 +++++++ src/g_game.c | 72 +++++++++++++++++++++++++++++++++++++++++++++----- src/k_podium.c | 20 ++++++++++++-- src/k_rank.h | 1 + src/r_skins.c | 27 +++++++++++++++++++ src/typedef.h | 1 + 7 files changed, 150 insertions(+), 9 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 89284a677..5f4cf88ba 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -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; } diff --git a/src/doomstat.h b/src/doomstat.h index ef5ed8a82..619f01db3 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -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. diff --git a/src/g_game.c b/src/g_game.c index 7e5193886..89bc1c0fd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -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); diff --git a/src/k_podium.c b/src/k_podium.c index a9e6f90f1..4c64261ba 100644 --- a/src/k_podium.c +++ b/src/k_podium.c @@ -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 diff --git a/src/k_rank.h b/src/k_rank.h index eb2c420cd..0a4375309 100644 --- a/src/k_rank.h +++ b/src/k_rank.h @@ -26,6 +26,7 @@ struct gpRank_t UINT8 totalPlayers; UINT8 position; + UINT8 skin; UINT32 winPoints; UINT32 totalPoints; diff --git a/src/r_skins.c b/src/r_skins.c index cddd8d116..94ac8bb03 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -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); diff --git a/src/typedef.h b/src/typedef.h index 771313e1c..a54ae82e5 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -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);