Add support for Kart player models

With just a little offcamera dearrowing
This commit is contained in:
GenericHeroGuy 2025-07-21 22:17:58 +02:00
parent e244c3ece4
commit 06f5f8cb86
5 changed files with 90 additions and 77 deletions

View file

@ -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));

View file

@ -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)

View file

@ -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);

View file

@ -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)

View file

@ -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);