Merge branch 'more-sprite2' into 'next'

Add 'sprite2' field to states

See merge request STJr/SRB2!2211
This commit is contained in:
sphere 2024-03-07 12:06:48 +00:00
commit ee96ed12a4
24 changed files with 3048 additions and 2817 deletions

View file

@ -5096,6 +5096,10 @@ struct int_const_s const INT_CONST[] = {
{"RF_SHADOWEFFECTS",RF_SHADOWEFFECTS}, {"RF_SHADOWEFFECTS",RF_SHADOWEFFECTS},
{"RF_DROPSHADOW",RF_DROPSHADOW}, {"RF_DROPSHADOW",RF_DROPSHADOW},
// Animation flags
{"SPR2F_MASK",SPR2F_MASK},
{"SPR2F_SUPER",SPR2F_SUPER},
// Level flags // Level flags
{"LF_SCRIPTISFILE",LF_SCRIPTISFILE}, {"LF_SCRIPTISFILE",LF_SCRIPTISFILE},
{"LF_SPEEDMUSIC",LF_SPEEDMUSIC}, {"LF_SPEEDMUSIC",LF_SPEEDMUSIC},

View file

@ -3530,7 +3530,7 @@ void F_TitleDemoTicker(void)
// ========== // ==========
static skin_t *contskins[2]; static skin_t *contskins[2];
static UINT8 cont_spr2[2][6]; static UINT16 cont_spr2[2][6];
static UINT8 *contcolormaps[2]; static UINT8 *contcolormaps[2];
void F_StartContinue(void) void F_StartContinue(void)

View file

@ -413,7 +413,7 @@ void G_WriteGhostTic(mobj_t *ghost)
{ {
oldghost.sprite2 = ghost->sprite2; oldghost.sprite2 = ghost->sprite2;
ziptic |= GZT_SPR2; ziptic |= GZT_SPR2;
WRITEUINT8(demo_p,oldghost.sprite2); WRITEUINT16(demo_p,oldghost.sprite2);
} }
// Check for sprite set changes // Check for sprite set changes
@ -513,7 +513,7 @@ void G_WriteGhostTic(mobj_t *ghost)
temp = ghost->player->followmobj->z-ghost->z; temp = ghost->player->followmobj->z-ghost->z;
WRITEFIXED(demo_p,temp); WRITEFIXED(demo_p,temp);
if (followtic & FZT_SKIN) if (followtic & FZT_SKIN)
WRITEUINT8(demo_p,ghost->player->followmobj->sprite2); WRITEUINT16(demo_p,ghost->player->followmobj->sprite2);
WRITEUINT16(demo_p,ghost->player->followmobj->sprite); WRITEUINT16(demo_p,ghost->player->followmobj->sprite);
WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK)); WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK));
WRITEUINT16(demo_p,ghost->player->followmobj->color); WRITEUINT16(demo_p,ghost->player->followmobj->color);
@ -575,7 +575,7 @@ void G_ConsGhostTic(void)
if (ziptic & GZT_FRAME) if (ziptic & GZT_FRAME)
demo_p++; demo_p++;
if (ziptic & GZT_SPR2) if (ziptic & GZT_SPR2)
demo_p++; demo_p += (demoversion < 0x0011) ? sizeof(UINT8) : sizeof(UINT16);
if (ziptic & GZT_EXTRA) if (ziptic & GZT_EXTRA)
{ // But wait, there's more! { // But wait, there's more!
@ -644,7 +644,7 @@ void G_ConsGhostTic(void)
// momx, momy and momz // momx, momy and momz
demo_p += (demoversion < 0x000e) ? sizeof(INT16) * 3 : sizeof(fixed_t) * 3; demo_p += (demoversion < 0x000e) ? sizeof(INT16) * 3 : sizeof(fixed_t) * 3;
if (followtic & FZT_SKIN) if (followtic & FZT_SKIN)
demo_p++; demo_p += (demoversion < 0x0011) ? sizeof(UINT8) : sizeof(UINT16);
demo_p += sizeof(UINT16); demo_p += sizeof(UINT16);
demo_p++; demo_p++;
demo_p += (demoversion==0x000c) ? 1 : sizeof(UINT16); demo_p += (demoversion==0x000c) ? 1 : sizeof(UINT16);
@ -726,7 +726,7 @@ void G_GhostTicker(void)
if (ziptic & GZT_FRAME) if (ziptic & GZT_FRAME)
g->oldmo.frame = READUINT8(g->p); g->oldmo.frame = READUINT8(g->p);
if (ziptic & GZT_SPR2) if (ziptic & GZT_SPR2)
g->oldmo.sprite2 = READUINT8(g->p); g->oldmo.sprite2 = (g->version < 0x0011) ? READUINT8(g->p) : READUINT16(g->p);
// Update ghost // Update ghost
P_UnsetThingPosition(g->mo); P_UnsetThingPosition(g->mo);
@ -941,7 +941,7 @@ void G_GhostTicker(void)
follow->z = g->mo->z + temp; follow->z = g->mo->z + temp;
P_SetThingPosition(follow); P_SetThingPosition(follow);
if (followtic & FZT_SKIN) if (followtic & FZT_SKIN)
follow->sprite2 = READUINT8(g->p); follow->sprite2 = (g->version < 0x0011) ? READUINT8(g->p) : READUINT16(g->p);
else else
follow->sprite2 = 0; follow->sprite2 = 0;
follow->sprite = READUINT16(g->p); follow->sprite = READUINT16(g->p);
@ -1056,7 +1056,7 @@ void G_ReadMetalTic(mobj_t *metal)
oldmetal.frame = G_ConvertOldFrameFlags(oldmetal.frame); oldmetal.frame = G_ConvertOldFrameFlags(oldmetal.frame);
} }
if (ziptic & GZT_SPR2) if (ziptic & GZT_SPR2)
oldmetal.sprite2 = READUINT8(metal_p); oldmetal.sprite2 = (metalversion < 0x0011) ? READUINT8(metal_p) : READUINT16(metal_p);
// Set movement, position, and angle // Set movement, position, and angle
// oldmetal contains where you're supposed to be. // oldmetal contains where you're supposed to be.
@ -1199,7 +1199,7 @@ void G_ReadMetalTic(mobj_t *metal)
follow->z = metal->z + temp; follow->z = metal->z + temp;
P_SetThingPosition(follow); P_SetThingPosition(follow);
if (followtic & FZT_SKIN) if (followtic & FZT_SKIN)
follow->sprite2 = READUINT8(metal_p); follow->sprite2 = (metalversion < 0x0011) ? READUINT8(metal_p) : READUINT16(metal_p);
else else
follow->sprite2 = 0; follow->sprite2 = 0;
follow->sprite = READUINT16(metal_p); follow->sprite = READUINT16(metal_p);
@ -1207,7 +1207,7 @@ void G_ReadMetalTic(mobj_t *metal)
if (metalversion < 0x000f) if (metalversion < 0x000f)
follow->frame = G_ConvertOldFrameFlags(follow->frame); follow->frame = G_ConvertOldFrameFlags(follow->frame);
follow->angle = metal->angle; follow->angle = metal->angle;
follow->color = (metalversion==0x000c) ? READUINT8(metal_p) : READUINT16(metal_p); follow->color = (metalversion == 0x000c) ? READUINT8(metal_p) : READUINT16(metal_p);
if (!(followtic & FZT_SPAWNED)) if (!(followtic & FZT_SPAWNED))
{ {
@ -1308,7 +1308,7 @@ void G_WriteMetalTic(mobj_t *metal)
{ {
oldmetal.sprite2 = metal->sprite2; oldmetal.sprite2 = metal->sprite2;
ziptic |= GZT_SPR2; ziptic |= GZT_SPR2;
WRITEUINT8(demo_p,oldmetal.sprite2); WRITEUINT16(demo_p,oldmetal.sprite2);
} }
// Check for sprite set changes // Check for sprite set changes
@ -1383,7 +1383,7 @@ void G_WriteMetalTic(mobj_t *metal)
temp = metal->player->followmobj->z-metal->z; temp = metal->player->followmobj->z-metal->z;
WRITEFIXED(demo_p,temp); WRITEFIXED(demo_p,temp);
if (followtic & FZT_SKIN) if (followtic & FZT_SKIN)
WRITEUINT8(demo_p,metal->player->followmobj->sprite2); WRITEUINT16(demo_p,metal->player->followmobj->sprite2);
WRITEUINT16(demo_p,metal->player->followmobj->sprite); WRITEUINT16(demo_p,metal->player->followmobj->sprite);
WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits
WRITEUINT16(demo_p,metal->player->followmobj->color); WRITEUINT16(demo_p,metal->player->followmobj->color);
@ -2607,10 +2607,10 @@ void G_AddGhost(char *defdemoname)
} }
gh->oldmo.color = gh->mo->color; 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->sprite = gh->mo->state->sprite;
gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK); gh->mo->sprite2 = P_GetStateSprite2(gh->mo->state);
//gh->mo->frame = tr_trans30<<FF_TRANSSHIFT; gh->mo->frame = (gh->mo->state->frame & ~FF_FRAMEMASK) | P_GetSprite2StateFrame(gh->mo->state);
gh->mo->flags2 |= MF2_DONTDRAW; gh->mo->flags2 |= MF2_DONTDRAW;
gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible
gh->mo->tics = -1; gh->mo->tics = -1;

View file

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

View file

@ -1078,30 +1078,47 @@ static boolean HWR_CanInterpolateSprite2(modelspr2frames_t *spr2frame)
return spr2frame->interpolate; return spr2frame->interpolate;
} }
// static modelspr2frames_t *HWR_GetModelSprite2Frames(md2_t *md2, UINT16 spr2)
// 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)
{ {
UINT8 super = 0, i = 0; if (!md2 || !md2->model)
return NULL;
if (!md2 || !md2->model || !md2->model->spr2frames || !skin) boolean is_super = spr2 & SPR2F_SUPER;
return 0;
if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) spr2 &= SPR2F_MASK;
return 0;
while (!md2->model->spr2frames[spr2].numframes if (spr2 >= free_spr2)
return NULL;
if (is_super)
{
modelspr2frames_t *frames = md2->model->superspr2frames;
if (frames && md2->model->superspr2frames[spr2].numframes)
return &md2->model->superspr2frames[spr2];
}
if (md2->model->spr2frames)
return &md2->model->spr2frames[spr2];
return NULL;
}
static modelspr2frames_t *HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT16 spr2, player_t *player)
{
UINT16 super = 0;
UINT8 i = 0;
if (!md2 || !md2->model || !skin)
return HWR_GetModelSprite2Frames(md2, 0);
while (!HWR_GetModelSprite2Frames(md2, spr2)
&& spr2 != SPR2_STND && spr2 != SPR2_STND
&& ++i != 32) // recursion limiter && ++i < 32) // recursion limiter
{ {
if (spr2 & FF_SPR2SUPER) if (spr2 & SPR2F_SUPER)
{ {
super = FF_SPR2SUPER; super = SPR2F_SUPER;
spr2 &= ~FF_SPR2SUPER; spr2 &= ~SPR2F_SUPER;
continue; continue;
} }
@ -1130,9 +1147,9 @@ static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t
} }
if (i >= 32) // probably an infinite loop... if (i >= 32) // probably an infinite loop...
return 0; spr2 = 0;
return spr2; return HWR_GetModelSprite2Frames(md2, spr2);
} }
// Adjust texture coords of model to fit into a patch's max_s and max_t // Adjust texture coords of model to fit into a patch's max_s and max_t
@ -1188,7 +1205,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
char filename[64]; char filename[64];
INT32 frame = 0; INT32 frame = 0;
INT32 nextFrame = -1; INT32 nextFrame = -1;
UINT8 spr2 = 0; modelspr2frames_t *spr2frames = NULL;
FTransform p; FTransform p;
FSurfaceInfo Surf; FSurfaceInfo Surf;
@ -1418,18 +1435,24 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
tics = (float)spr->mobj->anim_duration; 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); 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->skin, spr->mobj->sprite2, spr->mobj->player);
if (spr2frames)
{ {
spr2 = HWR_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player); mod = spr2frames->numframes;
mod = md2->model->spr2frames[spr2].numframes;
#ifndef DONTHIDEDIFFANIMLENGTH // by default, different anim length is masked by the mod #ifndef DONTHIDEDIFFANIMLENGTH // by default, different anim length is masked by the mod
if (mod > (INT32)((skin_t *)spr->mobj->skin)->sprites[spr2].numframes) if (mod > (INT32)sprdef->numframes)
mod = ((skin_t *)spr->mobj->skin)->sprites[spr2].numframes; mod = sprdef->numframes;
#endif #endif
if (!mod) if (!mod)
mod = 1; mod = 1;
frame = md2->model->spr2frames[spr2].frames[frame%mod]; frame = spr2frames->frames[frame % mod];
} }
else else
{ {
@ -1449,13 +1472,18 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
if (durs > INTERPOLERATION_LIMIT) if (durs > INTERPOLERATION_LIMIT)
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]) UINT16 next_spr2 = P_GetStateSprite2(&states[spr->mobj->state->nextstate]);
// Add or remove SPR2F_SUPER based on certain conditions
next_spr2 = P_ApplySuperFlagToSprite2(next_spr2, spr->mobj);
if (HWR_CanInterpolateSprite2(spr2frames)
&& (spr->mobj->frame & FF_ANIMATE && (spr->mobj->frame & FF_ANIMATE
|| (spr->mobj->state->nextstate != S_NULL || (spr->mobj->state->nextstate != S_NULL
&& states[spr->mobj->state->nextstate].sprite == SPR_PLAY && 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; nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1;
if (nextFrame >= mod) if (nextFrame >= mod)
@ -1466,7 +1494,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
nextFrame = 0; nextFrame = 0;
} }
if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE)) if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE))
nextFrame = md2->model->spr2frames[spr2].frames[nextFrame]; nextFrame = spr2frames->frames[nextFrame];
else else
nextFrame = -1; nextFrame = -1;
} }
@ -1502,11 +1530,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
else else
p.z = FIXED_TO_FLOAT(interp.z); 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]; sprframe = &sprdef->spriteframes[spr->mobj->frame & FF_FRAMEMASK];
if (sprframe->rotate || papersprite) if (sprframe->rotate || papersprite)

View file

@ -292,6 +292,7 @@ void LoadModelSprite2(model_t *model)
{ {
INT32 i; INT32 i;
modelspr2frames_t *spr2frames = NULL; modelspr2frames_t *spr2frames = NULL;
modelspr2frames_t *superspr2frames = NULL;
INT32 numframes = model->meshes[0].numFrames; INT32 numframes = model->meshes[0].numFrames;
char *framename = model->frameNames; char *framename = model->frameNames;
@ -335,25 +336,33 @@ void LoadModelSprite2(model_t *model)
spr2idx = 0; spr2idx = 0;
while (spr2idx < free_spr2) while (spr2idx < free_spr2)
{ {
modelspr2frames_t *frames = NULL;
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*2, PU_STATIC, NULL); spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES, PU_STATIC, NULL);
frames = spr2frames;
if (super) if (super)
spr2idx |= FF_SPR2SUPER; {
if (!superspr2frames)
superspr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES, PU_STATIC, NULL);
frames = superspr2frames;
}
if (framechars[0]) if (framechars[0])
{ {
frame = atoi(framechars); frame = atoi(framechars);
if (spr2frames[spr2idx].numframes < frame+1) if (frames[spr2idx].numframes < frame+1)
spr2frames[spr2idx].numframes = frame+1; frames[spr2idx].numframes = frame+1;
} }
else else
{ {
frame = spr2frames[spr2idx].numframes; frame = frames[spr2idx].numframes;
spr2frames[spr2idx].numframes++; frames[spr2idx].numframes++;
} }
spr2frames[spr2idx].frames[frame] = i; frames[spr2idx].frames[frame] = i;
spr2frames[spr2idx].interpolate = interpolate; frames[spr2idx].interpolate = interpolate;
break; break;
} }
spr2idx++; spr2idx++;
@ -366,7 +375,10 @@ void LoadModelSprite2(model_t *model)
if (model->spr2frames) if (model->spr2frames)
Z_Free(model->spr2frames); Z_Free(model->spr2frames);
if (model->superspr2frames)
Z_Free(model->superspr2frames);
model->spr2frames = spr2frames; model->spr2frames = spr2frames;
model->superspr2frames = superspr2frames;
} }
// //

View file

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

5290
src/info.c

File diff suppressed because it is too large Load diff

View file

@ -1078,9 +1078,6 @@ typedef enum sprite
NUMSPRITES NUMSPRITES
} spritenum_t; } spritenum_t;
// Make sure to be conscious of FF_FRAMEMASK and the fact sprite2 is stored as a UINT8 whenever you change this table.
// Currently, FF_FRAMEMASK is 0xff, or 255 - but the second half is used by FF_SPR2SUPER, so the limitation is 0x7f.
// Since this is zero-based, there can be at most 128 different SPR2_'s without changing that.
typedef enum playersprite typedef enum playersprite
{ {
SPR2_STND = 0, SPR2_STND = 0,
@ -1160,15 +1157,17 @@ typedef enum playersprite
SPR2_XTRA, // stuff that isn't in-map - "would this ever need an md2 or variable length animation?" SPR2_XTRA, // stuff that isn't in-map - "would this ever need an md2 or variable length animation?"
SPR2_FIRSTFREESLOT, SPR2_FIRSTFREESLOT,
SPR2_LASTFREESLOT = 0x7f, SPR2_LASTFREESLOT = 1024, // Do not make higher than SPR2F_MASK (currently 0x3FF) plus one
NUMPLAYERSPRITES NUMPLAYERSPRITES
} playersprite_t; } playersprite_t;
// SPR2_XTRA enum
#define XTRA_LIFEPIC 0 // Life icon patch {
#define XTRA_CHARSEL 1 // Character select picture XTRA_LIFEPIC,
#define XTRA_CONTINUE 2 // Continue icon XTRA_CHARSEL,
#define XTRA_ENDING 3 // Ending finale patches XTRA_CONTINUE,
XTRA_ENDING
};
typedef enum state typedef enum state
{ {
@ -4380,6 +4379,7 @@ typedef struct
INT32 var1; INT32 var1;
INT32 var2; INT32 var2;
statenum_t nextstate; statenum_t nextstate;
UINT16 sprite2;
} state_t; } state_t;
extern state_t states[NUMSTATES]; extern state_t states[NUMSTATES];

View file

@ -674,17 +674,15 @@ static int lib_pRemoveMobj(lua_State *L)
return 0; 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) static int lib_pIsValidSprite2(lua_State *L)
{ {
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); 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 //HUDSAFE
INLEVEL INLEVEL
if (!mobj) if (!mobj)
return LUA_ErrInvalid(L, "mobj_t"); 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; return 1;
} }
@ -3039,6 +3037,9 @@ static int lib_rFrame2Char(lua_State *L)
return 2; return 2;
} }
// R_SKINS
////////////
// R_SetPlayerSkin technically doesn't exist either, although it's basically just SetPlayerSkin and SetPlayerSkinByNum handled in one place for convenience // R_SetPlayerSkin technically doesn't exist either, although it's basically just SetPlayerSkin and SetPlayerSkinByNum handled in one place for convenience
static int lib_rSetPlayerSkin(lua_State *L) static int lib_rSetPlayerSkin(lua_State *L)
{ {
@ -3101,6 +3102,47 @@ static int lib_rSkinUsable(lua_State *L)
return 1; return 1;
} }
static int lib_pGetStateSprite2(lua_State *L)
{
int statenum = luaL_checkinteger(L, 1);
if (statenum < 0 || statenum >= NUMSTATES)
return luaL_error(L, "state %d out of range (0 - %d)", statenum, NUMSTATES-1);
lua_pushinteger(L, P_GetStateSprite2(&states[statenum]));
return 1;
}
static int lib_pGetSprite2StateFrame(lua_State *L)
{
int statenum = luaL_checkinteger(L, 1);
if (statenum < 0 || statenum >= NUMSTATES)
return luaL_error(L, "state %d out of range (0 - %d)", statenum, NUMSTATES-1);
lua_pushinteger(L, P_GetSprite2StateFrame(&states[statenum]));
return 1;
}
static int lib_pIsStateSprite2Super(lua_State *L)
{
int statenum = luaL_checkinteger(L, 1);
if (statenum < 0 || statenum >= NUMSTATES)
return luaL_error(L, "state %d out of range (0 - %d)", statenum, NUMSTATES-1);
lua_pushboolean(L, P_IsStateSprite2Super(&states[statenum]));
return 1;
}
// Not a real function. Who cares? I know I don't.
static int lib_pGetSuperSprite2(lua_State *L)
{
int animID = luaL_checkinteger(L, 1) & SPR2F_MASK;
if (animID < 0 || animID >= NUMPLAYERSPRITES)
return luaL_error(L, "sprite2 %d out of range (0 - %d)", animID, NUMPLAYERSPRITES-1);
lua_pushinteger(L, animID | SPR2F_SUPER);
return 1;
}
// R_DATA // R_DATA
//////////// ////////////
@ -4506,7 +4548,13 @@ static luaL_Reg lib[] = {
{"R_Char2Frame",lib_rChar2Frame}, {"R_Char2Frame",lib_rChar2Frame},
{"R_Frame2Char",lib_rFrame2Char}, {"R_Frame2Char",lib_rFrame2Char},
{"R_SetPlayerSkin",lib_rSetPlayerSkin}, {"R_SetPlayerSkin",lib_rSetPlayerSkin},
// r_skins
{"R_SkinUsable",lib_rSkinUsable}, {"R_SkinUsable",lib_rSkinUsable},
{"P_GetStateSprite2",lib_pGetStateSprite2},
{"P_GetSprite2StateFrame",lib_pGetSprite2StateFrame},
{"P_IsStateSprite2Super",lib_pIsStateSprite2Super},
{"P_GetSuperSprite2",lib_pGetSuperSprite2},
// r_data // r_data
{"R_CheckTextureNumForName",lib_rCheckTextureNumForName}, {"R_CheckTextureNumForName",lib_rCheckTextureNumForName},

View file

@ -556,7 +556,7 @@ static int libd_getSprite2Patch(lua_State *L)
UINT8 angle = 0; UINT8 angle = 0;
spritedef_t *sprdef; spritedef_t *sprdef;
spriteframe_t *sprframe; spriteframe_t *sprframe;
boolean super = false; // add FF_SPR2SUPER to sprite2 if true boolean super = false; // add SPR2F_SUPER to sprite2 if true
HUDONLY HUDONLY
// get skin first! // get skin first!
@ -583,11 +583,12 @@ static int libd_getSprite2Patch(lua_State *L)
if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR2_STND if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR2_STND
{ {
j = lua_tonumber(L, 1); 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; 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) if (j >= free_spr2)
return 0; return 0;
} }
@ -606,17 +607,15 @@ static int libd_getSprite2Patch(lua_State *L)
if (lua_isboolean(L, 2)) // optional boolean for superness 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 lua_remove(L, 2); // remove
} }
// if it's not boolean then just assume it's the frame number // if it's not boolean then just assume it's the frame number
if (super) 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 = P_GetSkinSpritedef(skins[i], j);
sprdef = &skins[i]->sprites[j];
// set frame number // set frame number
frame = luaL_optinteger(L, 2, 0); frame = luaL_optinteger(L, 2, 0);
@ -644,7 +643,7 @@ static int libd_getSprite2Patch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle); INT32 rot = R_GetRollAngle(rollangle);
if (rot) { if (rot) {
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), &skins[i]->sprinfo[j], rot); patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), P_GetSkinSpriteInfo(skins[i], j), rot);
LUA_PushUserdata(L, rotsprite, META_PATCH); LUA_PushUserdata(L, rotsprite, META_PATCH);
lua_pushboolean(L, false); lua_pushboolean(L, false);
lua_pushboolean(L, true); lua_pushboolean(L, true);

View file

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

View file

@ -564,7 +564,7 @@ static int mobj_set(lua_State *L)
mo->frame = (UINT32)luaL_checkinteger(L, 3); mo->frame = (UINT32)luaL_checkinteger(L, 3);
break; break;
case mobj_sprite2: 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; break;
case mobj_anim_duration: case mobj_anim_duration:
mo->anim_duration = (UINT16)luaL_checkinteger(L, 3); mo->anim_duration = (UINT16)luaL_checkinteger(L, 3);

View file

@ -55,6 +55,7 @@ enum skin {
skin_contangle, skin_contangle,
skin_soundsid, skin_soundsid,
skin_sprites, skin_sprites,
skin_supersprites,
skin_natkcolor skin_natkcolor
}; };
@ -95,6 +96,7 @@ static const char *const skin_opt[] = {
"contangle", "contangle",
"soundsid", "soundsid",
"sprites", "sprites",
"supersprites",
"natkcolor", "natkcolor",
NULL}; NULL};
@ -220,6 +222,9 @@ static int skin_get(lua_State *L)
case skin_sprites: case skin_sprites:
LUA_PushUserdata(L, skin->sprites, META_SKINSPRITES); LUA_PushUserdata(L, skin->sprites, META_SKINSPRITES);
break; break;
case skin_supersprites:
LUA_PushUserdata(L, skin->super.sprites, META_SKINSPRITES);
break;
case skin_natkcolor: case skin_natkcolor:
lua_pushinteger(L, skin->natkcolor); lua_pushinteger(L, skin->natkcolor);
break; break;
@ -347,17 +352,17 @@ static int lib_getSkinSprite(lua_State *L)
spritedef_t *sksprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITES); spritedef_t *sksprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITES);
playersprite_t i = luaL_checkinteger(L, 2); playersprite_t i = luaL_checkinteger(L, 2);
if (i < 0 || i >= NUMPLAYERSPRITES*2) if (i < 0 || i >= NUMPLAYERSPRITES)
return luaL_error(L, LUA_QL("skin_t") " field 'sprites' index %d out of range (0 - %d)", i, (NUMPLAYERSPRITES*2)-1); return luaL_error(L, "skin sprites index %d out of range (0 - %d)", i, NUMPLAYERSPRITES-1);
LUA_PushUserdata(L, &sksprites[i], META_SKINSPRITESLIST); LUA_PushUserdata(L, &sksprites[i], META_SKINSPRITESLIST);
return 1; return 1;
} }
// #skin.sprites -> NUMPLAYERSPRITES*2 // #skin.sprites -> NUMPLAYERSPRITES
static int lib_numSkinsSprites(lua_State *L) static int lib_numSkinsSprites(lua_State *L)
{ {
lua_pushinteger(L, NUMPLAYERSPRITES*2); lua_pushinteger(L, NUMPLAYERSPRITES);
return 1; return 1;
} }

View file

@ -12056,7 +12056,7 @@ static void M_HandleConnectIP(INT32 choice)
static fixed_t multi_tics; static fixed_t multi_tics;
static UINT8 multi_frame; static UINT8 multi_frame;
static UINT8 multi_spr2; static UINT16 multi_spr2;
static boolean multi_paused; static boolean multi_paused;
static boolean multi_invcolor; static boolean multi_invcolor;

View file

@ -85,9 +85,15 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum)
// //
static void P_SetupStateAnimation(mobj_t *mobj, state_t *st) static void P_SetupStateAnimation(mobj_t *mobj, state_t *st)
{ {
INT32 animlength = (mobj->sprite == SPR_PLAY && mobj->skin) INT32 animlength;
? (INT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes) - 1
: st->var1; if (mobj->sprite == SPR_PLAY && mobj->skin)
{
spritedef_t *spritedef = P_GetSkinSpritedef(mobj->skin, mobj->sprite2);
animlength = (INT32)(spritedef->numframes);
}
else
animlength = st->var1;
if (!(st->frame & FF_ANIMATE)) if (!(st->frame & FF_ANIMATE))
return; return;
@ -138,8 +144,13 @@ FUNCINLINE static ATTRINLINE void P_CycleStateAnimation(mobj_t *mobj)
} }
// sprite2 version of above // sprite2 version of above
if (mobj->skin && (((++mobj->frame) & FF_FRAMEMASK) >= (UINT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes))) if (mobj->skin)
{
spritedef_t *spritedef = P_GetSkinSpritedef(mobj->skin, mobj->sprite2);
UINT32 anim_length = (UINT32)(spritedef->numframes);
if (((++mobj->frame) & FF_FRAMEMASK) >= anim_length)
mobj->frame &= ~FF_FRAMEMASK; mobj->frame &= ~FF_FRAMEMASK;
}
} }
// //
@ -395,31 +406,23 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
{ {
skin_t *skin = ((skin_t *)mobj->skin); skin_t *skin = ((skin_t *)mobj->skin);
UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1;
UINT8 numframes, spr2; UINT8 numframes;
UINT16 spr2;
if (skin) if (skin)
{ {
UINT16 stateframe = st->frame; spr2 = P_GetStateSprite2(st);
// Add/Remove FF_SPR2SUPER based on certain conditions // Add or remove SPR2F_SUPER based on certain conditions
if (player->charflags & SF_NOSUPERSPRITES || (player->powers[pw_carry] == CR_NIGHTSMODE && (player->charflags & SF_NONIGHTSSUPER))) spr2 = P_ApplySuperFlagToSprite2(spr2, mobj);
stateframe = stateframe & ~FF_SPR2SUPER;
else if (player->powers[pw_super] || (player->powers[pw_carry] == CR_NIGHTSMODE && (player->charflags & SF_SUPER)))
stateframe = stateframe | FF_SPR2SUPER;
if (stateframe & FF_SPR2SUPER) // Get the needed sprite2 and frame number
{ spr2 = P_GetSkinSprite2(skin, spr2, mobj->player);
if (mobj->eflags & MFE_FORCENOSUPER)
stateframe = stateframe & ~FF_SPR2SUPER;
}
else if (mobj->eflags & MFE_FORCESUPER)
stateframe = stateframe | FF_SPR2SUPER;
// Get the sprite2 and frame number spritedef_t *sprdef = P_GetSkinSpritedef(skin, spr2);
spr2 = P_GetSkinSprite2(skin, (stateframe & FF_FRAMEMASK), mobj->player); numframes = sprdef->numframes;
numframes = skin->sprites[spr2].numframes;
if (state == S_PLAY_STND && (spr2 & FF_SPR2SUPER) && skin->sprites[SPR2_WAIT|FF_SPR2SUPER].numframes == 0) 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 mobj->tics = -1; // If no super wait, don't wait at all
} }
else else
@ -432,15 +435,22 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
if (mobj->sprite != SPR_PLAY) if (mobj->sprite != SPR_PLAY)
{ {
mobj->sprite = SPR_PLAY; mobj->sprite = SPR_PLAY;
frame = 0; frame = P_GetSprite2StateFrame(st);
} }
else if (mobj->sprite2 != spr2) else if (mobj->sprite2 != spr2)
{ {
if ((st->frame & FF_SPR2MIDSTART) && numframes && P_RandomChance(FRACUNIT/2)) if (st->frame & FF_SPR2MIDSTART)
{
if (numframes && P_RandomChance(FRACUNIT/2))
frame = numframes/2; frame = numframes/2;
else else
frame = 0; frame = 0;
} }
else if (numframes)
frame = P_GetSprite2StateFrame(st) % numframes;
else
frame = 0;
}
if (frame >= numframes) if (frame >= numframes)
{ {
@ -452,6 +462,7 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
{ {
if (mobj->frame & FF_FRAMEMASK) if (mobj->frame & FF_FRAMEMASK)
mobj->frame--; mobj->frame--;
return P_SetPlayerMobjState(mobj, st->var1); return P_SetPlayerMobjState(mobj, st->var1);
} }
} }
@ -539,26 +550,23 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
{ {
skin_t *skin = ((skin_t *)mobj->skin); skin_t *skin = ((skin_t *)mobj->skin);
UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1;
UINT8 numframes, spr2; UINT8 numframes;
UINT16 spr2;
if (skin) if (skin)
{ {
UINT16 stateframe = st->frame; spr2 = P_GetStateSprite2(st);
// Add/Remove FF_SPR2SUPER based on certain conditions // Add or remove SPR2F_SUPER based on certain conditions
if (stateframe & FF_SPR2SUPER) spr2 = P_ApplySuperFlagToSprite2(spr2, mobj);
{
if (mobj->eflags & MFE_FORCENOSUPER)
stateframe = stateframe & ~FF_SPR2SUPER;
}
else if (mobj->eflags & MFE_FORCESUPER)
stateframe = stateframe | FF_SPR2SUPER;
// Get the sprite2 and frame number // Get the needed sprite2 and frame number
spr2 = P_GetSkinSprite2(skin, (stateframe & FF_FRAMEMASK), NULL); spr2 = P_GetSkinSprite2(skin, spr2, NULL);
numframes = skin->sprites[spr2].numframes;
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 mobj->tics = -1; // If no super wait, don't wait at all
} }
else else
@ -571,15 +579,22 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
if (mobj->sprite != SPR_PLAY) if (mobj->sprite != SPR_PLAY)
{ {
mobj->sprite = SPR_PLAY; mobj->sprite = SPR_PLAY;
frame = 0; frame = P_GetSprite2StateFrame(st);
} }
else if (mobj->sprite2 != spr2) else if (mobj->sprite2 != spr2)
{ {
if ((st->frame & FF_SPR2MIDSTART) && numframes && P_RandomChance(FRACUNIT/2)) if (st->frame & FF_SPR2MIDSTART)
{
if (numframes && P_RandomChance(FRACUNIT/2))
frame = numframes/2; frame = numframes/2;
else else
frame = 0; frame = 0;
} }
else if (numframes)
frame = P_GetSprite2StateFrame(st) % numframes;
else
frame = 0;
}
if (frame >= numframes) if (frame >= numframes)
{ {
@ -591,6 +606,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
{ {
if (mobj->frame & FF_FRAMEMASK) if (mobj->frame & FF_FRAMEMASK)
mobj->frame--; mobj->frame--;
return P_SetMobjState(mobj, st->var1); return P_SetMobjState(mobj, st->var1);
} }
} }
@ -11193,7 +11209,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
if (mobj->skin) // correct inadequecies above. 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; mobj->frame &= ~FF_FRAMEMASK;
} }

View file

@ -308,7 +308,7 @@ typedef struct mobj_s
angle_t spriteroll, old_spriteroll, old_spriteroll2; angle_t spriteroll, old_spriteroll, old_spriteroll2;
spritenum_t sprite; // used to find patch_t and flip value spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h 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 UINT16 anim_duration; // for FF_ANIMATE states
UINT32 renderflags; // render flags UINT32 renderflags; // render flags
@ -451,7 +451,7 @@ typedef struct precipmobj_s
angle_t spriteroll, old_spriteroll, old_spriteroll2; angle_t spriteroll, old_spriteroll, old_spriteroll2;
spritenum_t sprite; // used to find patch_t and flip value spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h 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 UINT16 anim_duration; // for FF_ANIMATE states
UINT32 renderflags; // render flags UINT32 renderflags; // render flags

View file

@ -97,6 +97,11 @@
/// \brief Frame flags - Animate: Start at a random place in the animation (mutually exclusive with above) /// \brief Frame flags - Animate: Start at a random place in the animation (mutually exclusive with above)
#define FF_RANDOMANIM 0x40000000 #define FF_RANDOMANIM 0x40000000
/// \brief Animation flags: Bits used for the animation ID
#define SPR2F_MASK 0x3FF
/// \brief Animation flags: "Super" flag
#define SPR2F_SUPER 0x400
/** \brief translucency tables /** \brief translucency tables
\todo add another asm routine which use the fg and bg indexes in the \todo add another asm routine which use the fg and bg indexes in the

View file

@ -1882,7 +1882,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff |= MD_TICS; diff |= MD_TICS;
if (mobj->sprite != mobj->state->sprite) if (mobj->sprite != mobj->state->sprite)
diff |= MD_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; diff |= MD_SPRITE;
if (mobj->frame != mobj->state->frame) if (mobj->frame != mobj->state->frame)
diff |= MD_FRAME; diff |= MD_FRAME;
@ -2066,7 +2066,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
if (diff & MD_SPRITE) { if (diff & MD_SPRITE) {
WRITEUINT16(save_p, mobj->sprite); WRITEUINT16(save_p, mobj->sprite);
if (mobj->sprite == SPR_PLAY) if (mobj->sprite == SPR_PLAY)
WRITEUINT8(save_p, mobj->sprite2); WRITEUINT16(save_p, mobj->sprite2);
} }
if (diff & MD_FRAME) if (diff & MD_FRAME)
{ {
@ -3096,12 +3096,12 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
if (diff & MD_SPRITE) { if (diff & MD_SPRITE) {
mobj->sprite = READUINT16(save_p); mobj->sprite = READUINT16(save_p);
if (mobj->sprite == SPR_PLAY) if (mobj->sprite == SPR_PLAY)
mobj->sprite2 = READUINT8(save_p); mobj->sprite2 = READUINT16(save_p);
} }
else { else {
mobj->sprite = mobj->state->sprite; mobj->sprite = mobj->state->sprite;
if (mobj->sprite == SPR_PLAY) if (mobj->sprite == SPR_PLAY)
mobj->sprite2 = mobj->state->frame&FF_FRAMEMASK; mobj->sprite2 = P_GetStateSprite2(mobj->state);
} }
if (diff & MD_FRAME) if (diff & MD_FRAME)
{ {

View file

@ -1400,7 +1400,7 @@ void P_DoSuperDetransformation(player_t *player)
if (!G_CoopGametype()) if (!G_CoopGametype())
player->powers[pw_flashing] = flashingtics-1; player->powers[pw_flashing] = flashingtics-1;
if (player->mo->sprite2 & FF_SPR2SUPER) if (player->mo->sprite2 & SPR2F_SUPER)
P_SetMobjState(player->mo, player->mo->state-states); P_SetMobjState(player->mo, player->mo->state-states);
// Inform the netgame that the champion has fallen in the heat of battle. // Inform the netgame that the champion has fallen in the heat of battle.
@ -11417,10 +11417,10 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
} }
else else
{ {
if (tails->state != states+chosenstate) if (tails->state != &states[chosenstate])
{ {
if (states[chosenstate].sprite == SPR_PLAY) 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); P_SetMobjState(tails, chosenstate);
} }
} }

View file

@ -35,30 +35,87 @@
INT32 numskins = 0; INT32 numskins = 0;
skin_t **skins = NULL; skin_t **skins = NULL;
// // Gets the animation ID of a state
// P_GetSkinSprite2 UINT16 P_GetStateSprite2(state_t *state)
// 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)
{ {
UINT8 super = 0, i = 0; if (state->sprite2)
return state->sprite2;
else
{
// Transform the state frame into an animation ID
UINT32 stateframe = state->frame & FF_FRAMEMASK;
UINT16 spr2 = stateframe & ~FF_SPR2SUPER;
if (stateframe & FF_SPR2SUPER)
spr2 |= SPR2F_SUPER;
return spr2;
}
}
// Gets the starting frame of an animation
UINT16 P_GetSprite2StateFrame(state_t *state)
{
if (state->sprite2)
return state->frame & FF_FRAMEMASK;
else
return 0;
}
// Checks if a state should use the "super" variant of the animation
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;
}
// Applies SPR2F_SUPER to an animation based on the actor's state
UINT16 P_ApplySuperFlagToSprite2(UINT16 spr2, mobj_t *mobj)
{
if (mobj->player)
{
if (mobj->player->charflags & SF_NOSUPERSPRITES || (mobj->player->powers[pw_carry] == CR_NIGHTSMODE && (mobj->player->charflags & SF_NONIGHTSSUPER)))
spr2 &= ~SPR2F_SUPER;
else if (mobj->player->powers[pw_super] || (mobj->player->powers[pw_carry] == CR_NIGHTSMODE && (mobj->player->charflags & SF_SUPER)))
spr2 |= SPR2F_SUPER;
}
if (spr2 & SPR2F_SUPER)
{
if (mobj->eflags & MFE_FORCENOSUPER)
spr2 &= ~SPR2F_SUPER;
}
else if (mobj->eflags & MFE_FORCESUPER)
spr2 |= SPR2F_SUPER;
return spr2;
}
// For non-super players, this 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.
UINT16 P_GetSkinSprite2(skin_t *skin, UINT16 spr2, player_t *player)
{
UINT16 super = 0;
UINT8 i = 0;
if (!skin) if (!skin)
return 0; return 0;
if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) while (!P_IsValidSprite2(skin, spr2)
return 0;
while (!skin->sprites[spr2].numframes
&& spr2 != SPR2_STND && spr2 != SPR2_STND
&& ++i < 32) // recursion limiter && ++i < 32) // recursion limiter
{ {
if (spr2 & FF_SPR2SUPER) if (spr2 & SPR2F_SUPER)
{ {
super = FF_SPR2SUPER; super = SPR2F_SUPER;
spr2 &= ~FF_SPR2SUPER; spr2 &= ~SPR2F_SUPER;
continue; continue;
} }
@ -92,6 +149,51 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
return spr2; return spr2;
} }
// Gets the spritedef of a skin animation
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];
}
// Gets the spriteinfo of a skin animation
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];
}
// Checks if a skin animation is valid
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) static void Sk_SetDefaultValue(skin_t *skin)
{ {
INT32 i; INT32 i;
@ -500,10 +602,10 @@ static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
return INT16_MAX; // not found return INT16_MAX; // not found
} }
static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin, UINT8 start_spr2) static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin, UINT16 start_spr2)
{ {
UINT16 newlastlump; UINT16 newlastlump;
UINT8 sprite2; UINT16 sprite2;
*lump += 1; // start after S_SKIN *lump += 1; // start after S_SKIN
*lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END *lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END
@ -523,7 +625,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski
newlastlump++; newlastlump++;
// load all sprite sets we are aware of... for super! // load all sprite sets we are aware of... for super!
for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++) 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--; newlastlump--;
*lastlump = newlastlump; // okay, make the normal sprite set loading end there *lastlump = newlastlump; // okay, make the normal sprite set loading end there

View file

@ -80,9 +80,14 @@ typedef struct
// specific sounds per skin // specific sounds per skin
sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table
spritedef_t sprites[NUMPLAYERSPRITES];
spriteinfo_t sprinfo[NUMPLAYERSPRITES];
// contains super versions too // contains super versions too
spritedef_t sprites[NUMPLAYERSPRITES*2]; struct {
spriteinfo_t sprinfo[NUMPLAYERSPRITES*2]; spritedef_t sprites[NUMPLAYERSPRITES];
spriteinfo_t sprinfo[NUMPLAYERSPRITES];
} super;
} skin_t; } skin_t;
/// Externs /// Externs
@ -102,7 +107,14 @@ INT32 R_GetForcedSkin(INT32 playernum);
void R_AddSkins(UINT16 wadnum, boolean mainfile); void R_AddSkins(UINT16 wadnum, boolean mainfile);
void R_PatchSkins(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);
UINT16 P_ApplySuperFlagToSprite2(UINT16 spr2, mobj_t *mobj);
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); void R_RefreshSprite2(void);

View file

@ -1579,20 +1579,22 @@ static void R_ProjectSprite(mobj_t *thing)
// decide which patch to use for sprite relative to player // decide which patch to use for sprite relative to player
#ifdef RANGECHECK #ifdef RANGECHECK
if ((size_t)(thing->sprite) >= numsprites) 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 #endif
frame = thing->frame&FF_FRAMEMASK; frame = thing->frame & FF_FRAMEMASK;
//Fab : 02-08-98: 'skin' override spritedef currently used for skin //Fab : 02-08-98: 'skin' override spritedef currently used for skin
if (thing->skin && thing->sprite == SPR_PLAY) if (thing->skin && thing->sprite == SPR_PLAY)
{ {
sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2]; sprdef = P_GetSkinSpritedef(thing->skin, thing->sprite2);
#ifdef ROTSPRITE #ifdef ROTSPRITE
sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2]; sprinfo = P_GetSkinSpriteInfo(thing->skin, thing->sprite2);
#endif #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->sprite = states[S_UNKNOWN].sprite;
thing->frame = states[S_UNKNOWN].frame; thing->frame = states[S_UNKNOWN].frame;
sprdef = &sprites[thing->sprite]; sprdef = &sprites[thing->sprite];

View file

@ -371,9 +371,11 @@ void ST_LoadFaceGraphics(INT32 skinnum)
spritedef_t *sprdef = &skins[skinnum]->sprites[SPR2_XTRA]; spritedef_t *sprdef = &skins[skinnum]->sprites[SPR2_XTRA];
spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_LIFEPIC]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_LIFEPIC];
faceprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); 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]; sprframe = &sprdef->spriteframes[0];
superprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); superprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX);
} }