Skip to content

Commit

Permalink
Implement "On Death Action" feature (#97)
Browse files Browse the repository at this point in the history
* Variables

* Just use Woof variable names

* for Doom

* for Heretic

* Add missing lines

* Prevent imideate "use" repeating

As mentioned in #93 (comment)

* for Hexen
  • Loading branch information
JNechaevsky authored Feb 17, 2024
1 parent 9713e7c commit f6ea31f
Show file tree
Hide file tree
Showing 16 changed files with 279 additions and 64 deletions.
3 changes: 3 additions & 0 deletions src/doom/doomstat.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,9 @@ extern wbstartstruct_t wminfo;

// File handling stuff.
extern char *savegamedir;
extern char savename[256];

extern void G_ClearSavename (void);

// if true, load all graphics at level load
extern boolean precache;
Expand Down
23 changes: 22 additions & 1 deletion src/doom/g_game.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ static int joystrafemove;
static boolean joyarray[MAX_JOY_BUTTONS + 1];
static boolean *joybuttons = &joyarray[1]; // allow [-1]

static char savename[256]; // [crispy] moved here, made static
char savename[256]; // [crispy] moved here
static int savegameslot;
static char savedescription[32];

Expand Down Expand Up @@ -1702,6 +1702,13 @@ void G_DeathMatchSpawnPlayer (int playernum)
P_SpawnPlayer (&playerstarts[playernum]);
}

// [crispy] clear the "savename" variable,
// i.e. restart level from scratch upon resurrection
void G_ClearSavename (void)
{
M_StringCopy(savename, "", sizeof(savename));
}

//
// G_DoReborn
//
Expand Down Expand Up @@ -2176,6 +2183,18 @@ void G_DoLoadGame (void)

// draw the pattern into the back screen
R_FillBackScreen ();

// [crispy] if the player is dead in this savegame,
// do not consider it for reload
if (players[consoleplayer].health <= 0)
G_ClearSavename();

// [JN] If "On death action" is set to "last save",
// then prevent holded "use" button to work for next few tics.
// This fixes imidiate pressing on wall upon reloading
// a save game, if "use" button is kept pressed.
if (singleplayer && gp_death_use_action == 1)
players[consoleplayer].usedown = true;
}


Expand Down Expand Up @@ -2262,6 +2281,7 @@ void G_DoSaveGame (void)

gameaction = ga_nothing;
M_StringCopy(savedescription, "", sizeof(savedescription));
M_StringCopy(savename, savegame_file, sizeof(savename));

CT_SetMessage(&players[consoleplayer], DEH_String(GGSAVED), false, NULL);

Expand All @@ -2288,6 +2308,7 @@ G_DeferedInitNew
d_skill = skill;
d_episode = episode;
d_map = map;
G_ClearSavename();
gameaction = ga_newgame;

// [crispy] if a new game is started during demo recording, start a new demo
Expand Down
47 changes: 30 additions & 17 deletions src/doom/m_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,7 @@ static void M_ID_DefaulSkill (int choice);
static void M_ID_PistolStart (int choice);
static void M_ID_RevealedSecrets (int choice);
static void M_ID_FlipLevels (int choice);
static void M_ID_OnDeathAction (int choice);
static void M_ID_DemoTimer (int choice);
static void M_ID_TimerDirection (int choice);
static void M_ID_ProgressBar (int choice);
Expand Down Expand Up @@ -3479,6 +3480,7 @@ static menuitem_t ID_Menu_Gameplay_3[]=
{ M_LFRT, "DEFAULT SKILL LEVEL", M_ID_DefaulSkill, 'd' },
{ M_LFRT, "REPORT REVEALED SECRETS", M_ID_RevealedSecrets, 'r' },
{ M_LFRT, "FLIP LEVELS HORIZONTALLY", M_ID_FlipLevels, 'f' },
{ M_LFRT, "ON DEATH ACTION", M_ID_OnDeathAction, 'o' },
{ M_SKIP, "", 0, '\0' },
{ M_LFRT, "SHOW DEMO TIMER", M_ID_DemoTimer, 's' },
{ M_LFRT, "TIMER DIRECTION", M_ID_TimerDirection, 't' },
Expand All @@ -3489,7 +3491,6 @@ static menuitem_t ID_Menu_Gameplay_3[]=
{ M_LFRT, "IMPROVED HIT DETECTION", M_ID_BlockmapFix, 'i' },
{ M_LFRT, "VERTICAL AIMING", M_ID_VerticalAiming, 'v' },
{ M_SKIP, "", 0, '\0' },
{ M_SKIP, "", 0, '\0' },
{ M_SWTC, "", /*FIRST PAGE >*/ M_Choose_ID_Gameplay_1, 'n' },
{ M_SWTC, "", /*< PREV PAGE*/ M_Choose_ID_Gameplay_2, 'p' },
};
Expand Down Expand Up @@ -3533,47 +3534,53 @@ static void M_Draw_ID_Gameplay_3 (void)
M_WriteText (M_ItemRightAlign(str), 36, str,
M_Item_Glow(2, gp_flip_levels ? GLOW_GREEN : GLOW_DARKRED));

M_WriteTextCentered(45, "DEMOS", cr[CR_YELLOW]);
// On death action
sprintf(str, gp_death_use_action == 1 ? "LAST SAVE" :
gp_death_use_action == 2 ? "NOTHING" : "DEFAULT");
M_WriteText (M_ItemRightAlign(str), 45, str,
M_Item_Glow(3, gp_death_use_action ? GLOW_GREEN : GLOW_DARKRED));

M_WriteTextCentered(54, "DEMOS", cr[CR_YELLOW]);

// Demo timer
sprintf(str, demo_timer == 1 ? "PLAYBACK" :
demo_timer == 2 ? "RECORDING" :
demo_timer == 3 ? "ALWAYS" : "OFF");
M_WriteText (M_ItemRightAlign(str), 54, str,
M_Item_Glow(4, demo_timer ? GLOW_GREEN : GLOW_DARKRED));
M_WriteText (M_ItemRightAlign(str), 63, str,
M_Item_Glow(5, demo_timer ? GLOW_GREEN : GLOW_DARKRED));

// Timer direction
sprintf(str, demo_timerdir ? "BACKWARD" : "FORWARD");
M_WriteText (M_ItemRightAlign(str), 63, str,
M_Item_Glow(5, demo_timer ? GLOW_GREEN : GLOW_DARKRED));
M_WriteText (M_ItemRightAlign(str), 72, str,
M_Item_Glow(6, demo_timer ? GLOW_GREEN : GLOW_DARKRED));

// Progress bar
sprintf(str, demo_bar ? "ON" : "OFF");
M_WriteText (M_ItemRightAlign(str), 72, str,
M_Item_Glow(6, demo_bar ? GLOW_GREEN : GLOW_DARKRED));
M_WriteText (M_ItemRightAlign(str), 81, str,
M_Item_Glow(7, demo_bar ? GLOW_GREEN : GLOW_DARKRED));

// Play internal demos
sprintf(str, demo_internal ? "ON" : "OFF");
M_WriteText (M_ItemRightAlign(str), 81, str,
M_Item_Glow(7, demo_internal ? GLOW_DARKRED : GLOW_GREEN));
M_WriteText (M_ItemRightAlign(str), 90, str,
M_Item_Glow(8, demo_internal ? GLOW_DARKRED : GLOW_GREEN));

M_WriteTextCentered(90, "COMPATIBILITY-BREAKING", cr[CR_YELLOW]);
M_WriteTextCentered(99, "COMPATIBILITY-BREAKING", cr[CR_YELLOW]);

// Pistol start game mode
sprintf(str, compat_pistol_start ? "ON" : "OFF");
M_WriteText (M_ItemRightAlign(str), 99, str,
M_Item_Glow(9, compat_pistol_start ? GLOW_GREEN : GLOW_DARKRED));
M_WriteText (M_ItemRightAlign(str), 108, str,
M_Item_Glow(10, compat_pistol_start ? GLOW_GREEN : GLOW_DARKRED));

// Improved hit detection
sprintf(str, compat_blockmap_fix ? "ON" : "OFF");
M_WriteText (M_ItemRightAlign(str), 108, str,
M_Item_Glow(10, compat_blockmap_fix ? GLOW_GREEN : GLOW_DARKRED));
M_WriteText (M_ItemRightAlign(str), 117, str,
M_Item_Glow(11, compat_blockmap_fix ? GLOW_GREEN : GLOW_DARKRED));

// Vertical aiming
sprintf(str, compat_vertical_aiming == 1 ? "DIRECT" :
compat_vertical_aiming == 2 ? "BOTH" : "AUTOAIM");
M_WriteText (M_ItemRightAlign(str), 117, str,
M_Item_Glow(11, compat_vertical_aiming ? GLOW_GREEN : GLOW_DARKRED));
M_WriteText (M_ItemRightAlign(str), 126, str,
M_Item_Glow(12, compat_vertical_aiming ? GLOW_GREEN : GLOW_DARKRED));

M_WriteText (ID_MENU_LEFTOFFSET_BIG, 144, "FIRST PAGE >",
M_Item_Glow(14, GLOW_LIGHTGRAY));
Expand Down Expand Up @@ -3613,6 +3620,11 @@ static void M_ID_FlipLevels (int choice)
S_UpdateStereoSeparation();
}

static void M_ID_OnDeathAction (int choice)
{
gp_death_use_action = M_INT_Slider(gp_death_use_action, 0, 2, choice, false);
}

static void M_ID_DemoTimer (int choice)
{
demo_timer = M_INT_Slider(demo_timer, 0, 3, choice, false);
Expand Down Expand Up @@ -4202,6 +4214,7 @@ static void M_ID_ApplyResetHook (void)
gp_default_skill = 2;
gp_revealed_secrets = 0;
gp_flip_levels = 0;
gp_death_use_action = 0;

// Demos
demo_timer = 0;
Expand Down
31 changes: 30 additions & 1 deletion src/doom/p_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,36 @@ void P_DeathThink (player_t* player)


if (player->cmd.buttons & BT_USE)
player->playerstate = PST_REBORN;
{
if (demorecording || demoplayback || netgame)
{
player->playerstate = PST_REBORN;
}
else
{
// [JN] "On death action", mostly taken from Crispy Doom and Woof.
switch (gp_death_use_action)
{
case 0: // Default (reload the level from scratch)
gameaction = ga_loadlevel;
G_ClearSavename();
break;
case 1: // Load last save
if (*savename)
{
gameaction = ga_loadgame;
}
else
{
player->playerstate = PST_REBORN;
}
break;
case 2: // Nothing
default:
break;
}
}
}
}


Expand Down
3 changes: 3 additions & 0 deletions src/heretic/doomdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,9 @@ uint16_t SV_ReadWord(void);
uint32_t SV_ReadLong(void);

extern char *savegamedir;
extern char savename[256];

extern void G_ClearSavename (void);

// [crispy] support up to 8 pages of savegames
extern int savepage;
Expand Down
30 changes: 27 additions & 3 deletions src/heretic/g_game.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ boolean precache = true; // if true, load all graphics at start
// TODO: Heretic uses 16-bit shorts for consistency?
byte consistancy[MAXPLAYERS][BACKUPTICS];
char *savegamedir;
char savename[256];

boolean testcontrols = false;
int testcontrols_mousespeed;
Expand Down Expand Up @@ -1894,6 +1895,13 @@ void G_DeathMatchSpawnPlayer(int playernum)
P_SpawnPlayer(&playerstarts[playernum]);
}

// [crispy] clear the "savename" variable,
// i.e. restart level from scratch upon resurrection
void G_ClearSavename (void)
{
M_StringCopy(savename, "", sizeof(savename));
}

/*
====================
=
Expand Down Expand Up @@ -2146,11 +2154,9 @@ void G_DoWorldDone(void)
//
//---------------------------------------------------------------------------

static char *savename = NULL;

void G_LoadGame(char *name)
{
savename = M_StringDuplicate(name);
M_StringCopy(savename, name, sizeof(savename));
gameaction = ga_loadgame;
}

Expand Down Expand Up @@ -2179,8 +2185,12 @@ void G_DoLoadGame(void)

SV_OpenRead(savename);

// [JN] Do not erase save data,
// it will be needed for "On death action" feature.
/*
free(savename);
savename = NULL;
*/

// Skip the description field
SV_Read(savestr, SAVESTRINGSIZE);
Expand Down Expand Up @@ -2249,6 +2259,18 @@ void G_DoLoadGame(void)

// Draw the pattern into the back screen
R_FillBackScreen();

// [crispy] if the player is dead in this savegame,
// do not consider it for reload
if (players[consoleplayer].health <= 0)
G_ClearSavename();

// [JN] If "On death action" is set to "last save",
// then prevent holded "use" button to work for next few tics.
// This fixes imidiate pressing on wall upon reloading
// a save game, if "use" button is kept pressed.
if (singleplayer && gp_death_use_action == 1)
players[consoleplayer].usedown = true;
}


Expand All @@ -2271,6 +2293,7 @@ void G_DeferedInitNew(skill_t skill, int episode, int map)
d_skill = skill;
d_episode = episode;
d_map = map;
G_ClearSavename();
gameaction = ga_newgame;

// [crispy] if a new game is started during demo recording, start a new demo
Expand Down Expand Up @@ -3157,6 +3180,7 @@ void G_DoSaveGame(void)

gameaction = ga_nothing;
savedescription[0] = 0;
M_StringCopy(savename, filename, sizeof(savename));
CT_SetMessage(&players[consoleplayer], DEH_String(TXT_GAMESAVED), true, NULL);

free(filename);
Expand Down
Loading

0 comments on commit f6ea31f

Please sign in to comment.