Do a bunch of stuff to the MD2/3 sprite2 support to get it back to feature parity with before, without going back to being hacky as fuck.

* Store the number of frames per sprite2 run in the spr2frames struct.
* Reintroduce P_GetModelSprite2, to allow for the sprite2 defaulting system to be used to full advantage even in GL.
* Instead of splitting the SUPER and normal SPR2 stuff within the same cell of the struct, have them exist in different cells just like in the "normal" sprite2 structs.
* Allow for just providing spr2 frames in order without specifying which "normal" sprite2 frame it's supposed to replace.

Also:
* Fix FF_VERTICALFLIP-ignoring regression.
* Fix whitespace adjustment in win_dll.c
* Remove bracket in P_GetSkinSprite2 because I realised it was extraneous while making sure P_GetModelSprite2 worked with it.
This commit is contained in:
toaster 2019-11-02 17:52:54 +00:00
parent 7746767735
commit 417f17ebdd
5 changed files with 116 additions and 32 deletions

View File

@ -848,6 +848,63 @@ static boolean HWR_CanInterpolateSprite2(modelspr2frames_t *spr2frame)
return spr2frame->interpolate; return spr2frame->interpolate;
} }
//
// P_GetModelSprite2 (see P_GetSkinSprite2)
// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing.
// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version.
//
static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *player)
{
UINT8 super = 0, i = 0;
if (!md2 || !md2->model || !md2->model->spr2frames || !skin)
return 0;
if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2)
return 0;
while (!md2->model->spr2frames[spr2].numframes
&& spr2 != SPR2_STND
&& ++i != 32) // recursion limiter
{
if (spr2 & FF_SPR2SUPER)
{
super = FF_SPR2SUPER;
spr2 &= ~FF_SPR2SUPER;
continue;
}
switch(spr2)
{
// Normal special cases.
case SPR2_JUMP:
spr2 = ((player
? player->charflags
: skin->flags)
& SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL;
break;
case SPR2_TIRE:
spr2 = ((player
? player->charability
: skin->ability)
== CA_SWIM) ? SPR2_SWIM : SPR2_FLY;
break;
// Use the handy list, that's what it's there for!
default:
spr2 = spr2defaults[spr2];
break;
}
spr2 |= super;
}
if (i >= 32) // probably an infinite loop...
return 0;
return spr2;
}
void HWR_DrawMD2(gr_vissprite_t *spr) void HWR_DrawMD2(gr_vissprite_t *spr)
{ {
FSurfaceInfo Surf; FSurfaceInfo Surf;
@ -906,9 +963,10 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
INT32 durs = spr->mobj->state->tics; INT32 durs = spr->mobj->state->tics;
INT32 tics = spr->mobj->tics; INT32 tics = spr->mobj->tics;
//mdlframe_t *next = NULL; //mdlframe_t *next = NULL;
const UINT8 flip = (UINT8)((spr->mobj->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP); const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP));
spritedef_t *sprdef; spritedef_t *sprdef;
spriteframe_t *sprframe; spriteframe_t *sprframe;
INT32 mod;
float finalscale; float finalscale;
// Apparently people don't like jump frames like that, so back it goes // Apparently people don't like jump frames like that, so back it goes
@ -1018,34 +1076,49 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
tics = spr->mobj->anim_duration; tics = spr->mobj->anim_duration;
} }
//FIXME: this is not yet correct frame = (spr->mobj->frame & FF_FRAMEMASK);
if (spr->mobj->sprite2 && md2->model->spr2frames) if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames)
{ {
spr2 = (spr->mobj->sprite2 & ~FF_SPR2SUPER); spr2 = P_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player);
frame = (spr->mobj->frame & FF_FRAMEMASK); mod = md2->model->spr2frames[spr2].numframes;
if (spr->mobj->sprite2 & FF_SPR2SUPER) #ifndef DONTHIDEDIFFANIMLENGTH // by default, different anim length is masked by the mod
frame = md2->model->spr2frames[spr2].superframes[frame]; if (mod > (INT32)((skin_t *)spr->mobj->skin)->sprites[spr2].numframes)
mod = ((skin_t *)spr->mobj->skin)->sprites[spr2].numframes;
#endif
if (mod)
frame = md2->model->spr2frames[spr2].frames[frame%mod];
else else
frame = md2->model->spr2frames[spr2].frames[frame]; frame = 0;
} }
else else
frame = (spr->mobj->frame & FF_FRAMEMASK); {
mod = md2->model->meshes[0].numFrames;
if (mod)
frame %= mod;
}
#ifdef USE_MODEL_NEXTFRAME #ifdef USE_MODEL_NEXTFRAME
if (cv_grmodels.value == 1 && tics <= durs) #define INTERPOLERATION_LIMIT TICRATE/4
if (cv_grmodels.value == 1 && tics <= durs && tics <= INTERPOLERATION_LIMIT)
{ {
if (spr->mobj->sprite2 && md2->model->spr2frames) if (durs > INTERPOLERATION_LIMIT)
durs = INTERPOLERATION_LIMIT;
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames)
{ {
if (HWR_CanInterpolateSprite2(&md2->model->spr2frames[spr2])) if (mod && HWR_CanInterpolateSprite2(&md2->model->spr2frames[spr2])
&& (spr->mobj->frame & FF_ANIMATE
|| (spr->mobj->state->nextstate != S_NULL
&& states[spr->mobj->state->nextstate].sprite == SPR_PLAY
&& ((P_GetSkinSprite2(spr->mobj->skin, (((spr->mobj->player && spr->mobj->player->powers[pw_super]) ? FF_SPR2SUPER : 0)|states[spr->mobj->state->nextstate].frame) & FF_FRAMEMASK, spr->mobj->player) == spr->mobj->sprite2)))))
{ {
UINT32 framecount = (&((skin_t *)spr->mobj->skin)->sprites[spr->mobj->sprite2])->numframes;
nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1; nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1;
if (nextFrame >= framecount) if (nextFrame >= mod)
nextFrame = 0; nextFrame = 0;
if (spr->mobj->sprite2 & FF_SPR2SUPER) if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE))
nextFrame = md2->model->spr2frames[spr2].superframes[nextFrame];
else
nextFrame = md2->model->spr2frames[spr2].frames[nextFrame]; nextFrame = md2->model->spr2frames[spr2].frames[nextFrame];
else
nextFrame = -1;
} }
} }
else if (HWR_CanInterpolateModel(spr->mobj, md2->model)) else if (HWR_CanInterpolateModel(spr->mobj, md2->model))
@ -1054,7 +1127,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
if (spr->mobj->frame & FF_ANIMATE) if (spr->mobj->frame & FF_ANIMATE)
{ {
nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1; nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1;
if (nextFrame >= spr->mobj->state->var1) if (nextFrame >= (INT32)(spr->mobj->state->var1 + (spr->mobj->state->frame & FF_FRAMEMASK)))
nextFrame = (spr->mobj->state->frame & FF_FRAMEMASK); nextFrame = (spr->mobj->state->frame & FF_FRAMEMASK);
//next = &md2->model->meshes[0].frames[nextFrame]; //next = &md2->model->meshes[0].frames[nextFrame];
} }
@ -1069,13 +1142,14 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
} }
} }
} }
#undef INTERPOLERATION_LIMIT
#endif #endif
//Hurdler: it seems there is still a small problem with mobj angle //Hurdler: it seems there is still a small problem with mobj angle
p.x = FIXED_TO_FLOAT(spr->mobj->x); p.x = FIXED_TO_FLOAT(spr->mobj->x);
p.y = FIXED_TO_FLOAT(spr->mobj->y)+md2->offset; p.y = FIXED_TO_FLOAT(spr->mobj->y)+md2->offset;
if (spr->mobj->eflags & MFE_VERTICALFLIP) if (flip)
p.z = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height); p.z = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height);
else else
p.z = FIXED_TO_FLOAT(spr->mobj->z); p.z = FIXED_TO_FLOAT(spr->mobj->z);

View File

@ -296,7 +296,7 @@ void LoadModelSprite2(model_t *model)
char prefix[6]; char prefix[6];
char name[5]; char name[5];
char interpolation_flag[3]; char interpolation_flag[3];
char framechar[4]; char framechars[4];
UINT8 frame = 0; UINT8 frame = 0;
UINT8 spr2idx; UINT8 spr2idx;
boolean interpolate = false; boolean interpolate = false;
@ -304,10 +304,11 @@ void LoadModelSprite2(model_t *model)
memset(&prefix, 0x00, 6); memset(&prefix, 0x00, 6);
memset(&name, 0x00, 5); memset(&name, 0x00, 5);
memset(&interpolation_flag, 0x00, 3); memset(&interpolation_flag, 0x00, 3);
memset(&framechar, 0x00, 4); memset(&framechars, 0x00, 4);
if (strlen(framename) >= 9) if (strlen(framename) >= 9)
{ {
boolean super;
char *modelframename = framename; char *modelframename = framename;
memcpy(&prefix, modelframename, 5); memcpy(&prefix, modelframename, 5);
modelframename += 5; modelframename += 5;
@ -320,22 +321,31 @@ void LoadModelSprite2(model_t *model)
interpolate = true; interpolate = true;
modelframename += 2; modelframename += 2;
} }
memcpy(&framechar, modelframename, 3); memcpy(&framechars, modelframename, 3);
frame = atoi(framechar);
if ((!memcmp(prefix, "SPR2_", 5)) || (!memcmp(prefix, "SUPER", 5))) if ((super = (!memcmp(prefix, "SUPER", 5))) || (!memcmp(prefix, "SPR2_", 5)))
{ {
spr2idx = 0; spr2idx = 0;
while (spr2idx < NUMPLAYERSPRITES) while (spr2idx < free_spr2)
{ {
if (!memcmp(spr2names[spr2idx], name, 4)) if (!memcmp(spr2names[spr2idx], name, 4))
{ {
if (!spr2frames) if (!spr2frames)
spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES, PU_STATIC, NULL); spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES*2, PU_STATIC, NULL);
if (!memcmp(prefix, "SUPER", 5)) if (super)
spr2frames[spr2idx].superframes[frame] = i; spr2idx |= FF_SPR2SUPER;
if (framechars[0])
{
frame = atoi(framechars);
if (spr2frames[spr2idx].numframes < frame+1)
spr2frames[spr2idx].numframes = frame+1;
}
else else
spr2frames[spr2idx].frames[frame] = i; {
frame = spr2frames[spr2idx].numframes;
spr2frames[spr2idx].numframes++;
}
spr2frames[spr2idx].frames[frame] = i;
spr2frames[spr2idx].interpolate = interpolate; spr2frames[spr2idx].interpolate = interpolate;
break; break;
} }

View File

@ -78,7 +78,7 @@ typedef struct tag_s
typedef struct typedef struct
{ {
INT32 frames[256]; INT32 frames[256];
INT32 superframes[256]; UINT8 numframes;
boolean interpolate; boolean interpolate;
} modelspr2frames_t; } modelspr2frames_t;

View File

@ -2527,7 +2527,7 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2)
return 0; return 0;
while (!(skin->sprites[spr2].numframes) while (!skin->sprites[spr2].numframes
&& spr2 != SPR2_STND && spr2 != SPR2_STND
&& ++i < 32) // recursion limiter && ++i < 32) // recursion limiter
{ {

View File

@ -139,7 +139,7 @@ static loadfunc_t hwdFuncTable[] = {
{"GClipRect", &hwdriver.pfnGClipRect}, {"GClipRect", &hwdriver.pfnGClipRect},
{"ClearMipMapCache", &hwdriver.pfnClearMipMapCache}, {"ClearMipMapCache", &hwdriver.pfnClearMipMapCache},
{"SetSpecialState", &hwdriver.pfnSetSpecialState}, {"SetSpecialState", &hwdriver.pfnSetSpecialState},
{"DrawModel", &hwdriver.pfnDrawModel}, {"DrawModel", &hwdriver.pfnDrawModel},
{"SetTransform", &hwdriver.pfnSetTransform}, {"SetTransform", &hwdriver.pfnSetTransform},
{"GetTextureUsed", &hwdriver.pfnGetTextureUsed}, {"GetTextureUsed", &hwdriver.pfnGetTextureUsed},
{"GetRenderVersion", &hwdriver.pfnGetRenderVersion}, {"GetRenderVersion", &hwdriver.pfnGetRenderVersion},