From 8cbacdeda7e947a071b626eb67040cbbc8330fa8 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sat, 25 Jan 2025 23:52:53 +0100 Subject: [PATCH] Kart skin compatibility --- src/info.c | 1 + src/info/sprite2.h | 2 + src/r_skins.c | 121 ++++++++++++++++++++++++++++++++++++++++++--- src/r_skins.h | 1 + src/r_things.cpp | 24 +++++++++ src/r_things.h | 1 + src/w_wad.c | 34 ++++++++++++- 7 files changed, 175 insertions(+), 9 deletions(-) diff --git a/src/info.c b/src/info.c index a9f8ec64e..4982dc6e4 100644 --- a/src/info.c +++ b/src/info.c @@ -79,6 +79,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { 0, // SPR2_SIGN 0, // SPR2_XTRA + 0, // SPR2_KART }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) diff --git a/src/info/sprite2.h b/src/info/sprite2.h index 0440bad64..de564fc95 100644 --- a/src/info/sprite2.h +++ b/src/info/sprite2.h @@ -22,3 +22,5 @@ _(DEAD) // Dead _(SIGN) // Finish signpost _(XTRA) // Three Faces of Darkness + +_(KART) // Extra frames from Kart skins diff --git a/src/r_skins.c b/src/r_skins.c index 0ef47fd61..7c545a04c 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -109,6 +109,9 @@ static void Sk_SetDefaultValue(skin_t *skin) skin->flags = 0; strcpy(skin->realname, "Someone"); + strncpy(skin->facerank, "MISSING", 9); + strncpy(skin->facewant, "MISSING", 9); + strncpy(skin->facemmap, "MISSING", 9); skin->starttranscolor = 96; skin->prefcolor = SKINCOLOR_GREEN; skin->supercolor = SKINCOLOR_SUPERGOLD1; @@ -396,6 +399,37 @@ static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) return INT16_MAX; // not found } +#define NUMKARTFRAMES 19 +#define S(f, s) { f - 'A', SPR2_##s }, +static UINT8 KART_TO_SPR2[][2] = { + S('A', STIN) + S('B', STIN) + S('C', STIL) + S('D', STIL) + S('E', STIR) + S('F', STIR) + S('J', SLWN) + S('G', SLWN) + S('K', SLWL) + S('H', SLWL) + S('L', SLWR) + S('I', SLWR) + S('A', FSTN) + S('J', FSTN) + S('C', FSTL) + S('K', FSTL) + S('E', FSTR) + S('L', FSTR) + S('M', DRLN) + S('N', DRLN) + S('O', DRRN) + S('P', DRRN) + S('Q', SPIN) + S('R', KART) + S('S', SIGN) +}; +#undef S + static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin) { UINT16 newlastlump; @@ -427,20 +461,88 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski *lastlump = newlastlump; // okay, make the normal sprite set loading end there }*/ - // load all sprite sets we are aware of... for normal stuff. - for (sprite2 = 0; sprite2 < free_spr2; sprite2++) - R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump); + if (!wadfiles[wadnum]->compatmode) + { + // load all sprite sets we are aware of... for normal stuff. + for (sprite2 = 0; sprite2 < free_spr2; sprite2++) + R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump); + } + else + { + // okay, now we have to get fancy... + // first, just dump all the frames in a temporary def + size_t i; + spritedef_t *sd; + spriteframe_t *sf; + spritedef_t tmp = {}; + const char *sprname = W_CheckNameForNumPwad(wadnum, *lump); + R_AddSingleSpriteDef(sprname, &tmp, wadnum, *lump, *lastlump); + + if (tmp.numframes < NUMKARTFRAMES) + I_Error("R_LoadSkinSprites: too few frames for kart skin"); + + // now shuffle them around to fit the new SPR2 system + // iterate over KART_TO_SPR2, then add any excess frames to SPR2_KART +#define SPR2COUNT sizeof(KART_TO_SPR2)/sizeof(*KART_TO_SPR2) + for (i = 0; i < SPR2COUNT - NUMKARTFRAMES + tmp.numframes; i++) + { + boolean excess = i >= SPR2COUNT; + sf = &tmp.spriteframes[excess ? i - SPR2COUNT + NUMKARTFRAMES : KART_TO_SPR2[i][0]]; + sd = &skin->sprites[excess ? SPR2_KART : KART_TO_SPR2[i][1]]; + sd->spriteframes = Z_Realloc(sd->spriteframes, sizeof(*sd->spriteframes) * (sd->numframes+1), PU_STATIC, NULL); + sd->spriteframes[sd->numframes++] = *sf; + } + Z_Free(tmp.spriteframes); +#undef SPR2COUNT + + // now we have to rotate the drift frames. i hate this. + sd = &skin->sprites[SPR2_DRRN]; + for (i = 0; i < sd->numframes; i++) + { + sf = &sd->spriteframes[i]; + if (sf->rotate != SRF_3D) + continue; + lumpnum_t lastpat = sf->lumppat[7]; + size_t lastid = sf->lumpid[7]; + for (int r = 7; r >= 1; r--) + { + sf->lumppat[r] = sf->lumppat[r-1]; + sf->lumpid[r] = sf->lumpid[r-1]; + } + sf->lumppat[0] = lastpat; + sf->lumpid[0] = lastid; + } + sd = &skin->sprites[SPR2_DRLN]; + for (i = 0; i < sd->numframes; i++) + { + sf = &sd->spriteframes[i]; + if (sf->rotate != SRF_3D) + continue; + lumpnum_t firstpat = sf->lumppat[0]; + size_t firstid = sf->lumpid[0]; + for (int r = 0; r < 8; r++) + { + sf->lumppat[r] = sf->lumppat[r+1]; + sf->lumpid[r] = sf->lumpid[r+1]; + } + sf->lumppat[7] = firstpat; + sf->lumpid[7] = firstid; + } + + R_AddKartFaces(skin); + } if (skin->sprites[0].numframes == 0) I_Error("R_LoadSkinSprites: no frames found for sprite SPR2_%s\n", spr2names[0]); } +#undef NUMKARTFRAMES // returns whether found appropriate property -static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) +static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value, boolean compat) { // custom translation table if (!stricmp(stoken, "startcolor")) - skin->starttranscolor = atoi(value); + skin->starttranscolor = compat ? R_GetPaletteRemap(atoi(value)) : atoi(value); #define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value); // character type identification @@ -492,6 +594,11 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) GETFLAG(MACHINE) #undef GETFLAG +#define GETPATCH(field) else if (compat && !stricmp(stoken, #field)) strncpy(skin->field, value, 8); + GETPATCH(facerank) + GETPATCH(facewant) + GETPATCH(facemmap) + else // let's check if it's a sound, otherwise error out { boolean found = false; @@ -667,7 +774,7 @@ void R_AddSkins(UINT16 wadnum) pos++; } } - else if (!R_ProcessPatchableFields(skin, stoken, value)) + else if (!R_ProcessPatchableFields(skin, stoken, value, wadfiles[wadnum]->compatmode)) CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); next_token: @@ -822,7 +929,7 @@ void R_PatchSkins(UINT16 wadnum) pos++; } } - else if (!R_ProcessPatchableFields(skin, stoken, value)) + else if (!R_ProcessPatchableFields(skin, stoken, value, wadfiles[wadnum]->compatmode)) CONS_Debug(DBG_SETUP, "R_PatchSkins: Unknown keyword '%s' in P_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); } diff --git a/src/r_skins.h b/src/r_skins.h index 102bef3c0..c7bef3c1a 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -42,6 +42,7 @@ struct skin_t skinflags_t flags; char realname[SKINNAMESIZE+1]; // Display name for level completion. + char facerank[9], facewant[9], facemmap[9]; // Arbitrarily named patch lumps // SRB2kart UINT8 kartspeed; diff --git a/src/r_things.cpp b/src/r_things.cpp index 0c2795169..0683f9efc 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -249,6 +249,30 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch sprtemp[frame].flip &= ~(1<sprites[SPR2_XTRA]; + for (size_t f = 0; f < NUMFACES; f++) + { + lumpnum_t lumpnum = W_CheckNumForName(reinterpret_cast(skin) + KART_FACES[f]); // how do you do, fellow C++ers? + if (lumpnum == LUMPERROR) + I_Error("R_AddKartFaces: missing patch %s for skin %s", reinterpret_cast(skin) + KART_FACES[f], skin->name); + R_InstallSpriteLump(WADFILENUM(lumpnum), LUMPNUM(lumpnum), numspritelumps++, f, 0, 0); + } + sd->numframes = NUMFACES; + sd->spriteframes = static_cast(Z_Realloc(sd->spriteframes, sizeof(spriteframe_t)*NUMFACES, PU_STATIC, NULL)); + M_Memcpy(sd->spriteframes, sprtemp, sizeof(spriteframe_t)*NUMFACES); +} +#undef NUMFACES + // Install a single sprite, given its identifying name (4 chars) // // (originally part of R_AddSpriteDefs) diff --git a/src/r_things.h b/src/r_things.h index 0fa20666b..c51ab69ca 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -31,6 +31,7 @@ extern "C" { #define FEETADJUST (4<= 18; +#else + return false; +#endif +} + // try to figure out if a PK3 file needs compatmode enabled (palette remap) static inline boolean CheckCompatZip(UINT16 wadnum) { - if (CheckCompatFilename(wadfiles[wadnum]->filename)) + if (CheckCompatFilename(wadfiles[wadnum]->filename) || CheckCompatSkins(wadnum)) return true; // assume RR/2.2 for PK3s so basegame assets work @@ -311,7 +341,7 @@ static inline boolean CheckCompatZip(UINT16 wadnum) // ditto, but for WADs static inline boolean CheckCompatWad(UINT16 wadnum) { - if (CheckCompatFilename(wadfiles[wadnum]->filename)) + if (CheckCompatFilename(wadfiles[wadnum]->filename) || CheckCompatSkins(wadnum)) return true; // assume Kart/2.1 for WADs so basegame assets work