From 06f5f8cb86d83e365fb786457b486d37abf0fdcd Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Mon, 21 Jul 2025 22:17:58 +0200 Subject: [PATCH] Add support for Kart player models With just a little offcamera dearrowing --- src/hardware/hw_md2.c | 14 +++-- src/hardware/hw_model.c | 126 ++++++++++++++++++++-------------------- src/hardware/hw_model.h | 14 ++++- src/r_skins.c | 11 ++-- src/r_skins.h | 2 + 5 files changed, 90 insertions(+), 77 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 232e51531..b14625c49 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -96,14 +96,14 @@ static void md2_freeModel (model_t *model) // load model // // Hurdler: the current path is the Legacy.exe path -static model_t *md2_readModel(const char *filename) +static model_t *md2_readModel(const char *filename, modeltype_t modeltype) { //Filename checking fixed ~Monster Iestyn and Golden if (FIL_FileExists(va("%s"PATHSEP"%s", srb2home, filename))) - return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC); + return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC, modeltype); if (FIL_FileExists(va("%s"PATHSEP"%s", srb2path, filename))) - return LoadModel(va("%s"PATHSEP"%s", srb2path, filename), PU_STATIC); + return LoadModel(va("%s"PATHSEP"%s", srb2path, filename), PU_STATIC, modeltype); return NULL; } @@ -1391,6 +1391,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) spriteframe_t *sprframe; INT32 mod; interpmobjstate_t interp; + modeltype_t modeltype = MODELTYPE_SPRITE; if (R_UsingFrameInterpolation() && !paused) { @@ -1439,6 +1440,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) { md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins]; md2->skin = (skin_t*)spr->mobj->skin-skins; + modeltype = wadfiles[((skin_t*)spr->mobj->skin)->wadnum]->compatmode ? MODELTYPE_OLDPLAYER : MODELTYPE_PLAYER; } else { @@ -1481,7 +1483,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) { //CONS_Debug(DBG_RENDER, "Loading model... (%s)", sprnames[spr->mobj->sprite]); sprintf(filename, "models/%s", md2->filename); - md2->model = md2_readModel(filename); + md2->model = md2_readModel(filename, modeltype); if (md2->model) { @@ -1657,6 +1659,10 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.angley = FIXED_TO_FLOAT(anglef); } + // drift frame unrotation hack... + if (modeltype == MODELTYPE_OLDPLAYER && (spr2 == SPR2_DRRN || spr2 == SPR2_DRLN)) + p.angley += spr2 == SPR2_DRRN ? 45.0f : -45.0f; + { fixed_t anglef = AngleFixed(R_SpriteRotationAngle(spr->mobj, NULL, &interp)); diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 4ed03744b..b0d377976 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -11,6 +11,7 @@ #include "../doomtype.h" #include "../info.h" #include "../z_zone.h" +#include "../r_skins.h" #include "hw_model.h" #include "hw_md2load.h" #include "hw_md3load.h" @@ -145,7 +146,7 @@ tag_t *GetTagByName(model_t *model, char *name, int frame) // convert it to the // internal format. // -model_t *LoadModel(const char *filename, int ztag) +model_t *LoadModel(const char *filename, int ztag, modeltype_t modeltype) { model_t *model; @@ -198,7 +199,7 @@ model_t *LoadModel(const char *filename, int ztag) Optimize(model); GeneratePolygonNormals(model, ztag); - LoadModelSprite2(model); + LoadModelSprite2(model, modeltype); if (!model->spr2frames) LoadModelInterpolationSettings(model); @@ -241,7 +242,7 @@ void HWR_ReloadModels(void) for (s = 0; s < MAXSKINS; s++) { if (md2_playermodels[s].model) - LoadModelSprite2(md2_playermodels[s].model); + LoadModelSprite2(md2_playermodels[s].model, wadfiles[skins[s].wadnum]->compatmode ? MODELTYPE_OLDPLAYER : MODELTYPE_PLAYER); } for (i = 0; i < NUMSPRITES; i++) @@ -255,7 +256,7 @@ void LoadModelInterpolationSettings(model_t *model) { INT32 i; INT32 numframes = model->meshes[0].numFrames; - char *framename = model->framenames; + const char *framename = model->framenames; if (!framename) return; @@ -264,7 +265,7 @@ void LoadModelInterpolationSettings(model_t *model) memcpy(&interpolation_flag, framename + offset, 2); \ model->interpolate[i] = (!memcmp(interpolation_flag, MODEL_INTERPOLATION_FLAG, 2)); - for (i = 0; i < numframes; i++) + for (i = 0; i < numframes; i++, framename += 16) { int offset = (strlen(framename) - 4); char interpolation_flag[3]; @@ -283,87 +284,84 @@ void LoadModelInterpolationSettings(model_t *model) offset--; GET_OFFSET; } - - framename += 16; } #undef GET_OFFSET } -void LoadModelSprite2(model_t *model) +void LoadModelSprite2(model_t *model, modeltype_t modeltype) { INT32 i; modelspr2frames_t *spr2frames = NULL; INT32 numframes = model->meshes[0].numFrames; - char *framename = model->framenames; + const char *framename = model->framenames; + + if (modeltype != MODELTYPE_PLAYER && modeltype != MODELTYPE_OLDPLAYER) + return; if (!framename) return; - for (i = 0; i < numframes; i++) + for (i = 0; i < numframes; i++, framename += 16) { - char prefix[6]; - char name[5]; - char interpolation_flag[3]; - char framechars[4]; - UINT8 frame = 0; + const char *name; + const char *framechars; + UINT8 frame; UINT8 spr2idx; - boolean interpolate = false; + boolean interpolate; + boolean super; - memset(&prefix, 0x00, 6); - memset(&name, 0x00, 5); - memset(&interpolation_flag, 0x00, 3); - memset(&framechars, 0x00, 4); - - if (strlen(framename) >= 9) + if (modeltype == MODELTYPE_OLDPLAYER) { - boolean super; - char *modelframename = framename; - memcpy(&prefix, modelframename, 5); - modelframename += 5; - memcpy(&name, modelframename, 4); - modelframename += 4; - // Oh look - memcpy(&interpolation_flag, modelframename, 2); - if (!memcmp(interpolation_flag, MODEL_INTERPOLATION_FLAG, 2)) - { - interpolate = true; - modelframename += 2; - } - memcpy(&framechars, modelframename, 3); + size_t j; + spr2idx = SPR2_KART; + if (!spr2frames) + spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES*2, PU_STATIC, NULL); - if ((super = (!memcmp(prefix, "SUPER", 5))) || (!memcmp(prefix, "SPR2_", 5))) - { - spr2idx = 0; - while (spr2idx < free_spr2) + // i don't care, just iterate the whole array for every model frame + for (j = 0; j < sizeof(kart2spr2)/sizeof(*kart2spr2); j++) + if (kart2spr2[j][0] == i) { - if (!memcmp(spr2names[spr2idx], name, 4)) - { - if (!spr2frames) - spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES*2, PU_STATIC, NULL); - if (super) - spr2idx |= FF_SPR2SUPER; - if (framechars[0]) - { - frame = atoi(framechars); - if (spr2frames[spr2idx].numframes < frame+1) - spr2frames[spr2idx].numframes = frame+1; - } - else - { - frame = spr2frames[spr2idx].numframes; - spr2frames[spr2idx].numframes++; - } - spr2frames[spr2idx].frames[frame] = i; - spr2frames[spr2idx].interpolate = interpolate; - break; - } - spr2idx++; + spr2idx = kart2spr2[j][1]; + spr2frames[spr2idx].frames[spr2frames[spr2idx].numframes++] = i; } - } + if (spr2idx == SPR2_KART) // excess frame? + spr2frames[spr2idx].frames[spr2frames[spr2idx].numframes++] = i; + continue; } - framename += 16; + if (strlen(framename) < 9 || !((super = !memcmp(framename, "SUPER", 5)) || !memcmp(framename, "SPR2_", 5))) + continue; + + name = framename + 5; + // Oh look + interpolate = !memcmp(framename + 9, MODEL_INTERPOLATION_FLAG, 2); + framechars = framename + (interpolate ? 11 : 9); + + for (spr2idx = 0; spr2idx < free_spr2; spr2idx++) + if (!memcmp(spr2names[spr2idx], name, 4)) + break; + if (spr2idx == free_spr2) + continue; // not found + + if (!spr2frames) + spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES*2, PU_STATIC, NULL); + if (super) + spr2idx |= FF_SPR2SUPER; + + if (framechars[0]) + { + frame = atoi(framechars); + if (spr2frames[spr2idx].numframes < frame+1) + spr2frames[spr2idx].numframes = frame+1; + } + else + { + frame = spr2frames[spr2idx].numframes; + spr2frames[spr2idx].numframes++; + } + spr2frames[spr2idx].frames[frame] = i; + spr2frames[spr2idx].interpolate = interpolate; } if (model->spr2frames) diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h index b42792925..653263dfa 100644 --- a/src/hardware/hw_model.h +++ b/src/hardware/hw_model.h @@ -91,6 +91,13 @@ typedef struct boolean interpolate; } modelspr2frames_t; +typedef enum +{ + MODELTYPE_SPRITE, + MODELTYPE_PLAYER, // this model uses sprite2! + MODELTYPE_OLDPLAYER, // regular sprite translated to sprite2 +} modeltype_t; + typedef struct model_s { int maxNumFrames; @@ -104,9 +111,10 @@ typedef struct model_s char *mdlFilename; boolean unloaded; + modeltype_t modeltype; char *framenames; - boolean interpolate[256]; + UINT8 interpolate[256]; modelspr2frames_t *spr2frames; // the max_s and max_t values that the uvs are currently adjusted to @@ -125,11 +133,11 @@ extern model_t *modelHead; void HWR_ReloadModels(void); tag_t *GetTagByName(model_t *model, char *name, int frame); -model_t *LoadModel(const char *filename, int ztag); +model_t *LoadModel(const char *filename, int ztag, modeltype_t modeltype); void UnloadModel(model_t *model); void Optimize(model_t *model); void LoadModelInterpolationSettings(model_t *model); -void LoadModelSprite2(model_t *model); +void LoadModelSprite2(model_t *model, modeltype_t modeltype); void GenerateVertexNormals(model_t *model); void GeneratePolygonNormals(model_t *model, int ztag); void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame); diff --git a/src/r_skins.c b/src/r_skins.c index 4bc2f6286..18fd69bd4 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -401,7 +401,7 @@ static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) #define NUMKARTFRAMES 19 #define S(f, s) { f - 'A', SPR2_##s }, -static UINT8 KART_TO_SPR2[][2] = { +const UINT8 kart2spr2[26][2] = { S('A', STIN) S('B', STIN) S('C', STIL) @@ -487,13 +487,13 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski 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) + // iterate over kart2spr2, then add any excess frames to SPR2_KART +#define SPR2COUNT sizeof(kart2spr2)/sizeof(*kart2spr2) 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]]; + sf = &tmp.spriteframes[excess ? i - SPR2COUNT + NUMKARTFRAMES : kart2spr2[i][0]]; + sd = &skin->sprites[excess ? SPR2_KART : kart2spr2[i][1]]; sd->spriteframes = Z_Realloc(sd->spriteframes, sizeof(*sd->spriteframes) * (sd->numframes+1), PU_STATIC, NULL); sd->spriteframes[sd->numframes++] = *sf; } @@ -540,7 +540,6 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski R_AddKartFaces(skin); skin->flags |= SF_OLDDEATH|SF_NOGIBS; - } if (skin->sprites[0].numframes == 0) diff --git a/src/r_skins.h b/src/r_skins.h index 6bfc71dc3..de0a0990a 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -82,6 +82,8 @@ extern skin_t skins[MAXSKINS]; extern CV_PossibleValue_t Forceskin_cons_t[]; +extern const UINT8 kart2spr2[26][2]; + /// Function prototypes void R_InitSkins(void);