Add 'sprite2' field to states

This commit is contained in:
Lactozilla 2023-11-12 21:46:49 -03:00
parent 55444cf204
commit 4408f4462e
21 changed files with 2937 additions and 2804 deletions

View file

@ -2578,10 +2578,10 @@ void G_AddGhost(char *defdemoname)
}
gh->oldmo.color = gh->mo->color;
gh->mo->state = states+S_PLAY_STND;
gh->mo->state = &states[S_PLAY_STND];
gh->mo->sprite = gh->mo->state->sprite;
gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK);
//gh->mo->frame = tr_trans30<<FF_TRANSSHIFT;
gh->mo->sprite2 = P_GetStateSprite2(gh->mo->state);
gh->mo->frame = (gh->mo->state->frame & ~FF_FRAMEMASK) | P_GetSprite2StateFrame(gh->mo->state);
gh->mo->flags2 |= MF2_DONTDRAW;
gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible
gh->mo->tics = -1;

View file

@ -5155,9 +5155,9 @@ static void HWR_ProjectSprite(mobj_t *thing)
//Fab : 02-08-98: 'skin' override spritedef currently used for skin
if (thing->skin && thing->sprite == SPR_PLAY)
{
sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2];
sprdef = P_GetSkinSpritedef(thing->skin, thing->sprite2);
#ifdef ROTSPRITE
sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2];
sprinfo = P_GetSkinSpriteInfo(thing->skin, thing->sprite2);
#endif
}
else

View file

@ -1167,61 +1167,24 @@ static boolean HWR_CanInterpolateSprite2(modelspr2frames_t *spr2frame)
return spr2frame->interpolate;
}
//
// HWR_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 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *player)
static modelspr2frames_t *HWR_GetModelSprite2(md2_t *md2, UINT16 spr2)
{
UINT8 super = 0, i = 0;
if (!md2 || !md2->model)
return NULL;
if (!md2 || !md2->model || !md2->model->spr2frames || !skin)
return 0;
boolean is_super = spr2 & SPR2F_SUPER;
if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2)
return 0;
spr2 &= SPR2F_MASK;
while (!md2->model->spr2frames[spr2].numframes
&& spr2 != SPR2_STND
&& ++i != 32) // recursion limiter
{
if (spr2 & FF_SPR2SUPER)
{
super = FF_SPR2SUPER;
spr2 &= ~FF_SPR2SUPER;
continue;
}
if (spr2 >= free_spr2)
return NULL;
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;
}
if (is_super && md2->model->superspr2frames)
return &md2->model->superspr2frames[spr2];
else if (md2->model->spr2frames)
return &md2->model->spr2frames[spr2];
spr2 |= super;
}
if (i >= 32) // probably an infinite loop...
return 0;
return spr2;
return NULL;
}
// Adjust texture coords of model to fit into a patch's max_s and max_t
@ -1277,7 +1240,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
char filename[64];
INT32 frame = 0;
INT32 nextFrame = -1;
UINT8 spr2 = 0;
modelspr2frames_t *spr2frames = NULL;
FTransform p;
FSurfaceInfo Surf;
@ -1507,18 +1470,24 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
tics = (float)spr->mobj->anim_duration;
}
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
sprdef = P_GetSkinSpritedef(spr->mobj->skin, spr->mobj->sprite2);
else
sprdef = &sprites[spr->mobj->sprite];
frame = (spr->mobj->frame & FF_FRAMEMASK);
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames)
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
spr2frames = HWR_GetModelSprite2(md2, spr->mobj->sprite2);
if (spr2frames)
{
spr2 = HWR_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player);
mod = md2->model->spr2frames[spr2].numframes;
mod = spr2frames->numframes;
#ifndef DONTHIDEDIFFANIMLENGTH // by default, different anim length is masked by the mod
if (mod > (INT32)((skin_t *)spr->mobj->skin)->sprites[spr2].numframes)
mod = ((skin_t *)spr->mobj->skin)->sprites[spr2].numframes;
if (mod > (INT32)sprdef->numframes)
mod = sprdef->numframes;
#endif
if (!mod)
mod = 1;
frame = md2->model->spr2frames[spr2].frames[frame%mod];
frame = spr2frames->frames[frame%mod];
}
else
{
@ -1538,13 +1507,39 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
if (durs > INTERPOLERATION_LIMIT)
durs = INTERPOLERATION_LIMIT;
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames)
if (spr2frames)
{
if (HWR_CanInterpolateSprite2(&md2->model->spr2frames[spr2])
boolean is_super = P_IsStateSprite2Super(&states[spr->mobj->state->nextstate]);
// Add/Remove SPR2F_SUPER based on certain conditions
if (spr->mobj->player)
{
if (spr->mobj->player->charflags & SF_NOSUPERSPRITES)
is_super = false;
else if (spr->mobj->player->powers[pw_super])
is_super = true;
}
if (is_super)
{
if (spr->mobj->eflags & MFE_FORCENOSUPER)
is_super = false;
}
else if (spr->mobj->eflags & MFE_FORCESUPER)
is_super = true;
UINT16 next_spr2 = P_GetStateSprite2(&states[spr->mobj->state->nextstate]);
if (is_super)
next_spr2 |= SPR2F_SUPER;
else
next_spr2 &= ~SPR2F_SUPER;
if (HWR_CanInterpolateSprite2(spr2frames)
&& (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)))))
&& ((P_GetSkinSprite2(spr->mobj->skin, next_spr2, spr->mobj->player) == spr->mobj->sprite2)))))
{
nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1;
if (nextFrame >= mod)
@ -1555,7 +1550,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
nextFrame = 0;
}
if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE))
nextFrame = md2->model->spr2frames[spr2].frames[nextFrame];
nextFrame = spr2frames->frames[nextFrame];
else
nextFrame = -1;
}
@ -1589,11 +1584,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
else
p.z = FIXED_TO_FLOAT(interp.z);
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
sprdef = &((skin_t *)spr->mobj->skin)->sprites[spr->mobj->sprite2];
else
sprdef = &sprites[spr->mobj->sprite];
sprframe = &sprdef->spriteframes[spr->mobj->frame & FF_FRAMEMASK];
if (sprframe->rotate || papersprite)

View file

@ -294,6 +294,7 @@ void LoadModelSprite2(model_t *model)
{
INT32 i;
modelspr2frames_t *spr2frames = NULL;
modelspr2frames_t *superspr2frames = NULL;
INT32 numframes = model->meshes[0].numFrames;
char *framename = model->framenames;
@ -337,25 +338,33 @@ void LoadModelSprite2(model_t *model)
spr2idx = 0;
while (spr2idx < free_spr2)
{
modelspr2frames_t *frames = NULL;
if (!memcmp(spr2names[spr2idx], name, 4))
{
if (!spr2frames)
spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES*2, PU_STATIC, NULL);
spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES, PU_STATIC, NULL);
frames = spr2frames;
if (super)
spr2idx |= FF_SPR2SUPER;
{
if (!superspr2frames)
superspr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES, PU_STATIC, NULL);
frames = superspr2frames;
}
if (framechars[0])
{
frame = atoi(framechars);
if (spr2frames[spr2idx].numframes < frame+1)
spr2frames[spr2idx].numframes = frame+1;
if (frames[spr2idx].numframes < frame+1)
frames[spr2idx].numframes = frame+1;
}
else
{
frame = spr2frames[spr2idx].numframes;
spr2frames[spr2idx].numframes++;
frame = frames[spr2idx].numframes;
frames[spr2idx].numframes++;
}
spr2frames[spr2idx].frames[frame] = i;
spr2frames[spr2idx].interpolate = interpolate;
frames[spr2idx].frames[frame] = i;
frames[spr2idx].interpolate = interpolate;
break;
}
spr2idx++;
@ -368,7 +377,10 @@ void LoadModelSprite2(model_t *model)
if (model->spr2frames)
Z_Free(model->spr2frames);
if (model->superspr2frames)
Z_Free(model->superspr2frames);
model->spr2frames = spr2frames;
model->superspr2frames = superspr2frames;
}
//

View file

@ -104,6 +104,7 @@ typedef struct model_s
char *framenames;
boolean interpolate[256];
modelspr2frames_t *spr2frames;
modelspr2frames_t *superspr2frames;
// the max_s and max_t values that the uvs are currently adjusted to
// (if a sprite is used as a texture)

5298
src/info.c

File diff suppressed because it is too large Load diff

View file

@ -1158,7 +1158,7 @@ typedef enum playersprite
SPR2_XTRA, // stuff that isn't in-map - "would this ever need an md2 or variable length animation?"
SPR2_FIRSTFREESLOT,
SPR2_LASTFREESLOT = 0x7f,
SPR2_LASTFREESLOT = 1024, // Do not make higher than SPR2F_MASK
NUMPLAYERSPRITES
} playersprite_t;
@ -4378,6 +4378,7 @@ typedef struct
INT32 var1;
INT32 var2;
statenum_t nextstate;
UINT16 sprite2;
} state_t;
extern state_t states[NUMSTATES];

View file

@ -660,17 +660,15 @@ static int lib_pRemoveMobj(lua_State *L)
return 0;
}
// P_IsValidSprite2 technically doesn't exist, and probably never should... but too much would need to be exposed to allow this to be checked by other methods.
static int lib_pIsValidSprite2(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
UINT8 spr2 = (UINT8)luaL_checkinteger(L, 2);
UINT16 spr2 = (UINT16)luaL_checkinteger(L, 2);
//HUDSAFE
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, (mobj->skin && (((skin_t *)mobj->skin)->sprites[spr2].numframes)));
lua_pushboolean(L, mobj->skin && P_IsValidSprite2(mobj->skin, spr2));
return 1;
}

View file

@ -541,7 +541,7 @@ static int libd_getSprite2Patch(lua_State *L)
UINT8 angle = 0;
spritedef_t *sprdef;
spriteframe_t *sprframe;
boolean super = false; // add FF_SPR2SUPER to sprite2 if true
boolean super = false; // add SPR2F_SUPER to sprite2 if true
HUDONLY
// get skin first!
@ -568,11 +568,12 @@ static int libd_getSprite2Patch(lua_State *L)
if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR2_STND
{
j = lua_tonumber(L, 1);
if (j & FF_SPR2SUPER) // e.g. SPR2_STND|FF_SPR2SUPER
if (j & SPR2F_SUPER) // e.g. SPR2_STND|SPR2F_SUPER
{
super = true;
j &= ~FF_SPR2SUPER; // remove flag so the next check doesn't fail
j &= ~SPR2F_SUPER; // remove flag so the next check doesn't fail
}
if (j >= free_spr2)
return 0;
}
@ -591,17 +592,15 @@ static int libd_getSprite2Patch(lua_State *L)
if (lua_isboolean(L, 2)) // optional boolean for superness
{
super = lua_toboolean(L, 2); // note: this can override FF_SPR2SUPER from sprite number
super = lua_toboolean(L, 2); // note: this can override SPR2F_SUPER from sprite number
lua_remove(L, 2); // remove
}
// if it's not boolean then just assume it's the frame number
if (super)
j |= FF_SPR2SUPER;
j |= SPR2F_SUPER;
j = P_GetSkinSprite2(&skins[i], j, NULL); // feed skin and current sprite2 through to change sprite2 used if necessary
sprdef = &skins[i].sprites[j];
sprdef = P_GetSkinSpritedef(&skins[i], j);
// set frame number
frame = luaL_optinteger(L, 2, 0);
@ -629,7 +628,7 @@ static int libd_getSprite2Patch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle);
if (rot) {
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, &skins[i].sprinfo[j], rot);
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, P_GetSkinSpriteInfo(&skins[i], j), rot);
LUA_PushUserdata(L, rotsprite, META_PATCH);
lua_pushboolean(L, false);
lua_pushboolean(L, true);

View file

@ -167,7 +167,7 @@ static int lib_getSpr2default(lua_State *L)
static int lib_setSpr2default(lua_State *L)
{
playersprite_t i;
UINT8 j = 0;
UINT16 j = 0;
if (hud_running)
return luaL_error(L, "Do not alter spr2defaults[] in HUD rendering code!");

View file

@ -547,7 +547,7 @@ static int mobj_set(lua_State *L)
mo->frame = (UINT32)luaL_checkinteger(L, 3);
break;
case mobj_sprite2:
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), (UINT8)luaL_checkinteger(L, 3), mo->player);
mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), (UINT16)luaL_checkinteger(L, 3), mo->player);
break;
case mobj_anim_duration:
mo->anim_duration = (UINT16)luaL_checkinteger(L, 3);

View file

@ -54,7 +54,8 @@ enum skin {
skin_contspeed,
skin_contangle,
skin_soundsid,
skin_sprites
skin_sprites,
skin_supersprites
};
static const char *const skin_opt[] = {
@ -94,6 +95,7 @@ static const char *const skin_opt[] = {
"contangle",
"soundsid",
"sprites",
"supersprites",
NULL};
#define UNIMPLEMENTED luaL_error(L, LUA_QL("skin_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", skin_opt[field])
@ -218,6 +220,9 @@ static int skin_get(lua_State *L)
case skin_sprites:
LUA_PushUserdata(L, skin->sprites, META_SKINSPRITES);
break;
case skin_supersprites:
LUA_PushUserdata(L, skin->super.sprites, META_SKINSPRITES);
break;
}
return 1;
}
@ -342,17 +347,17 @@ static int lib_getSkinSprite(lua_State *L)
spritedef_t *sksprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITES);
playersprite_t i = luaL_checkinteger(L, 2);
if (i < 0 || i >= NUMPLAYERSPRITES*2)
return luaL_error(L, LUA_QL("skin_t") " field 'sprites' index %d out of range (0 - %d)", i, (NUMPLAYERSPRITES*2)-1);
if (i < 0 || i >= NUMPLAYERSPRITES)
return luaL_error(L, "skin sprites index %d out of range (0 - %d)", i, NUMPLAYERSPRITES-1);
LUA_PushUserdata(L, &sksprites[i], META_SKINSPRITESLIST);
return 1;
}
// #skin.sprites -> NUMPLAYERSPRITES*2
// #skin.sprites -> NUMPLAYERSPRITES
static int lib_numSkinsSprites(lua_State *L)
{
lua_pushinteger(L, NUMPLAYERSPRITES*2);
lua_pushinteger(L, NUMPLAYERSPRITES);
return 1;
}

View file

@ -393,31 +393,40 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
{
skin_t *skin = ((skin_t *)mobj->skin);
UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1;
UINT8 numframes, spr2;
UINT8 numframes;
UINT16 spr2;
boolean is_super = P_IsStateSprite2Super(st);
if (skin)
{
UINT16 stateframe = st->frame;
// Add/Remove FF_SPR2SUPER based on certain conditions
// Add/Remove SPR2F_SUPER based on certain conditions
if (player->charflags & SF_NOSUPERSPRITES)
stateframe = stateframe & ~FF_SPR2SUPER;
is_super = false;
else if (player->powers[pw_super])
stateframe = stateframe | FF_SPR2SUPER;
is_super = true;
if (stateframe & FF_SPR2SUPER)
if (is_super)
{
if (mobj->eflags & MFE_FORCENOSUPER)
stateframe = stateframe & ~FF_SPR2SUPER;
is_super = false;
}
else if (mobj->eflags & MFE_FORCESUPER)
stateframe = stateframe | FF_SPR2SUPER;
is_super = true;
spr2 = P_GetStateSprite2(st);
if (is_super)
spr2 |= SPR2F_SUPER;
else
spr2 &= ~SPR2F_SUPER;
// Get the sprite2 and frame number
spr2 = P_GetSkinSprite2(skin, (stateframe & FF_FRAMEMASK), mobj->player);
numframes = skin->sprites[spr2].numframes;
spr2 = P_GetSkinSprite2(skin, spr2, mobj->player);
if (state == S_PLAY_STND && (spr2 & FF_SPR2SUPER) && skin->sprites[SPR2_WAIT|FF_SPR2SUPER].numframes == 0)
spritedef_t *sprdef = P_GetSkinSpritedef(skin, spr2);
numframes = sprdef->numframes;
if (state == S_PLAY_STND && (spr2 & SPR2F_SUPER) && sprdef[SPR2_WAIT].numframes == 0)
mobj->tics = -1; // If no super wait, don't wait at all
}
else
@ -430,12 +439,19 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
if (mobj->sprite != SPR_PLAY)
{
mobj->sprite = SPR_PLAY;
frame = 0;
frame = P_GetSprite2StateFrame(st);
}
else if (mobj->sprite2 != spr2)
{
if ((st->frame & FF_SPR2MIDSTART) && numframes && P_RandomChance(FRACUNIT/2))
frame = numframes/2;
if (st->frame & FF_SPR2MIDSTART)
{
if (numframes && P_RandomChance(FRACUNIT/2))
frame = numframes/2;
else
frame = 0;
}
else if (numframes)
frame = P_GetSprite2StateFrame(st) % numframes;
else
frame = 0;
}
@ -450,6 +466,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
{
if (mobj->frame & FF_FRAMEMASK)
mobj->frame--;
return P_SetPlayerMobjState(mobj, st->var1);
}
}
@ -539,26 +556,35 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
{
skin_t *skin = ((skin_t *)mobj->skin);
UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1;
UINT8 numframes, spr2;
UINT8 numframes;
UINT16 spr2;
boolean is_super = P_IsStateSprite2Super(st);
if (skin)
{
UINT16 stateframe = st->frame;
// Add/Remove FF_SPR2SUPER based on certain conditions
if (stateframe & FF_SPR2SUPER)
// Add/Remove SPR2F_SUPER based on certain conditions
if (is_super)
{
if (mobj->eflags & MFE_FORCENOSUPER)
stateframe = stateframe & ~FF_SPR2SUPER;
is_super = false;
}
else if (mobj->eflags & MFE_FORCESUPER)
stateframe = stateframe | FF_SPR2SUPER;
is_super = true;
spr2 = P_GetStateSprite2(st);
if (is_super)
spr2 |= SPR2F_SUPER;
else
spr2 &= ~SPR2F_SUPER;
// Get the sprite2 and frame number
spr2 = P_GetSkinSprite2(skin, (stateframe & FF_FRAMEMASK), NULL);
numframes = skin->sprites[spr2].numframes;
spr2 = P_GetSkinSprite2(skin, spr2, NULL);
if (state == S_PLAY_STND && (spr2 & FF_SPR2SUPER) && skin->sprites[SPR2_WAIT|FF_SPR2SUPER].numframes == 0)
spritedef_t *sprdef = P_GetSkinSpritedef(skin, spr2);
numframes = sprdef->numframes;
if (state == S_PLAY_STND && (spr2 & SPR2F_SUPER) && sprdef[SPR2_WAIT].numframes == 0)
mobj->tics = -1; // If no super wait, don't wait at all
}
else
@ -571,12 +597,19 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
if (mobj->sprite != SPR_PLAY)
{
mobj->sprite = SPR_PLAY;
frame = 0;
frame = P_GetSprite2StateFrame(st);
}
else if (mobj->sprite2 != spr2)
{
if ((st->frame & FF_SPR2MIDSTART) && numframes && P_RandomChance(FRACUNIT/2))
frame = numframes/2;
if (st->frame & FF_SPR2MIDSTART)
{
if (numframes && P_RandomChance(FRACUNIT/2))
frame = numframes/2;
else
frame = 0;
}
else if (numframes)
frame = P_GetSprite2StateFrame(st) % numframes;
else
frame = 0;
}
@ -591,6 +624,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
{
if (mobj->frame & FF_FRAMEMASK)
mobj->frame--;
return P_SetMobjState(mobj, st->var1);
}
}
@ -11011,7 +11045,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
if (mobj->skin) // correct inadequecies above.
{
mobj->sprite2 = P_GetSkinSprite2(mobj->skin, (mobj->frame & FF_FRAMEMASK), NULL);
mobj->sprite2 = P_GetSkinSprite2(mobj->skin, P_GetStateSprite2(mobj->state), NULL);
mobj->frame &= ~FF_FRAMEMASK;
}

View file

@ -295,7 +295,7 @@ typedef struct mobj_s
angle_t spriteroll, old_spriteroll, old_spriteroll2;
spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h
UINT8 sprite2; // player sprites
UINT16 sprite2; // player sprites
UINT16 anim_duration; // for FF_ANIMATE states
UINT32 renderflags; // render flags
@ -434,7 +434,7 @@ typedef struct precipmobj_s
angle_t spriteroll, old_spriteroll, old_spriteroll2;
spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h
UINT8 sprite2; // player sprites
UINT16 sprite2; // player sprites
UINT16 anim_duration; // for FF_ANIMATE states
UINT32 renderflags; // render flags

View file

@ -97,6 +97,9 @@
/// \brief Frame flags - Animate: Start at a random place in the animation (mutually exclusive with above)
#define FF_RANDOMANIM 0x40000000
#define SPR2F_MASK 0x7FFF
#define SPR2F_SUPER 0x8000
/** \brief translucency tables
\todo add another asm routine which use the fg and bg indexes in the

View file

@ -1716,7 +1716,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff |= MD_TICS;
if (mobj->sprite != mobj->state->sprite)
diff |= MD_SPRITE;
if (mobj->sprite == SPR_PLAY && mobj->sprite2 != (mobj->state->frame&FF_FRAMEMASK))
if (mobj->sprite == SPR_PLAY && mobj->sprite2 != P_GetStateSprite2(mobj->state))
diff |= MD_SPRITE;
if (mobj->frame != mobj->state->frame)
diff |= MD_FRAME;

View file

@ -4362,7 +4362,7 @@ static void P_DoSuperStuff(player_t *player)
if (!G_CoopGametype())
player->powers[pw_flashing] = flashingtics-1;
if (player->mo->sprite2 & FF_SPR2SUPER)
if (player->mo->sprite2 & SPR2F_SUPER)
P_SetPlayerMobjState(player->mo, player->mo->state-states);
// Inform the netgame that the champion has fallen in the heat of battle.
@ -11328,10 +11328,10 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
}
else
{
if (tails->state != states+chosenstate)
if (tails->state != &states[chosenstate])
{
if (states[chosenstate].sprite == SPR_PLAY)
tails->sprite2 = P_GetSkinSprite2(((skin_t *)tails->skin), (states[chosenstate].frame & FF_FRAMEMASK), player);
tails->sprite2 = P_GetSkinSprite2(((skin_t *)tails->skin), P_GetStateSprite2(&states[chosenstate]), player);
P_SetMobjState(tails, chosenstate);
}
}

View file

@ -40,30 +40,63 @@ skin_t skins[MAXSKINS];
CV_PossibleValue_t skin_cons_t[MAXSKINS+1];
#endif
UINT16 P_GetStateSprite2(state_t *state)
{
if (state->sprite2)
return state->sprite2;
else
{
boolean is_super = state->frame & FF_SPR2SUPER;
UINT16 frame = state->frame & (FF_FRAMEMASK | ~FF_SPR2SUPER);
if (is_super)
frame |= SPR2F_SUPER;
return frame;
}
}
UINT16 P_GetSprite2StateFrame(state_t *state)
{
if (state->sprite2)
return state->frame & FF_FRAMEMASK;
else
return 0;
}
boolean P_IsStateSprite2Super(state_t *state)
{
if (state->sprite2)
{
if (state->sprite2 & SPR2F_SUPER)
return true;
}
else if (state->frame & FF_SPR2SUPER)
return true;
return false;
}
//
// 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.
//
UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
UINT16 P_GetSkinSprite2(skin_t *skin, UINT16 spr2, player_t *player)
{
UINT8 super = 0, i = 0;
UINT16 super = 0;
UINT8 i = 0;
if (!skin)
return 0;
if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2)
return 0;
while (!skin->sprites[spr2].numframes
while (!P_IsValidSprite2(skin, spr2)
&& spr2 != SPR2_STND
&& ++i < 32) // recursion limiter
{
if (spr2 & FF_SPR2SUPER)
if (spr2 & SPR2F_SUPER)
{
super = FF_SPR2SUPER;
spr2 &= ~FF_SPR2SUPER;
super = SPR2F_SUPER;
spr2 &= ~SPR2F_SUPER;
continue;
}
@ -97,6 +130,48 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
return spr2;
}
spritedef_t *P_GetSkinSpritedef(skin_t *skin, UINT16 spr2)
{
if (!skin)
return NULL;
boolean is_super = spr2 & SPR2F_SUPER;
spr2 &= SPR2F_MASK;
if (spr2 >= free_spr2)
return NULL;
if (is_super)
return &skin->super.sprites[spr2];
else
return &skin->sprites[spr2];
}
spriteinfo_t *P_GetSkinSpriteInfo(skin_t *skin, UINT16 spr2)
{
if (!skin)
return NULL;
boolean is_super = spr2 & SPR2F_SUPER;
spr2 &= SPR2F_MASK;
if (spr2 >= free_spr2)
return NULL;
if (is_super)
return &skin->super.sprinfo[spr2];
else
return &skin->sprinfo[spr2];
}
boolean P_IsValidSprite2(skin_t *skin, UINT16 spr2)
{
spritedef_t *sprdef = P_GetSkinSpritedef(skin, spr2);
return sprdef && sprdef->numframes;
}
static void Sk_SetDefaultValue(skin_t *skin)
{
INT32 i;
@ -536,7 +611,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski
newlastlump++;
// load all sprite sets we are aware of... for super!
for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++)
R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump);
R_AddSingleSpriteDef(spr2names[sprite2], &skin->super.sprites[sprite2], wadnum, newlastlump, *lastlump);
newlastlump--;
*lastlump = newlastlump; // okay, make the normal sprite set loading end there

View file

@ -78,9 +78,14 @@ typedef struct
// specific sounds per skin
sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table
spritedef_t sprites[NUMPLAYERSPRITES];
spriteinfo_t sprinfo[NUMPLAYERSPRITES];
// contains super versions too
spritedef_t sprites[NUMPLAYERSPRITES*2];
spriteinfo_t sprinfo[NUMPLAYERSPRITES*2];
struct {
spritedef_t sprites[NUMPLAYERSPRITES];
spriteinfo_t sprinfo[NUMPLAYERSPRITES];
} super;
} skin_t;
/// Externs
@ -100,7 +105,13 @@ INT32 R_GetForcedSkin(INT32 playernum);
void R_AddSkins(UINT16 wadnum, boolean mainfile);
void R_PatchSkins(UINT16 wadnum, boolean mainfile);
UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player);
UINT16 P_GetStateSprite2(state_t *state);
UINT16 P_GetSprite2StateFrame(state_t *state);
UINT16 P_GetSkinSprite2(skin_t *skin, UINT16 spr2, player_t *player);
spritedef_t *P_GetSkinSpritedef(skin_t *skin, UINT16 spr2);
spriteinfo_t *P_GetSkinSpriteInfo(skin_t *skin, UINT16 spr2);
boolean P_IsValidSprite2(skin_t *skin, UINT16 spr2);
boolean P_IsStateSprite2Super(state_t *state);
void R_RefreshSprite2(void);

View file

@ -1673,20 +1673,22 @@ static void R_ProjectSprite(mobj_t *thing)
// decide which patch to use for sprite relative to player
#ifdef RANGECHECK
if ((size_t)(thing->sprite) >= numsprites)
I_Error("R_ProjectSprite: invalid sprite number %d ", thing->sprite);
I_Error("R_ProjectSprite: invalid sprite number %d", thing->sprite);
#endif
frame = thing->frame&FF_FRAMEMASK;
frame = thing->frame & FF_FRAMEMASK;
//Fab : 02-08-98: 'skin' override spritedef currently used for skin
if (thing->skin && thing->sprite == SPR_PLAY)
{
sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2];
sprdef = P_GetSkinSpritedef(thing->skin, thing->sprite2);
#ifdef ROTSPRITE
sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2];
sprinfo = P_GetSkinSpriteInfo(thing->skin, thing->sprite2);
#endif
if (frame >= sprdef->numframes) {
CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(frame));
if (frame >= sprdef->numframes)
{
CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[SPR2_%s] %sframe %s\n"), ((skin_t *)thing->skin)->name, spr2names[thing->sprite2 & SPR2F_MASK], (thing->sprite2 & SPR2F_SUPER) ? "super ": "", sizeu5(frame));
thing->sprite = states[S_UNKNOWN].sprite;
thing->frame = states[S_UNKNOWN].frame;
sprdef = &sprites[thing->sprite];

View file

@ -373,9 +373,11 @@ void ST_LoadFaceGraphics(INT32 skinnum)
spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_LIFEPIC];
faceprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX);
if (skins[skinnum].sprites[(SPR2_XTRA|FF_SPR2SUPER)].numframes > XTRA_LIFEPIC)
spritedef_t *super_sprdef = P_GetSkinSpritedef(&skins[skinnum], SPR2_XTRA|SPR2F_SUPER);
if (super_sprdef->numframes > XTRA_LIFEPIC)
{
sprdef = &skins[skinnum].sprites[SPR2_XTRA|FF_SPR2SUPER];
sprdef = super_sprdef;
sprframe = &sprdef->spriteframes[0];
superprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX);
}