diff --git a/src/dehacked.c b/src/dehacked.c index 8187ad62c..20f835981 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6978,8 +6978,10 @@ struct { {"FF_VERTICALFLIP",FF_VERTICALFLIP}, {"FF_PAPERSPRITE",FF_PAPERSPRITE}, {"FF_SPR2ENDSTATE",FF_SPR2ENDSTATE}, - {"FF_MIDDLESTARTCHANCE",FF_MIDDLESTARTCHANCE}, + {"FF_SPR2MIDSTART",FF_SPR2MIDSTART}, {"FF_ANIMATE",FF_ANIMATE}, + {"FF_RANDOMANIM",FF_RANDOMANIM}, + {"FF_GLOBALANIM",FF_GLOBALANIM}, {"FF_FULLBRIGHT",FF_FULLBRIGHT}, {"FF_TRANSMASK",FF_TRANSMASK}, {"FF_TRANSSHIFT",FF_TRANSSHIFT}, diff --git a/src/info.c b/src/info.c index 884217611..c73a5798f 100644 --- a/src/info.c +++ b/src/info.c @@ -474,8 +474,8 @@ enum playersprite free_spr2 = SPR2_FIRSTFREESLOT; state_t states[NUMSTATES] = { // frame is masked through FF_FRAMEMASK - // FF_ANIMATE (0x4000) makes simple state animations (var1 #frames, var2 tic delay) - // FF_FULLBRIGHT (0x8000) activates the fullbright colormap + // FF_ANIMATE makes simple state animations (var1 #frames, var2 tic delay) + // FF_FULLBRIGHT activates the fullbright colormap // use FF_TRANS10 - FF_TRANS90 for easy translucency // (or tr_trans10<frame & FF_ANIMATE)) + return; + if (st->var1 == 0 || st->var2 == 0) + { + mobj->frame &= ~FF_ANIMATE; + return; // Crash/stupidity prevention + } + + mobj->anim_duration = (UINT16)st->var2; + + if (st->frame & FF_GLOBALANIM) + { + // Attempt to account for the pre-ticker for objects spawned on load + if (!leveltime) return; + + mobj->anim_duration -= (leveltime + 2) % st->var2; // Duration synced to timer + mobj->frame += ((leveltime + 2) / st->var2) % (st->var1 + 1); // Frame synced to timer (duration taken into account) + } + else if (st->frame & FF_RANDOMANIM) + { + mobj->frame += P_RandomKey(st->var1 + 1); // Random starting frame + mobj->anim_duration -= P_RandomKey(st->var2); // Random duration for first frame + } +} + // // P_CycleStateAnimation // @@ -588,7 +618,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) } else if (mobj->sprite2 != spr2) { - if ((st->frame & FF_MIDDLESTARTCHANCE) && numframes && P_RandomChance(FRACUNIT/2)) + if ((st->frame & FF_SPR2MIDSTART) && numframes && P_RandomChance(FRACUNIT/2)) frame = numframes/2; else frame = 0; @@ -621,8 +651,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) { mobj->sprite = st->sprite; mobj->frame = st->frame; - if ((st->frame & (FF_ANIMATE|FF_MIDDLESTARTCHANCE)) == (FF_ANIMATE|FF_MIDDLESTARTCHANCE)) - mobj->frame += P_RandomKey(st->var1+1); + P_SetupStateAnimation(mobj, st); } // Modified handling. @@ -689,7 +718,6 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) st = &states[state]; mobj->state = st; mobj->tics = st->tics; - mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set // Player animations if (st->sprite == SPR_PLAY) @@ -714,7 +742,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) } else if (mobj->sprite2 != spr2) { - if ((st->frame & FF_MIDDLESTARTCHANCE) && numframes && P_RandomChance(FRACUNIT/2)) + if ((st->frame & FF_SPR2MIDSTART) && numframes && P_RandomChance(FRACUNIT/2)) frame = numframes/2; else frame = 0; @@ -736,8 +764,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) { mobj->sprite = st->sprite; mobj->frame = st->frame; - if ((st->frame & (FF_ANIMATE|FF_MIDDLESTARTCHANCE)) == (FF_ANIMATE|FF_MIDDLESTARTCHANCE)) - mobj->frame += P_RandomKey(st->var1+1); + P_SetupStateAnimation(mobj, st); } // Modified handling. @@ -792,7 +819,7 @@ boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state) mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; - mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set + P_SetupStateAnimation(mobj, st); return true; } @@ -811,7 +838,7 @@ static boolean P_SetPrecipMobjState(precipmobj_t *mobj, statenum_t state) mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; - mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set + P_SetupStateAnimation((mobj_t*)mobj, st); return true; } @@ -8000,7 +8027,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits.. - mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set + P_SetupStateAnimation(mobj, st); mobj->friction = ORIG_FRICTION; @@ -8226,7 +8253,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits.. - mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set + P_SetupStateAnimation((mobj_t*)mobj, st); // set subsector and/or block links P_SetPrecipitationThingPosition(mobj); diff --git a/src/p_pspr.h b/src/p_pspr.h index a0e7be275..97d7adb94 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -37,18 +37,12 @@ /// \brief Frame flags: only the frame number - 0 to 511 (Frames from 0 to 63, Sprite2 number uses full range) #define FF_FRAMEMASK 0x1ff -/// \brief Frame flags: Flip sprite vertically (relative to what it should be for its gravity) -#define FF_VERTICALFLIP 0x400 -/// \brief Frame flags: Thin, paper-like sprite (for collision equivalent, see MF_PAPERCOLLISION) -#define FF_PAPERSPRITE 0x800 -/// \brief Frame flags: A change of state at the end of Sprite2 animation + +/// \brief Frame flags - SPR2: A change of state at the end of Sprite2 animation #define FF_SPR2ENDSTATE 0x1000 -/// \brief Frame flags: 50% of starting in middle of animation (Sprite2 and FF_ANIMATE) -#define FF_MIDDLESTARTCHANCE 0x2000 -/// \brief Frame flags: Simple stateless animation -#define FF_ANIMATE 0x4000 -/// \brief Frame flags: frame always appears full bright -#define FF_FULLBRIGHT 0x8000 +/// \brief Frame flags - SPR2: 50% of starting in middle of Sprite2 animation +#define FF_SPR2MIDSTART 0x2000 + /// \brief Frame flags: 0 = no trans(opaque), 1-15 = transl. table #define FF_TRANSMASK 0xf0000 /// \brief shift for FF_TRANSMASK @@ -64,6 +58,20 @@ #define FF_TRANS80 (tr_trans80<