mirror of
https://github.com/fabiangreffrath/woof.git
synced 2025-09-22 11:22:18 -04:00
Add auto save feature (#1939)
* Add auto save menu item * Allow appending to default save name * Add saving auto save * Add loading auto save * Add auto save slot to load game menu * Fix rect x-offset * Enable by default
This commit is contained in:
parent
ed349ec34e
commit
9a43e5494b
@ -78,6 +78,8 @@ typedef enum
|
||||
ga_worlddone,
|
||||
ga_screenshot,
|
||||
ga_reloadlevel,
|
||||
ga_loadautosave,
|
||||
ga_saveautosave,
|
||||
} gameaction_t;
|
||||
|
||||
|
||||
|
187
src/g_game.c
187
src/g_game.c
@ -23,6 +23,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "am_map.h"
|
||||
@ -212,6 +213,9 @@ boolean joybuttons[NUM_GAMEPAD_BUTTONS];
|
||||
int savegameslot = -1;
|
||||
char savedescription[32];
|
||||
|
||||
static boolean save_autosave;
|
||||
static boolean autosave;
|
||||
|
||||
//jff 3/24/98 declare startskill external, define defaultskill here
|
||||
int default_skill; //note 1-based
|
||||
|
||||
@ -1961,6 +1965,11 @@ static void G_DoWorldDone(void)
|
||||
gameaction = ga_nothing;
|
||||
viewactive = true;
|
||||
AM_clearMarks(); //jff 4/12/98 clear any marks on the automap
|
||||
|
||||
if (autosave && !demorecording && !demoplayback && !netgame)
|
||||
{
|
||||
M_SaveAutoSave();
|
||||
}
|
||||
}
|
||||
|
||||
// killough 2/28/98: A ridiculously large number
|
||||
@ -2268,6 +2277,12 @@ static char *savename = NULL;
|
||||
static boolean forced_loadgame = false;
|
||||
static boolean command_loadgame = false;
|
||||
|
||||
void G_ForcedLoadAutoSave(void)
|
||||
{
|
||||
gameaction = ga_loadautosave;
|
||||
forced_loadgame = true;
|
||||
}
|
||||
|
||||
void G_ForcedLoadGame(void)
|
||||
{
|
||||
gameaction = ga_loadgame;
|
||||
@ -2277,6 +2292,15 @@ void G_ForcedLoadGame(void)
|
||||
// killough 3/16/98: add slot info
|
||||
// killough 5/15/98: add command-line
|
||||
|
||||
void G_LoadAutoSave(char *name)
|
||||
{
|
||||
free(savename);
|
||||
savename = M_StringDuplicate(name);
|
||||
gameaction = ga_loadautosave;
|
||||
forced_loadgame = false;
|
||||
command_loadgame = false;
|
||||
}
|
||||
|
||||
void G_LoadGame(char *name, int slot, boolean command)
|
||||
{
|
||||
if (savename) free(savename);
|
||||
@ -2290,6 +2314,12 @@ void G_LoadGame(char *name, int slot, boolean command)
|
||||
// killough 5/15/98:
|
||||
// Consistency Error when attempting to load savegame.
|
||||
|
||||
static void G_LoadAutoSaveErr(const char *msg)
|
||||
{
|
||||
Z_Free(savebuffer);
|
||||
MN_ForcedLoadAutoSave(msg);
|
||||
}
|
||||
|
||||
static void G_LoadGameErr(const char *msg)
|
||||
{
|
||||
Z_Free(savebuffer); // Free the savegame buffer
|
||||
@ -2308,6 +2338,12 @@ static void G_LoadGameErr(const char *msg)
|
||||
// Description is a 24 byte text string
|
||||
//
|
||||
|
||||
void G_SaveAutoSave(char *description)
|
||||
{
|
||||
strcpy(savedescription, description);
|
||||
save_autosave = true;
|
||||
}
|
||||
|
||||
void G_SaveGame(int slot, char *description)
|
||||
{
|
||||
savegameslot = slot;
|
||||
@ -2330,13 +2366,8 @@ void CheckSaveGame(size_t size)
|
||||
|
||||
// [FG] support up to 8 pages of savegames
|
||||
|
||||
char* G_SaveGameName(int slot)
|
||||
static char *SaveGameName(const char *buf)
|
||||
{
|
||||
// Ty 05/04/98 - use savegamename variable (see d_deh.c)
|
||||
// killough 12/98: add .7 to truncate savegamename
|
||||
char buf[16] = {0};
|
||||
sprintf(buf, "%.7s%d.dsg", savegamename, 10*savepage+slot);
|
||||
|
||||
char *filepath = M_StringJoin(basesavegame, DIR_SEPARATOR_S, buf);
|
||||
char *existing = M_FileCaseExists(filepath);
|
||||
|
||||
@ -2353,6 +2384,20 @@ char* G_SaveGameName(int slot)
|
||||
}
|
||||
}
|
||||
|
||||
char *G_AutoSaveName(void)
|
||||
{
|
||||
return SaveGameName("autosave.dsg");
|
||||
}
|
||||
|
||||
char *G_SaveGameName(int slot)
|
||||
{
|
||||
// Ty 05/04/98 - use savegamename variable (see d_deh.c)
|
||||
// killough 12/98: add .7 to truncate savegamename
|
||||
char buf[16] = {0};
|
||||
sprintf(buf, "%.7s%d.dsg", savegamename, 10 * savepage + slot);
|
||||
return SaveGameName(buf);
|
||||
}
|
||||
|
||||
char* G_MBFSaveGameName(int slot)
|
||||
{
|
||||
char buf[16] = {0};
|
||||
@ -2397,15 +2442,12 @@ static uint64_t G_Signature(int sig_epi, int sig_map)
|
||||
return s;
|
||||
}
|
||||
|
||||
static void G_DoSaveGame(void)
|
||||
static void DoSaveGame(char *name)
|
||||
{
|
||||
char *name = NULL;
|
||||
char name2[VERSIONSIZE];
|
||||
char *description;
|
||||
int length, i;
|
||||
|
||||
name = G_SaveGameName(savegameslot);
|
||||
|
||||
description = savedescription;
|
||||
|
||||
save_p = savebuffer = Z_Malloc(savegamesize, PU_STATIC, 0);
|
||||
@ -2511,11 +2553,22 @@ static void G_DoSaveGame(void)
|
||||
|
||||
if (name) free(name);
|
||||
|
||||
MN_SetQuickSaveSlot(savegameslot);
|
||||
|
||||
drs_skip_frame = true;
|
||||
}
|
||||
|
||||
static void G_DoSaveGame(void)
|
||||
{
|
||||
char *name = G_SaveGameName(savegameslot);
|
||||
DoSaveGame(name);
|
||||
MN_SetQuickSaveSlot(savegameslot);
|
||||
}
|
||||
|
||||
static void G_DoSaveAutoSave(void)
|
||||
{
|
||||
char *name = G_AutoSaveName();
|
||||
DoSaveGame(name);
|
||||
}
|
||||
|
||||
static void CheckSaveVersion(const char *str, saveg_compat_t ver)
|
||||
{
|
||||
if (strncmp((char *) save_p, str, strlen(str)) == 0)
|
||||
@ -2524,7 +2577,7 @@ static void CheckSaveVersion(const char *str, saveg_compat_t ver)
|
||||
}
|
||||
}
|
||||
|
||||
static void G_DoLoadGame(void)
|
||||
static boolean DoLoadGame(boolean do_load_autosave)
|
||||
{
|
||||
int length, i;
|
||||
char vcheck[VERSIONSIZE];
|
||||
@ -2562,8 +2615,12 @@ static void G_DoLoadGame(void)
|
||||
// killough 2/22/98: Friendly savegame version difference message
|
||||
if (!forced_loadgame && saveg_compat != saveg_mbf && saveg_compat < saveg_woof600)
|
||||
{
|
||||
G_LoadGameErr("Different Savegame Version!!!\n\nAre you sure?");
|
||||
return;
|
||||
const char *msg = "Different Savegame Version!!!\n\nAre you sure?";
|
||||
if (do_load_autosave)
|
||||
G_LoadAutoSaveErr(msg);
|
||||
else
|
||||
G_LoadGameErr(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
save_p += VERSIONSIZE;
|
||||
@ -2595,9 +2652,12 @@ static void G_DoLoadGame(void)
|
||||
if (save_p[sizeof checksum])
|
||||
strcat(strcat(msg,"Wads expected:\n\n"), (char *) save_p);
|
||||
strcat(msg, "\nAre you sure?");
|
||||
G_LoadGameErr(msg);
|
||||
if (do_load_autosave)
|
||||
G_LoadAutoSaveErr(msg);
|
||||
else
|
||||
G_LoadGameErr(msg);
|
||||
free(msg);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2723,15 +2783,86 @@ static void G_DoLoadGame(void)
|
||||
if (demorecording) // So this can only possibly be a -recordfrom command.
|
||||
G_BeginRecording();// Start the -recordfrom, since the game was loaded.
|
||||
|
||||
I_Printf(VB_INFO, "G_DoLoadGame: Slot %02d, Time ", 10 * savepage + savegameslot);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void PrintLevelTimes(void)
|
||||
{
|
||||
if (totalleveltimes)
|
||||
I_Printf(VB_INFO, "(%d:%02d) ", ((totalleveltimes + leveltime) / TICRATE) / 60,
|
||||
((totalleveltimes + leveltime) / TICRATE) % 60);
|
||||
I_Printf(VB_INFO, "%d:%05.2f", leveltime / TICRATE / 60,
|
||||
(float)(leveltime % (60 * TICRATE)) / TICRATE);
|
||||
{
|
||||
I_Printf(VB_INFO, "(%d:%02d) ",
|
||||
((totalleveltimes + leveltime) / TICRATE) / 60,
|
||||
((totalleveltimes + leveltime) / TICRATE) % 60);
|
||||
}
|
||||
|
||||
MN_SetQuickSaveSlot(savegameslot);
|
||||
I_Printf(VB_INFO, "%d:%05.2f", leveltime / TICRATE / 60,
|
||||
(float)(leveltime % (60 * TICRATE)) / TICRATE);
|
||||
}
|
||||
|
||||
static void G_DoLoadGame(void)
|
||||
{
|
||||
if (DoLoadGame(false))
|
||||
{
|
||||
const int slot_num = 10 * savepage + savegameslot;
|
||||
I_Printf(VB_INFO, "G_DoLoadGame: Slot %02d, Time ", slot_num);
|
||||
PrintLevelTimes();
|
||||
MN_SetQuickSaveSlot(savegameslot);
|
||||
}
|
||||
}
|
||||
|
||||
static void G_DoLoadAutoSave(void)
|
||||
{
|
||||
if (DoLoadGame(true))
|
||||
{
|
||||
I_Printf(VB_INFO, "G_DoLoadGame: Auto Save, Time ");
|
||||
PrintLevelTimes();
|
||||
}
|
||||
}
|
||||
|
||||
boolean G_AutoSaveEnabled(void)
|
||||
{
|
||||
return autosave;
|
||||
}
|
||||
|
||||
//
|
||||
// G_LoadAutoSaveDeathUse
|
||||
// Loads the auto save if it's more recent than the current save slot.
|
||||
// Returns true if the auto save is loaded.
|
||||
//
|
||||
boolean G_LoadAutoSaveDeathUse(void)
|
||||
{
|
||||
struct stat st;
|
||||
char *auto_path = G_AutoSaveName();
|
||||
time_t auto_time = (M_stat(auto_path, &st) != -1 ? st.st_mtime : 0);
|
||||
boolean result = (auto_time > 0);
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (savegameslot >= 0)
|
||||
{
|
||||
char *save_path = G_SaveGameName(savegameslot);
|
||||
time_t save_time = (M_stat(save_path, &st) != -1 ? st.st_mtime : 0);
|
||||
free(save_path);
|
||||
result = (auto_time > save_time);
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
G_LoadAutoSave(auto_path);
|
||||
}
|
||||
}
|
||||
|
||||
free(auto_path);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void CheckSaveAutoSave(void)
|
||||
{
|
||||
if (save_autosave)
|
||||
{
|
||||
save_autosave = false;
|
||||
gameaction = ga_saveautosave;
|
||||
}
|
||||
}
|
||||
|
||||
boolean clean_screenshot;
|
||||
@ -2812,11 +2943,19 @@ void G_Ticker(void)
|
||||
case ga_reloadlevel:
|
||||
G_ReloadLevel();
|
||||
break;
|
||||
case ga_loadautosave:
|
||||
G_DoLoadAutoSave();
|
||||
break;
|
||||
case ga_saveautosave:
|
||||
G_DoSaveAutoSave();
|
||||
break;
|
||||
default: // killough 9/29/98
|
||||
gameaction = ga_nothing;
|
||||
break;
|
||||
}
|
||||
|
||||
CheckSaveAutoSave();
|
||||
|
||||
// killough 10/6/98: allow games to be saved during demo
|
||||
// playback, by the playback user (not by demo itself)
|
||||
|
||||
@ -4674,6 +4813,8 @@ void G_BindGameVariables(void)
|
||||
"Maximum number of player corpses (< 0 = No limit)");
|
||||
BIND_NUM_GENERAL(death_use_action, 0, 0, 2,
|
||||
"Use-button action upon death (0 = Default; 1 = Load save; 2 = Nothing)");
|
||||
BIND_BOOL_GENERAL(autosave, true,
|
||||
"Auto save at the beginning of a map, after completing the previous one.");
|
||||
}
|
||||
|
||||
void G_BindEnemVariables(void)
|
||||
|
@ -46,9 +46,14 @@ void G_DeathMatchSpawnPlayer(int playernum);
|
||||
void G_InitNew(skill_t skill, int episode, int map);
|
||||
void G_DeferedInitNew(skill_t skill, int episode, int map);
|
||||
void G_DeferedPlayDemo(char *demo);
|
||||
void G_LoadAutoSave(char *name);
|
||||
void G_LoadGame(char *name, int slot, boolean is_command); // killough 5/15/98
|
||||
void G_ForcedLoadAutoSave(void);
|
||||
void G_ForcedLoadGame(void); // killough 5/15/98: forced loadgames
|
||||
void G_SaveAutoSave(char *description);
|
||||
void G_SaveGame(int slot, char *description); // Called by M_Responder.
|
||||
boolean G_AutoSaveEnabled(void);
|
||||
boolean G_LoadAutoSaveDeathUse(void);
|
||||
void G_RecordDemo(char *name); // Only called by startup code.
|
||||
void G_BeginRecording(void);
|
||||
void G_PlayDemo(char *name);
|
||||
@ -58,6 +63,7 @@ void G_WorldDone(void);
|
||||
void G_Ticker(void);
|
||||
void G_ScreenShot(void);
|
||||
void G_ReloadDefaults(boolean keep_demover); // killough 3/1/98: loads game defaults
|
||||
char *G_AutoSaveName(void);
|
||||
char *G_SaveGameName(int); // killough 3/22/98: sets savegame filename
|
||||
char *G_MBFSaveGameName(int); // MBF savegame filename
|
||||
void G_SetFastParms(int); // killough 4/10/98: sets -fast parameters
|
||||
|
492
src/mn_menu.c
492
src/mn_menu.c
@ -117,8 +117,13 @@ backdrop_t menu_backdrop;
|
||||
|
||||
#define M_X_LOADSAVE 80
|
||||
#define M_Y_LOADSAVE 34
|
||||
#define M_Y_AUTOSAVE 26
|
||||
#define M_LOADSAVE_WIDTH (24 * 8 + 8) // [FG] c.f. M_DrawSaveLoadBorder()
|
||||
|
||||
#define LOADGRAPHIC_Y 8
|
||||
#define AUTOGRAPHIC_Y 2
|
||||
static int loadsave_title_y = LOADGRAPHIC_Y;
|
||||
|
||||
static char savegamestrings[10][SAVESTRINGSIZE];
|
||||
|
||||
// [FG] support up to 8 pages of savegames
|
||||
@ -181,7 +186,7 @@ short whichSkull; // which skull to draw (he blinks)
|
||||
|
||||
char skullName[2][/*8*/ 9] = {"M_SKULL1", "M_SKULL2"};
|
||||
|
||||
static menu_t SaveDef, LoadDef;
|
||||
static menu_t SaveDef, LoadDef, LoadAutoSaveDef;
|
||||
static menu_t *currentMenu; // current menudef
|
||||
|
||||
// end of externs added for setup menus
|
||||
@ -206,6 +211,7 @@ static void M_MusicVol(int choice);
|
||||
|
||||
static void M_FinishReadThis(int choice);
|
||||
static void M_FinishHelp(int choice); // killough 10/98
|
||||
static void M_LoadAutoSaveSelect(int choice);
|
||||
static void M_LoadSelect(int choice);
|
||||
static void M_SaveSelect(int choice);
|
||||
static void M_ReadSaveStrings(void);
|
||||
@ -732,8 +738,15 @@ enum
|
||||
load_end
|
||||
} load_e;
|
||||
|
||||
#define SAVE_LOAD_RECT(n) \
|
||||
{M_X_LOADSAVE, M_Y_LOADSAVE + (n) * LINEHEIGHT - 7, M_LOADSAVE_WIDTH, LINEHEIGHT}
|
||||
#define SAVE_LOAD_RECT_Y(m_y, n) ((m_y) + (n) * LINEHEIGHT - 7)
|
||||
|
||||
#define SAVE_LOAD_RECT(n) \
|
||||
{M_X_LOADSAVE, SAVE_LOAD_RECT_Y(M_Y_LOADSAVE, n), M_LOADSAVE_WIDTH, \
|
||||
LINEHEIGHT}
|
||||
|
||||
#define AUTO_SAVE_RECT(n) \
|
||||
{M_X_LOADSAVE, SAVE_LOAD_RECT_Y(M_Y_AUTOSAVE, n), M_LOADSAVE_WIDTH, \
|
||||
LINEHEIGHT}
|
||||
|
||||
// The definitions of the Load Game screen
|
||||
|
||||
@ -761,39 +774,76 @@ static menu_t LoadDef =
|
||||
0
|
||||
};
|
||||
|
||||
#define LOADGRAPHIC_Y 8
|
||||
enum
|
||||
{
|
||||
autosave_page = load_end,
|
||||
autosave_end
|
||||
} autosave_e;
|
||||
|
||||
static menuitem_t LoadAutoSaveMenu[] = {
|
||||
// Auto save slot.
|
||||
{1, "", M_LoadAutoSaveSelect, 'a', NULL, AUTO_SAVE_RECT(0)},
|
||||
// Regular save slots.
|
||||
{1, "", M_LoadSelect, '1', NULL, AUTO_SAVE_RECT(1)},
|
||||
{1, "", M_LoadSelect, '2', NULL, AUTO_SAVE_RECT(2)},
|
||||
{1, "", M_LoadSelect, '3', NULL, AUTO_SAVE_RECT(3)},
|
||||
{1, "", M_LoadSelect, '4', NULL, AUTO_SAVE_RECT(4)},
|
||||
{1, "", M_LoadSelect, '5', NULL, AUTO_SAVE_RECT(5)},
|
||||
{1, "", M_LoadSelect, '6', NULL, AUTO_SAVE_RECT(6)},
|
||||
{1, "", M_LoadSelect, '7', NULL, AUTO_SAVE_RECT(7)},
|
||||
{1, "", M_LoadSelect, '8', NULL, AUTO_SAVE_RECT(8)},
|
||||
// Save page navigation.
|
||||
{-1, "", NULL, 0, NULL, AUTO_SAVE_RECT(9), MF_PAGE}
|
||||
};
|
||||
|
||||
static menu_t LoadAutoSaveDef =
|
||||
{
|
||||
autosave_end,
|
||||
&MainDef,
|
||||
LoadAutoSaveMenu,
|
||||
M_DrawLoad,
|
||||
M_X_LOADSAVE,
|
||||
M_Y_AUTOSAVE,
|
||||
};
|
||||
|
||||
// [FG] draw a snapshot of the n'th savegame into a separate window,
|
||||
// or fill window with solid color and "n/a" if snapshot not available
|
||||
|
||||
static int snapshot_width, snapshot_height;
|
||||
|
||||
static void M_DrawBorderedSnapshot(int n)
|
||||
static void M_DrawBorderedSnapshot(int slot)
|
||||
{
|
||||
const char *txt = "n/a";
|
||||
|
||||
const int snapshot_x =
|
||||
MAX(video.deltaw + SaveDef.x + SKULLXOFF - snapshot_width - 8, 8);
|
||||
const int snapshot_y =
|
||||
LoadDef.y
|
||||
+ MAX((load_end * LINEHEIGHT - snapshot_height) * n / load_end, 0);
|
||||
|
||||
// [FG] a snapshot window smaller than 80*48 px is considered too small
|
||||
if (snapshot_width < SCREENWIDTH / 4)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MN_DrawSnapshot(n, snapshot_x, snapshot_y, snapshot_width,
|
||||
snapshot_height))
|
||||
const int x =
|
||||
video.deltaw + currentMenu->x + SKULLXOFF - snapshot_width - 8;
|
||||
const int y = (currentMenu->numitems * LINEHEIGHT - snapshot_height) * slot
|
||||
/ currentMenu->numitems;
|
||||
|
||||
const int snapshot_x = MAX(8, x);
|
||||
const int snapshot_y = currentMenu->y + MAX(0, y);
|
||||
|
||||
const boolean draw_shot = MN_DrawSnapshot(slot, snapshot_x, snapshot_y,
|
||||
snapshot_width, snapshot_height);
|
||||
|
||||
const boolean is_autosave = (currentMenu == &LoadAutoSaveDef && slot == 0);
|
||||
|
||||
const char *txt;
|
||||
|
||||
if (!draw_shot || is_autosave)
|
||||
{
|
||||
txt = (is_autosave ? "Auto Save" : "N/A");
|
||||
WriteText(snapshot_x + (snapshot_width - MN_StringWidth(txt)) / 2
|
||||
- video.deltaw,
|
||||
snapshot_y + snapshot_height / 2 - MN_StringHeight(txt) / 2,
|
||||
txt);
|
||||
}
|
||||
|
||||
txt = MN_GetSavegameTime(n);
|
||||
txt = MN_GetSavegameTime(slot);
|
||||
MN_DrawString(snapshot_x + snapshot_width / 2 - MN_GetPixelWidth(txt) / 2
|
||||
- video.deltaw,
|
||||
snapshot_y + snapshot_height + MN_StringHeight(txt), CR_GOLD,
|
||||
@ -807,26 +857,49 @@ static void M_DrawBorderedSnapshot(int n)
|
||||
|
||||
static boolean delete_verify = false;
|
||||
|
||||
static void M_DeleteGame(int i)
|
||||
static void DeleteAutoSave(void)
|
||||
{
|
||||
char *name = G_SaveGameName(i);
|
||||
char *name = G_AutoSaveName();
|
||||
M_remove(name);
|
||||
free(name);
|
||||
}
|
||||
|
||||
if (i == quickSaveSlot)
|
||||
static void DeleteSaveGame(int slot)
|
||||
{
|
||||
char *name = G_SaveGameName(slot);
|
||||
M_remove(name);
|
||||
free(name);
|
||||
|
||||
if (slot == quickSaveSlot)
|
||||
{
|
||||
quickSaveSlot = -1;
|
||||
}
|
||||
|
||||
if (i == savegameslot)
|
||||
if (slot == savegameslot)
|
||||
{
|
||||
savegameslot = -1;
|
||||
}
|
||||
}
|
||||
|
||||
M_ReadSaveStrings();
|
||||
static void M_DeleteGame(int choice)
|
||||
{
|
||||
int slot = choice;
|
||||
|
||||
if (name)
|
||||
if (currentMenu == &LoadAutoSaveDef)
|
||||
{
|
||||
free(name);
|
||||
if (slot == 0)
|
||||
{
|
||||
DeleteAutoSave();
|
||||
}
|
||||
else
|
||||
{
|
||||
slot--;
|
||||
DeleteSaveGame(slot);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteSaveGame(slot);
|
||||
}
|
||||
}
|
||||
|
||||
@ -834,7 +907,8 @@ static void M_DeleteGame(int i)
|
||||
static void M_DrawSaveLoadBottomLine(void)
|
||||
{
|
||||
char pagestr[16];
|
||||
const int y = LoadDef.y + LINEHEIGHT * load_page;
|
||||
const int x = currentMenu->x;
|
||||
const int y = currentMenu->y + LINEHEIGHT * (currentMenu->numitems - 1);
|
||||
|
||||
// [crispy] force status bar refresh
|
||||
inhelpscreens = true;
|
||||
@ -844,21 +918,38 @@ static void M_DrawSaveLoadBottomLine(void)
|
||||
int flags = currentMenu->menuitems[index].flags;
|
||||
byte *cr = (flags & MF_PAGE) ? cr_bright : NULL;
|
||||
|
||||
M_DrawSaveLoadBorder(LoadDef.x, y, cr);
|
||||
M_DrawSaveLoadBorder(x, y, cr);
|
||||
|
||||
if (savepage > 0)
|
||||
{
|
||||
MN_DrawString(LoadDef.x, y, CR_GOLD, "<-");
|
||||
MN_DrawString(x, y, CR_GOLD, "<-");
|
||||
}
|
||||
if (savepage < savepage_max)
|
||||
{
|
||||
MN_DrawString(LoadDef.x + (SAVESTRINGSIZE - 2) * 8, y, CR_GOLD, "->");
|
||||
MN_DrawString(x + (SAVESTRINGSIZE - 2) * 8, y, CR_GOLD, "->");
|
||||
}
|
||||
|
||||
M_snprintf(pagestr, sizeof(pagestr), "page %d/%d", savepage + 1,
|
||||
savepage_max + 1);
|
||||
MN_DrawString(LoadDef.x + M_LOADSAVE_WIDTH / 2 - MN_StringWidth(pagestr) / 2,
|
||||
y, CR_GOLD, pagestr);
|
||||
MN_DrawString(x + M_LOADSAVE_WIDTH / 2 - MN_StringWidth(pagestr) / 2, y,
|
||||
CR_GOLD, pagestr);
|
||||
}
|
||||
|
||||
static void M_DrawSaveLoadBorders(void)
|
||||
{
|
||||
const int num_slots = currentMenu->numitems - 1;
|
||||
const int x = currentMenu->x;
|
||||
|
||||
for (int i = 0; i < num_slots; i++)
|
||||
{
|
||||
const int y = currentMenu->y + LINEHEIGHT * i;
|
||||
|
||||
const menuitem_t *item = ¤tMenu->menuitems[i];
|
||||
byte *cr = (item->flags & MF_HILITE) ? cr_bright : NULL;
|
||||
|
||||
M_DrawSaveLoadBorder(x, y, cr);
|
||||
WriteText(x, y, savegamestrings[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@ -867,22 +958,13 @@ static void M_DrawSaveLoadBottomLine(void)
|
||||
|
||||
static void M_DrawLoad(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
// jff 3/15/98 use symbolic load position
|
||||
MN_DrawTitle(72, LOADGRAPHIC_Y, "M_LOADG", "Load Game");
|
||||
for (i = 0; i < load_page; i++)
|
||||
{
|
||||
menuitem_t *item = ¤tMenu->menuitems[i];
|
||||
byte *cr = (item->flags & MF_HILITE) ? cr_bright : NULL;
|
||||
|
||||
M_DrawSaveLoadBorder(LoadDef.x, LoadDef.y + LINEHEIGHT * i, cr);
|
||||
WriteText(LoadDef.x, LoadDef.y + LINEHEIGHT * i, savegamestrings[i]);
|
||||
}
|
||||
MN_DrawTitle(M_X_CENTER, loadsave_title_y, "M_LOADG", "Load Game");
|
||||
M_DrawSaveLoadBorders();
|
||||
|
||||
int index = (menu_input == mouse_mode ? highlight_item : itemOn);
|
||||
|
||||
if (index < load_page)
|
||||
if (index < currentMenu->numitems - 1)
|
||||
{
|
||||
M_DrawBorderedSnapshot(index);
|
||||
}
|
||||
@ -913,12 +995,28 @@ static void M_DrawSaveLoadBorder(int x, int y, byte *cr)
|
||||
// User wants to load this game
|
||||
//
|
||||
|
||||
static void M_LoadAutoSaveSelect(int choice)
|
||||
{
|
||||
saveg_compat = saveg_woof510;
|
||||
char *name = G_AutoSaveName();
|
||||
G_LoadAutoSave(name);
|
||||
free(name);
|
||||
MN_ClearMenus();
|
||||
// Auto save slot doesn't exist for save menu, so don't change lastOn.
|
||||
//SaveDef.lastOn = choice;
|
||||
}
|
||||
|
||||
static void M_LoadSelect(int choice)
|
||||
{
|
||||
char *name = NULL; // killough 3/22/98
|
||||
int slot = choice;
|
||||
|
||||
name = G_SaveGameName(choice);
|
||||
if (currentMenu == &LoadAutoSaveDef)
|
||||
{
|
||||
slot--;
|
||||
}
|
||||
|
||||
name = G_SaveGameName(slot);
|
||||
saveg_compat = saveg_woof510;
|
||||
|
||||
if (M_access(name, F_OK) != 0)
|
||||
@ -927,11 +1025,11 @@ static void M_LoadSelect(int choice)
|
||||
{
|
||||
free(name);
|
||||
}
|
||||
name = G_MBFSaveGameName(choice);
|
||||
name = G_MBFSaveGameName(slot);
|
||||
saveg_compat = saveg_mbf;
|
||||
}
|
||||
|
||||
G_LoadGame(name, choice, false); // killough 3/16/98, 5/15/98: add slot, cmd
|
||||
G_LoadGame(name, slot, false); // killough 3/16/98, 5/15/98: add slot, cmd
|
||||
|
||||
MN_ClearMenus();
|
||||
if (name)
|
||||
@ -940,13 +1038,23 @@ static void M_LoadSelect(int choice)
|
||||
}
|
||||
|
||||
// [crispy] save the last game you loaded
|
||||
SaveDef.lastOn = choice;
|
||||
SaveDef.lastOn = slot;
|
||||
}
|
||||
|
||||
//
|
||||
// killough 5/15/98: add forced loadgames
|
||||
//
|
||||
|
||||
static void M_VerifyForcedLoadAutoSave(int ch)
|
||||
{
|
||||
if (ch == 'y')
|
||||
{
|
||||
G_ForcedLoadAutoSave();
|
||||
}
|
||||
free(messageString);
|
||||
MN_ClearMenus();
|
||||
}
|
||||
|
||||
static void M_VerifyForcedLoadGame(int ch)
|
||||
{
|
||||
if (ch == 'y')
|
||||
@ -957,6 +1065,11 @@ static void M_VerifyForcedLoadGame(int ch)
|
||||
MN_ClearMenus();
|
||||
}
|
||||
|
||||
void MN_ForcedLoadAutoSave(const char *msg)
|
||||
{
|
||||
M_StartMessage(strdup(msg), M_VerifyForcedLoadAutoSave, true);
|
||||
}
|
||||
|
||||
void MN_ForcedLoadGame(const char *msg)
|
||||
{
|
||||
M_StartMessage(strdup(msg), M_VerifyForcedLoadGame, true); // free()'d above
|
||||
@ -984,7 +1097,15 @@ static void M_LoadGame(int choice)
|
||||
return;
|
||||
}
|
||||
|
||||
SetNextMenu(&LoadDef);
|
||||
if (G_AutoSaveEnabled() && savepage == 0)
|
||||
{
|
||||
SetNextMenu(&LoadAutoSaveDef);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetNextMenu(&LoadDef);
|
||||
}
|
||||
|
||||
M_ReadSaveStrings();
|
||||
}
|
||||
|
||||
@ -1019,18 +1140,102 @@ static menu_t SaveDef =
|
||||
0
|
||||
};
|
||||
|
||||
static void SetLoadSlotStatus(int slot, int status)
|
||||
{
|
||||
if (currentMenu == &LoadAutoSaveDef)
|
||||
{
|
||||
if (slot > 0)
|
||||
{
|
||||
LoadDef.menuitems[slot - 1].status = status;
|
||||
}
|
||||
|
||||
LoadAutoSaveDef.menuitems[slot].status = status;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadDef.menuitems[slot].status = status;
|
||||
LoadAutoSaveDef.menuitems[slot + 1].status = status;
|
||||
}
|
||||
}
|
||||
|
||||
static void EmptySaveString(char *name, boolean is_autosave)
|
||||
{
|
||||
if (is_autosave)
|
||||
{
|
||||
M_snprintf(name, SAVESTRINGSIZE, "%s (Auto)", s_EMPTYSTRING);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_snprintf(name, SAVESTRINGSIZE, "%s", s_EMPTYSTRING);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_ReadSaveString(char *name, int menu_slot, int save_slot,
|
||||
boolean is_autosave)
|
||||
{
|
||||
FILE *fp = M_fopen(name, "rb");
|
||||
MN_ReadSavegameTime(menu_slot, name);
|
||||
free(name);
|
||||
|
||||
MN_ResetSnapshot(menu_slot);
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
if (!is_autosave)
|
||||
{
|
||||
// Ty 03/27/98 - externalized:
|
||||
name = G_MBFSaveGameName(save_slot);
|
||||
fp = M_fopen(name, "rb");
|
||||
free(name);
|
||||
}
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
EmptySaveString(savegamestrings[menu_slot], is_autosave);
|
||||
SetLoadSlotStatus(menu_slot, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// [FG] check return value
|
||||
if (!fread(&savegamestrings[menu_slot], SAVESTRINGSIZE, 1, fp))
|
||||
{
|
||||
fclose(fp);
|
||||
EmptySaveString(savegamestrings[menu_slot], is_autosave);
|
||||
SetLoadSlotStatus(menu_slot, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MN_ReadSnapshot(menu_slot, fp))
|
||||
{
|
||||
MN_ResetSnapshot(menu_slot);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
SetLoadSlotStatus(menu_slot, 1);
|
||||
}
|
||||
|
||||
static void UpdateRectX(menu_t *menu, int x)
|
||||
{
|
||||
for (int i = 0; i < menu->numitems; i++)
|
||||
{
|
||||
menu->menuitems[i].rect.x = x;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// M_ReadSaveStrings
|
||||
// read the strings from the savegame files
|
||||
//
|
||||
static void M_ReadSaveStrings(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
// [FG] shift savegame descriptions a bit to the right
|
||||
// to make room for the snapshots on the left
|
||||
SaveDef.x = LoadDef.x =
|
||||
M_X_LOADSAVE + MIN(M_LOADSAVE_WIDTH / 2, video.deltaw);
|
||||
const int x = M_X_LOADSAVE + MIN(M_LOADSAVE_WIDTH / 2, video.deltaw);
|
||||
SaveDef.x = LoadDef.x = LoadAutoSaveDef.x = x;
|
||||
UpdateRectX(&SaveDef, x);
|
||||
UpdateRectX(&LoadDef, x);
|
||||
UpdateRectX(&LoadAutoSaveDef, x);
|
||||
|
||||
// [FG] fit the snapshots into the resulting space
|
||||
snapshot_width = MIN((video.deltaw + SaveDef.x + 2 * SKULLXOFF) & ~7,
|
||||
@ -1038,51 +1243,22 @@ static void M_ReadSaveStrings(void)
|
||||
snapshot_height = MIN((snapshot_width * SCREENHEIGHT / SCREENWIDTH) & ~7,
|
||||
SCREENHEIGHT / 2);
|
||||
|
||||
for (i = 0; i < load_page; i++)
|
||||
int start_slot = 0;
|
||||
|
||||
if (currentMenu == &LoadAutoSaveDef)
|
||||
{
|
||||
FILE *fp; // killough 11/98: change to use stdio
|
||||
char *name = G_AutoSaveName();
|
||||
M_ReadSaveString(name, 0, 0, true);
|
||||
start_slot = 1;
|
||||
}
|
||||
|
||||
char *name = G_SaveGameName(i); // killough 3/22/98
|
||||
fp = M_fopen(name, "rb");
|
||||
MN_ReadSavegameTime(i, name);
|
||||
if (name)
|
||||
{
|
||||
free(name);
|
||||
}
|
||||
const int num_slots = currentMenu->numitems - 1;
|
||||
|
||||
MN_ResetSnapshot(i);
|
||||
|
||||
if (!fp)
|
||||
{ // Ty 03/27/98 - externalized:
|
||||
name = G_MBFSaveGameName(i);
|
||||
fp = M_fopen(name, "rb");
|
||||
if (name)
|
||||
{
|
||||
free(name);
|
||||
}
|
||||
if (!fp)
|
||||
{
|
||||
strcpy(&savegamestrings[i][0], s_EMPTYSTRING);
|
||||
LoadMenu[i].status = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// [FG] check return value
|
||||
if (!fread(&savegamestrings[i], SAVESTRINGSIZE, 1, fp))
|
||||
{
|
||||
strcpy(&savegamestrings[i][0], s_EMPTYSTRING);
|
||||
LoadMenu[i].status = 0;
|
||||
fclose(fp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!MN_ReadSnapshot(i, fp))
|
||||
{
|
||||
MN_ResetSnapshot(i);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
LoadMenu[i].status = 1;
|
||||
for (int menu_slot = start_slot; menu_slot < num_slots; menu_slot++)
|
||||
{
|
||||
const int save_slot = menu_slot - start_slot;
|
||||
char *name = G_SaveGameName(save_slot);
|
||||
M_ReadSaveString(name, menu_slot, save_slot, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1094,25 +1270,19 @@ static void M_DrawSave(void)
|
||||
int i;
|
||||
|
||||
// jff 3/15/98 use symbolic load position
|
||||
MN_DrawTitle(72, LOADGRAPHIC_Y, "M_SAVEG", "Save Game");
|
||||
for (i = 0; i < load_page; i++)
|
||||
{
|
||||
menuitem_t *item = ¤tMenu->menuitems[i];
|
||||
byte *cr = (item->flags & MF_HILITE) ? cr_bright : NULL;
|
||||
|
||||
M_DrawSaveLoadBorder(LoadDef.x, LoadDef.y + LINEHEIGHT * i, cr);
|
||||
WriteText(LoadDef.x, LoadDef.y + LINEHEIGHT * i, savegamestrings[i]);
|
||||
}
|
||||
MN_DrawTitle(M_X_CENTER, loadsave_title_y, "M_SAVEG", "Save Game");
|
||||
M_DrawSaveLoadBorders();
|
||||
|
||||
if (saveStringEnter)
|
||||
{
|
||||
i = MN_StringWidth(savegamestrings[saveSlot]);
|
||||
WriteText(LoadDef.x + i, LoadDef.y + LINEHEIGHT * saveSlot, "_");
|
||||
WriteText(currentMenu->x + i, currentMenu->y + LINEHEIGHT * saveSlot,
|
||||
"_");
|
||||
}
|
||||
|
||||
int index = (menu_input == mouse_mode ? highlight_item : itemOn);
|
||||
|
||||
if (index < load_page)
|
||||
if (index < currentMenu->numitems - 1)
|
||||
{
|
||||
M_DrawBorderedSnapshot(index);
|
||||
}
|
||||
@ -1138,7 +1308,7 @@ void MN_SetQuickSaveSlot(int slot)
|
||||
}
|
||||
|
||||
// [FG] generate a default save slot name when the user saves to an empty slot
|
||||
static void SetDefaultSaveName(int slot)
|
||||
static void SetDefaultSaveName(char *name, const char *append)
|
||||
{
|
||||
char *maplump = MAPNAME(gameepisode, gamemap);
|
||||
int maplumpnum = W_CheckNumForName(maplump);
|
||||
@ -1158,16 +1328,31 @@ static void SetDefaultSaveName(int slot)
|
||||
*ext = '\0';
|
||||
}
|
||||
|
||||
M_snprintf(savegamestrings[slot], SAVESTRINGSIZE, "%s (%s)", maplump,
|
||||
wadname);
|
||||
if (append)
|
||||
{
|
||||
M_snprintf(name, SAVESTRINGSIZE, "%s (%s) (%s)", maplump, wadname,
|
||||
append);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_snprintf(name, SAVESTRINGSIZE, "%s (%s)", maplump, wadname);
|
||||
}
|
||||
|
||||
free(wadname);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_snprintf(savegamestrings[slot], SAVESTRINGSIZE, "%s", maplump);
|
||||
if (append)
|
||||
{
|
||||
M_snprintf(name, SAVESTRINGSIZE, "%s (%s)", maplump, append);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_snprintf(name, SAVESTRINGSIZE, "%s", maplump);
|
||||
}
|
||||
}
|
||||
|
||||
M_StringToUpper(savegamestrings[slot]);
|
||||
M_StringToUpper(name);
|
||||
}
|
||||
|
||||
// [FG] override savegame name if it already starts with a map identifier
|
||||
@ -1188,16 +1373,22 @@ boolean MN_StartsWithMapIdentifier(char *str)
|
||||
return false;
|
||||
}
|
||||
|
||||
void M_SaveAutoSave(void)
|
||||
{
|
||||
char autosave_string[SAVESTRINGSIZE];
|
||||
SetDefaultSaveName(autosave_string, "Auto");
|
||||
G_SaveAutoSave(autosave_string);
|
||||
}
|
||||
|
||||
static boolean GamepadSave(int choice)
|
||||
{
|
||||
if (menu_input == pad_mode)
|
||||
{
|
||||
// Immediately save game using a default name.
|
||||
saveSlot = choice;
|
||||
savegamestrings[choice][0] = 0;
|
||||
SetDefaultSaveName(choice);
|
||||
SetDefaultSaveName(savegamestrings[choice], NULL);
|
||||
M_DoSave(choice);
|
||||
LoadDef.lastOn = choice;
|
||||
LoadAutoSaveDef.lastOn = choice + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1224,12 +1415,13 @@ static void M_SaveSelect(int choice)
|
||||
|| MN_StartsWithMapIdentifier(savegamestrings[choice]))
|
||||
{
|
||||
savegamestrings[choice][0] = 0;
|
||||
SetDefaultSaveName(choice);
|
||||
SetDefaultSaveName(savegamestrings[choice], NULL);
|
||||
}
|
||||
saveCharIndex = strlen(savegamestrings[choice]);
|
||||
|
||||
// [crispy] load the last game you saved
|
||||
LoadDef.lastOn = choice;
|
||||
LoadAutoSaveDef.lastOn = choice + 1;
|
||||
}
|
||||
|
||||
//
|
||||
@ -1449,7 +1641,7 @@ static void M_QuickSaveResponse(int ch)
|
||||
{
|
||||
if (MN_StartsWithMapIdentifier(savegamestrings[quickSaveSlot]))
|
||||
{
|
||||
SetDefaultSaveName(quickSaveSlot);
|
||||
SetDefaultSaveName(savegamestrings[quickSaveSlot], NULL);
|
||||
}
|
||||
M_DoSave(quickSaveSlot);
|
||||
M_StartSound(sfx_swtchx);
|
||||
@ -1472,8 +1664,8 @@ static void M_QuickSave(void)
|
||||
if (quickSaveSlot < 0)
|
||||
{
|
||||
MN_StartControlPanel();
|
||||
M_ReadSaveStrings();
|
||||
SetNextMenu(&SaveDef);
|
||||
M_ReadSaveStrings();
|
||||
quickSaveSlot = -2; // means to pick a slot now
|
||||
return;
|
||||
}
|
||||
@ -1514,8 +1706,8 @@ static void M_QuickLoad(void)
|
||||
{
|
||||
// [crispy] allow quickload before quicksave
|
||||
MN_StartControlPanel();
|
||||
M_ReadSaveStrings();
|
||||
SetNextMenu(&LoadDef);
|
||||
M_ReadSaveStrings();
|
||||
quickSaveSlot = -2; // means to pick a slot now
|
||||
return;
|
||||
}
|
||||
@ -2010,6 +2202,36 @@ void MN_BackSecondary(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateRectY(menu_t *menu, int m_y)
|
||||
{
|
||||
for (int i = 0; i < menu->numitems; i++)
|
||||
{
|
||||
menu->menuitems[i].rect.y = SAVE_LOAD_RECT_Y(m_y, i);
|
||||
}
|
||||
}
|
||||
|
||||
void M_ResetAutoSave(void)
|
||||
{
|
||||
int m_y;
|
||||
|
||||
if (G_AutoSaveEnabled())
|
||||
{
|
||||
loadsave_title_y = AUTOGRAPHIC_Y;
|
||||
m_y = M_Y_AUTOSAVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadsave_title_y = LOADGRAPHIC_Y;
|
||||
m_y = M_Y_LOADSAVE;
|
||||
}
|
||||
|
||||
LoadDef.y = m_y;
|
||||
UpdateRectY(&LoadDef, m_y);
|
||||
|
||||
SaveDef.y = m_y;
|
||||
UpdateRectY(&SaveDef, m_y);
|
||||
}
|
||||
|
||||
//
|
||||
// M_Init
|
||||
//
|
||||
@ -2029,6 +2251,7 @@ void M_Init(void)
|
||||
messageString = NULL;
|
||||
messageLastMenuActive = menuactive;
|
||||
quickSaveSlot = -1;
|
||||
M_ResetAutoSave();
|
||||
|
||||
int lumpnum = W_CheckNumForName("DBIGFONT");
|
||||
if (lumpnum > 0)
|
||||
@ -2467,9 +2690,31 @@ static void ClearHighlightedItems(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void M_UpdateLoadMenu(void)
|
||||
{
|
||||
if (G_AutoSaveEnabled()
|
||||
&& (currentMenu == &LoadDef || currentMenu == &LoadAutoSaveDef))
|
||||
{
|
||||
if (savepage == 0 && currentMenu == &LoadDef)
|
||||
{
|
||||
SetNextMenu(&LoadAutoSaveDef);
|
||||
}
|
||||
else if (savepage != 0 && currentMenu == &LoadAutoSaveDef)
|
||||
{
|
||||
SetNextMenu(&LoadDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static boolean AnyLoadSaveMenu(void)
|
||||
{
|
||||
return (currentMenu == &LoadDef || currentMenu == &SaveDef
|
||||
|| currentMenu == &LoadAutoSaveDef);
|
||||
}
|
||||
|
||||
static boolean SaveLoadResponder(menu_action_t action, int ch)
|
||||
{
|
||||
if (currentMenu != &LoadDef && currentMenu != &SaveDef)
|
||||
if (!AnyLoadSaveMenu())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -2481,6 +2726,7 @@ static boolean SaveLoadResponder(menu_action_t action, int ch)
|
||||
if (M_ToUpper(ch) == 'Y' || action == MENU_ENTER)
|
||||
{
|
||||
M_DeleteGame(old_menu_input == mouse_mode ? highlight_item : itemOn);
|
||||
M_ReadSaveStrings();
|
||||
M_StartSound(sfx_itemup);
|
||||
delete_verify = false;
|
||||
}
|
||||
@ -2501,6 +2747,7 @@ static boolean SaveLoadResponder(menu_action_t action, int ch)
|
||||
{
|
||||
savepage--;
|
||||
quickSaveSlot = -1;
|
||||
M_UpdateLoadMenu();
|
||||
M_ReadSaveStrings();
|
||||
M_StartSound(sfx_pstop);
|
||||
}
|
||||
@ -2512,6 +2759,7 @@ static boolean SaveLoadResponder(menu_action_t action, int ch)
|
||||
{
|
||||
savepage++;
|
||||
quickSaveSlot = -1;
|
||||
M_UpdateLoadMenu();
|
||||
M_ReadSaveStrings();
|
||||
M_StartSound(sfx_pstop);
|
||||
}
|
||||
@ -2627,6 +2875,14 @@ static boolean MouseResponder(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean AllowDeleteSaveGame(void)
|
||||
{
|
||||
return (((currentMenu == &LoadDef || currentMenu == &SaveDef)
|
||||
&& LoadDef.menuitems[itemOn].status)
|
||||
|| (currentMenu == &LoadAutoSaveDef
|
||||
&& LoadAutoSaveDef.menuitems[itemOn].status));
|
||||
}
|
||||
|
||||
boolean M_Responder(event_t *ev)
|
||||
{
|
||||
int ch;
|
||||
@ -3036,9 +3292,9 @@ boolean M_Responder(event_t *ev)
|
||||
|
||||
if (action == MENU_CLEAR)
|
||||
{
|
||||
if (currentMenu == &LoadDef || currentMenu == &SaveDef)
|
||||
if (AnyLoadSaveMenu())
|
||||
{
|
||||
if (LoadMenu[itemOn].status)
|
||||
if (AllowDeleteSaveGame())
|
||||
{
|
||||
M_StartSound(sfx_itemup);
|
||||
currentMenu->lastOn = itemOn;
|
||||
|
@ -57,6 +57,7 @@ void M_Init(void);
|
||||
|
||||
void MN_StartControlPanel(void);
|
||||
|
||||
void MN_ForcedLoadAutoSave(const char *msg);
|
||||
void MN_ForcedLoadGame(const char *msg); // killough 5/15/98: forced loadgames
|
||||
void MN_Trans(void); // killough 11/98: reset translucency
|
||||
void MN_SetupResetMenu(void);
|
||||
@ -87,8 +88,12 @@ extern int savepage;
|
||||
|
||||
extern const char *default_skill_strings[];
|
||||
|
||||
void M_ResetAutoSave(void);
|
||||
|
||||
void MN_SetQuickSaveSlot(int slot);
|
||||
|
||||
void M_SaveAutoSave(void);
|
||||
|
||||
void MN_InitMenuStrings(void);
|
||||
|
||||
boolean MN_StartsWithMapIdentifier(char *str);
|
||||
|
@ -3289,17 +3289,20 @@ static setup_menu_t gen_settings6[] = {
|
||||
{"Screen wipe effect", S_CHOICE | S_STRICT, OFF_CNTR_X, M_SPC,
|
||||
{"screen_melt"}, .strings_id = str_screen_melt},
|
||||
|
||||
{"On death action", S_CHOICE, OFF_CNTR_X, M_SPC, {"death_use_action"},
|
||||
.strings_id = str_death_use_action},
|
||||
|
||||
{"Demo progress bar", S_ONOFF, OFF_CNTR_X, M_SPC, {"demobar"}},
|
||||
|
||||
{"Screen flashes", S_ONOFF | S_STRICT, OFF_CNTR_X, M_SPC,
|
||||
{"palette_changes"}},
|
||||
|
||||
{"Invulnerability effect", S_CHOICE | S_STRICT, OFF_CNTR_X, M_SPC,
|
||||
{"invul_mode"}, .strings_id = str_invul_mode, .action = R_InvulMode},
|
||||
|
||||
{"Demo progress bar", S_ONOFF, OFF_CNTR_X, M_SPC, {"demobar"}},
|
||||
|
||||
{"On death action", S_CHOICE, OFF_CNTR_X, M_SPC, {"death_use_action"},
|
||||
.strings_id = str_death_use_action},
|
||||
|
||||
{"Auto save", S_ONOFF, OFF_CNTR_X, M_SPC, {"autosave"},
|
||||
.action = M_ResetAutoSave},
|
||||
|
||||
{"Organize save files", S_ONOFF | S_PRGWARN, OFF_CNTR_X, M_SPC,
|
||||
{"organize_savefiles"}},
|
||||
|
||||
|
17
src/p_user.c
17
src/p_user.c
@ -322,14 +322,19 @@ void P_DeathThink (player_t* player)
|
||||
{
|
||||
activate_death_use_reload = 1;
|
||||
|
||||
if (savegameslot >= 0)
|
||||
if (!G_AutoSaveEnabled() || !G_LoadAutoSaveDeathUse())
|
||||
{
|
||||
char *file = G_SaveGameName(savegameslot);
|
||||
G_LoadGame(file, savegameslot, false);
|
||||
free(file);
|
||||
if (savegameslot >= 0)
|
||||
{
|
||||
char *file = G_SaveGameName(savegameslot);
|
||||
G_LoadGame(file, savegameslot, false);
|
||||
free(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
player->playerstate = PST_REBORN;
|
||||
}
|
||||
}
|
||||
else
|
||||
player->playerstate = PST_REBORN;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user