Mobj thinker freeze condition rework

- There's a freeze cheat bool to freeze everything except for players.
- There's a level freeze bool to freeze literally everything.
- There's a frozen bool on mobj_t to explicitly control freeze status on an object.
This commit is contained in:
Sally Coolatta 2023-09-18 03:24:58 -04:00
parent 9ba5a93407
commit c9291b0f61
14 changed files with 108 additions and 14 deletions

View file

@ -534,6 +534,7 @@ void D_RegisterClientCommands(void)
// add cheats
COM_AddDebugCommand("noclip", Command_CheatNoClip_f);
COM_AddDebugCommand("god", Command_CheatGod_f);
COM_AddDebugCommand("freeze", Command_CheatFreeze_f);
COM_AddDebugCommand("setrings", Command_Setrings_f);
COM_AddDebugCommand("setspheres", Command_Setspheres_f);
COM_AddDebugCommand("setlives", Command_Setlives_f);
@ -5737,6 +5738,13 @@ static void Got_Cheat(UINT8 **cp, INT32 playernum)
break;
}
case CHEAT_FREEZE: {
const char *status = P_FreezeCheat() ? "off" : "on";
P_SetFreezeCheat( !P_FreezeCheat() );
CV_CheaterWarning(targetPlayer, va("freeze %s", status));
break;
}
case NUMBER_OF_CHEATS:
break;
}

View file

@ -25,6 +25,8 @@ void K_UnsetDialogue(void);
void K_DrawDialogue(void);
void K_TickDialogue(void);
boolean K_DialogueFreeze(void);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -48,6 +48,7 @@ private:
bool syllable;
bool dismissable;
bool freeze;
void Init(void);
//void Unset(void);

View file

@ -435,7 +435,7 @@ void K_HandleFollower(player_t *player)
}
else // follower exists, woo!
{
if (player->follower->hitlag != 0)
if (P_MobjIsFrozen(player->follower))
{
// Don't update frames in hitlag
return;

View file

@ -303,6 +303,14 @@ void Command_CheatGod_f(void)
D_Cheat(consoleplayer, CHEAT_GOD);
}
void Command_CheatFreeze_f(void)
{
REQUIRE_CHEATS;
REQUIRE_INLEVEL;
D_Cheat(consoleplayer, CHEAT_FREEZE);
}
void Command_Scale_f(void)
{
const double scaled = atof(COM_Argv(1));

View file

@ -41,6 +41,7 @@ typedef enum {
CHEAT_RESPAWNAT,
CHEAT_GIVEPOWERUP,
CHEAT_SPHERES,
CHEAT_FREEZE,
NUMBER_OF_CHEATS
} cheat_t;
@ -74,6 +75,7 @@ void OP_ObjectplaceMovement(player_t *player);
//
void Command_CheatNoClip_f(void);
void Command_CheatGod_f(void);
void Command_CheatFreeze_f(void);
void Command_Savecheckpoint_f(void);
void Command_Setrings_f(void);
void Command_Setspheres_f(void);

View file

@ -333,6 +333,8 @@ void P_FlashPal(player_t *pl, UINT16 type, UINT16 duration);
#define PAL_RECYCLE 3
#define PAL_NUKE 4
boolean P_MobjIsFrozen(mobj_t *mobj);
//
// P_ENEMY
//

View file

@ -573,7 +573,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
return BMIT_CONTINUE;
// Ignore the collision if BOTH things are in hitlag.
if (thing->hitlag > 0 && tm.thing->hitlag > 0)
if (P_MobjIsFrozen(thing) && P_MobjIsFrozen(tm.thing))
return BMIT_CONTINUE;
if ((thing->flags & MF_NOCLIPTHING) || !(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING)))

View file

@ -9937,6 +9937,7 @@ void P_MobjThinker(mobj_t *mobj)
mobj->flags2 &= ~(MF2_ALREADYHIT);
// Don't run any thinker code while in hitlag
mobj->eflags &= ~(MFE_PAUSED);
if ((mobj->player ? mobj->hitlag - mobj->player->nullHitlag : mobj->hitlag) > 0)
{
mobj->eflags |= MFE_PAUSED;
@ -9971,11 +9972,14 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->type == MT_HITLAG && mobj->hitlag == 0)
mobj->renderflags &= ~RF_DONTDRAW;
*/
}
if (P_MobjIsFrozen(mobj))
{
return;
}
mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG|MFE_JUSTBOUNCEDWALL|MFE_DAMAGEHITLAG|MFE_SLOPELAUNCHED|MFE_PAUSED);
mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG|MFE_JUSTBOUNCEDWALL|MFE_DAMAGEHITLAG|MFE_SLOPELAUNCHED);
// sal: what the hell? is there any reason this isn't done, like, literally ANYWHERE else?
P_SetTarget(&tm.floorthing, NULL);

View file

@ -433,6 +433,8 @@ struct mobj_t
INT32 script_args[NUM_SCRIPT_ARGS];
char *script_stringargs[NUM_SCRIPT_STRINGARGS];
boolean frozen;
// WARNING: New fields must be added separately to savegame and Lua.
};

View file

@ -2534,7 +2534,7 @@ typedef enum
MD2_WAYPOINTCAP = 1<<25,
MD2_KITEMCAP = 1<<26,
MD2_ITNEXT = 1<<27,
MD2_LASTMOMZ = 1<<28,
MD2_FROZEN = 1<<28,
MD2_TERRAIN = 1<<29,
MD2_WATERSKIP = 1<<30,
MD2_LIGHTLEVEL = (INT32)(1U<<31),
@ -2725,7 +2725,7 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
}
// not the default but the most probable
if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0 || mobj->pmomz != 0)
if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0 || mobj->pmomz != 0 || mobj->lastmomz != 0)
diff |= MD_MOM;
if (mobj->radius != mobj->info->radius)
diff |= MD_RADIUS;
@ -2847,8 +2847,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
diff2 |= MD2_KITEMCAP;
if (mobj->itnext)
diff2 |= MD2_ITNEXT;
if (mobj->lastmomz)
diff2 |= MD2_LASTMOMZ;
if (mobj->frozen)
diff2 |= MD2_FROZEN;
if (mobj->terrain != NULL || mobj->terrainOverlay != NULL)
diff2 |= MD2_TERRAIN;
@ -2911,6 +2911,7 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
WRITEFIXED(save->p, mobj->momy);
WRITEFIXED(save->p, mobj->momz);
WRITEFIXED(save->p, mobj->pmomz);
WRITEFIXED(save->p, mobj->lastmomz);
}
if (diff & MD_RADIUS)
WRITEFIXED(save->p, mobj->radius);
@ -3114,9 +3115,9 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
{
WRITEINT32(save->p, mobj->dispoffset);
}
if (diff2 & MD2_LASTMOMZ)
if (diff2 & MD2_FROZEN)
{
WRITEINT32(save->p, mobj->lastmomz);
WRITEUINT8(save->p, mobj->frozen);
}
if (diff2 & MD2_TERRAIN)
{
@ -4093,6 +4094,7 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
mobj->momy = READFIXED(save->p);
mobj->momz = READFIXED(save->p);
mobj->pmomz = READFIXED(save->p);
mobj->lastmomz = READFIXED(save->p);
} // otherwise they're zero, and the memset took care of it
if (diff & MD_RADIUS)
@ -4347,9 +4349,9 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
{
mobj->dispoffset = READINT32(save->p);
}
if (diff2 & MD2_LASTMOMZ)
if (diff2 & MD2_FROZEN)
{
mobj->lastmomz = READINT32(save->p);
mobj->frozen = (boolean)READUINT8(save->p);
}
if (diff2 & MD2_TERRAIN)
{

View file

@ -52,6 +52,63 @@
tic_t leveltime;
boolean thinkersCompleted;
static boolean g_freezeCheat;
static boolean g_freezeLevel;
boolean P_LevelIsFrozen(void)
{
return (g_freezeLevel || g_freezeCheat);
}
boolean P_FreezeCheat(void)
{
return (g_freezeLevel || g_freezeCheat);
}
void P_SetFreezeCheat(boolean value)
{
g_freezeCheat = value;
}
void P_SetFreezeLevel(boolean value)
{
g_freezeLevel = value;
}
boolean P_MobjIsFrozen(mobj_t *mobj)
{
if (g_freezeCheat == true)
{
// freeze cheat
switch (mobj->type)
{
case MT_PLAYER:
{
break;
}
default:
{
return true;
}
}
}
if (g_freezeLevel == true)
{
// level totally frozen
return true;
}
if ((mobj->eflags & MFE_PAUSED) == MFE_PAUSED)
{
// hitlag
return true;
}
// manual
return mobj->frozen;
}
INT32 P_AltFlip(INT32 n, tic_t tics)
{
return leveltime % (2 * tics) < tics ? n : -(n);

View file

@ -27,6 +27,12 @@ extern "C" {
extern tic_t leveltime;
extern boolean thinkersCompleted;
boolean P_LevelIsFrozen(void);
boolean P_FreezeCheat(void);
void P_SetFreezeCheat(boolean value);
void P_SetFreezeLevel(boolean value);
boolean P_MobjIsFrozen(mobj_t *mobj);
// Called by G_Ticker. Carries out all thinking of enemies and players.
void Command_Numthinkers_f(void);
void Command_CountMobjs_f(void);

View file

@ -3118,7 +3118,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
mo = player->mo;
if (mo->hitlag > 0 || player->playerstate == PST_DEAD)
if (P_MobjIsFrozen(mo) || player->playerstate == PST_DEAD)
{
// Do not move the camera while in hitlag!
// The camera zooming out after you got hit makes it hard to focus on the vibration.
@ -4212,7 +4212,7 @@ void P_PlayerThink(player_t *player)
ALL ABOVE THIS BLOCK OCCURS EVEN WITH HITLAG
/ ------------------------------------------ */
if (player->mo->hitlag > 0)
if (P_MobjIsFrozen(player->mo))
{
return;
}
@ -4550,7 +4550,7 @@ void P_IncrementGriefValue(player_t *player, UINT32 *grief, const UINT32 griefMa
INT32 progress = player->distancetofinishprev - player->distancetofinish;
boolean exceptions = (
player->flashing != 0
|| player->mo->hitlag != 0
|| P_MobjIsFrozen(player->mo)
|| player->airtime > 3*TICRATE/2
|| (player->justbumped > 0 && player->justbumped < bumptime-1)
);