Skip to content

Commit

Permalink
libcommon: Enhanced loadgame and savegame console commands
Browse files Browse the repository at this point in the history
These two commands now also implement the logic for prompting the user
to confirm a load/save game request, previously used with the <quick>
save slot only.

Each command now accepts a new "confirm" argument for the purpose of
declaring confirmation without being prompted. Note that this logic is
additional to that of cvar "game-save-confirm", meaning the user can
leave this enabled yet still override it.

Added read-only cvar "game-save-last-slot" which as the name suggests,
is the logical slot number of the last used save slot. There is also
a new mnemonic <last>, which can be used as a symbolic reference which
is automatically resolved with both loadgame and savegame commands.

The console commands quickload and quicksave are essentially glorified
aliases now.
  • Loading branch information
danij-deng committed Jan 21, 2012
1 parent 21d0201 commit 64b2abc
Show file tree
Hide file tree
Showing 12 changed files with 200 additions and 175 deletions.
13 changes: 7 additions & 6 deletions doomsday/plugins/common/include/p_saveio.h
Expand Up @@ -75,12 +75,13 @@ void SV_UpdateGameSaveInfo(void);
* game-save slot.
*
* @param str String to be parsed. Parse is divided into three passes.
* Pass 1: Check for a known game-save name which matches this.
* Search is in ascending logical slot order 0...N (where N is
* the number of available save slots in the current game).
* Pass 2: Check for keyword identifiers.
* <quick> = The currently nominated "quick save" slot.
* Pass 3: Check for a logical save slot identifier.
* Pass 1: Check for a known game-save name which matches this.
* Search is in ascending logical slot order 0..N (where N is the
* number of available save slots in the current game).
* Pass 2: Check for keyword identifiers.
* <last> = The last used slot.
* <quick> = The currently nominated "quick save" slot.
* Pass 3: Check for a logical save slot number.
*
* @return Save slot identifier of the slot else @c -1
*/
Expand Down
241 changes: 117 additions & 124 deletions doomsday/plugins/common/src/g_game.c
Expand Up @@ -135,11 +135,11 @@ D_CMD(EndGame);
D_CMD(HelpScreen);
D_CMD(ListMaps);
D_CMD(LoadGame);
D_CMD(LoadGameName);
D_CMD(OpenLoadMenu);
D_CMD(QuickLoadGame);
D_CMD(QuickSaveGame);
D_CMD(SaveGame);
D_CMD(SaveGameName);
D_CMD(OpenSaveMenu);

void G_PlayerReborn(int player);
void G_InitNew(skillmode_t skill, uint episode, uint map);
Expand Down Expand Up @@ -418,12 +418,15 @@ ccmdtemplate_t gameCmds[] = {
{ "endgame", "", CCmdEndGame },
{ "helpscreen", "", CCmdHelpScreen },
{ "listmaps", "", CCmdListMaps },
{ "loadgame", "s", CCmdLoadGameName },
{ "loadgame", "", CCmdLoadGame },
{ "loadgame", "ss", CCmdLoadGame },
{ "loadgame", "s", CCmdLoadGame },
{ "loadgame", "", CCmdOpenLoadMenu },
{ "quickload", "", CCmdQuickLoadGame },
{ "quicksave", "", CCmdQuickSaveGame },
{ "savegame", "s*", CCmdSaveGameName },
{ "savegame", "", CCmdSaveGame },
{ "savegame", "sss", CCmdSaveGame },
{ "savegame", "ss", CCmdSaveGame },
{ "savegame", "s", CCmdSaveGame },
{ "savegame", "", CCmdOpenSaveMenu },
{ "togglegamma", "", CCmdCycleTextureGamma },
{ NULL }
};
Expand Down Expand Up @@ -2331,7 +2334,7 @@ boolean G_LoadGame(int slot)

// Check whether this slot is in use. We do this here also because we
// need to provide our caller with instant feedback. Naturally this is
// no guarantee that the game-save will be acessible come load time.
// no guarantee that the game-save will be accessible come load time.

// First ensure we have up-to-date info.
SV_UpdateGameSaveInfo();
Expand Down Expand Up @@ -3275,7 +3278,7 @@ static ddstring_t* composeScreenshotFileName(void)
void G_DoScreenShot(void)
{
ddstring_t* name = composeScreenshotFileName();
if(NULL == name)
if(!name)
{
Con_Message("G_DoScreenShot: Failed composing file name, screenshot not saved.\n");
return;
Expand Down Expand Up @@ -3306,167 +3309,170 @@ static void openSaveMenu(void)
Hu_MenuSetActivePage(Hu_MenuFindPageByName("SaveGame"));
}

int G_QuickLoadGameResponse(msgresponse_t response, void* context)
D_CMD(OpenLoadMenu)
{
if(!G_IsLoadGamePossible()) return false;
openLoadMenu();
return true;
}

D_CMD(OpenSaveMenu)
{
if(!G_IsSaveGamePossible()) return false;
openSaveMenu();
return true;
}

int loadGameConfirmResponse(msgresponse_t response, void* context)
{
if(response == MSG_YES)
{
const int slot = Con_GetInteger("game-save-quick-slot");
const int slot = *(int*)context;
G_LoadGame(slot);
}
return true;
}

void G_QuickLoadGame(void)
D_CMD(LoadGame)
{
const int slot = Con_GetInteger("game-save-quick-slot");
const gamesaveinfo_t* info;
char buf[80];
const boolean confirm = (argc == 3 && !stricmp(argv[2], "confirm"));
int slot;

if(G_QuitInProgress()) return;
if(G_QuitInProgress()) return false;
if(!G_IsLoadGamePossible()) return false;

if(IS_NETGAME)
{
S_LocalSound(SFX_QUICKLOAD_PROMPT, NULL);
Hu_MsgStart(MSG_ANYKEY, QLOADNET, NULL, NULL);
return;
return false;
}

if(0 > slot || !SV_IsGameSaveSlotUsed(slot))
slot = SV_ParseGameSaveSlot(argv[1]);
if(SV_IsGameSaveSlotUsed(slot))
{
// A known used slot identifier.
const gamesaveinfo_t* info;
char buf[80];

if(confirm || !cfg.confirmQuickGameSave)
{
// Try to schedule a GA_LOADGAME action.
S_LocalSound(SFX_MENU_ACCEPT, NULL);
return G_LoadGame(slot);
}

info = SV_GetGameSaveInfoForSlot(slot);
dd_snprintf(buf, 80, QLPROMPT, Str_Text(&info->name));

S_LocalSound(SFX_QUICKLOAD_PROMPT, NULL);
Hu_MsgStart(MSG_YESNO, buf, loadGameConfirmResponse, (void*)&slot);
return true;
}
else if(!stricmp(argv[1], "quick") || !stricmp(argv[1], "<quick>"))
{
S_LocalSound(SFX_QUICKLOAD_PROMPT, NULL);
Hu_MsgStart(MSG_ANYKEY, QSAVESPOT, NULL, NULL);
return;
return true;
}

if(!cfg.confirmQuickGameSave)
// Clearly the caller needs some assistance...
Con_Message("Failed to determine game-save slot from \"%s\"\n", argv[1]);

// We'll open the load menu if caller is the console.
// Reasoning: User attempted to load a named game-save however the name
// specified didn't match anything known. Opening the load menu allows
// the user to see the names of the known game-saves.
if(CMDS_CONSOLE == src)
{
S_LocalSound(SFX_MENU_ACCEPT, NULL);
G_LoadGame(slot);
return;
Con_Message("Opening game-save load menu...\n");
openLoadMenu();
return true;
}

info = SV_GetGameSaveInfoForSlot(slot);
dd_snprintf(buf, 80, QLPROMPT, Str_Text(&info->name));
// No action means the command failed.
return false;
}

S_LocalSound(SFX_QUICKLOAD_PROMPT, NULL);
Hu_MsgStart(MSG_YESNO, buf, G_QuickLoadGameResponse, NULL);
D_CMD(QuickLoadGame)
{
/// @todo Implement console command scripts?
return DD_Execute(true, "loadgame quick");
}

int G_QuickSaveGameResponse(msgresponse_t response, void* context)
typedef struct {
int slot;
const char* name;
} savegameconfirmresponse_params_t;

int saveGameConfirmResponse(msgresponse_t response, void* context)
{
if(response == MSG_YES)
{
const int slot = Con_GetInteger("game-save-quick-slot");
G_SaveGame(slot);
savegameconfirmresponse_params_t* p = (savegameconfirmresponse_params_t*)context;
G_SaveGame2(p->slot, p->name);
}
return true;
}

void G_QuickSaveGame(void)
D_CMD(SaveGame)
{
const boolean confirm = (argc >= 3 && !stricmp(argv[argc-1], "confirm"));
player_t* player = &players[CONSOLEPLAYER];
const int slot = Con_GetInteger("game-save-quick-slot");
boolean slotIsUsed;
char buf[80];
int slot;

if(G_QuitInProgress()) return;
if(G_QuitInProgress()) return false;

if(player->playerState == PST_DEAD || Get(DD_PLAYBACK))
{
S_LocalSound(SFX_QUICKSAVE_PROMPT, NULL);
Hu_MsgStart(MSG_ANYKEY, SAVEDEAD, NULL, NULL);
return;
return true;
}

if(G_GameState() != GS_MAP)
{
S_LocalSound(SFX_QUICKSAVE_PROMPT, NULL);
Hu_MsgStart(MSG_ANYKEY, SAVEOUTMAP, NULL, NULL);
return;
return true;
}

// If no quick-save slot has been nominated - allow doing so now.
if(0 > slot)
slot = SV_ParseGameSaveSlot(argv[1]);
if(slot >= 0)
{
Hu_MenuCommand(MCMD_OPEN);
Hu_MenuUpdateGameSaveWidgets();
Hu_MenuSetActivePage(Hu_MenuFindPageByName("SaveGame"));
menuNominatingQuickSaveSlot = true;
return;
}
// A known slot identifier.
const boolean slotIsUsed = SV_IsGameSaveSlotUsed(slot);
const char* name = (argc >= 3 && stricmp(argv[2], "confirm"))? argv[2] : NULL;
char buf[80];

slotIsUsed = SV_IsGameSaveSlotUsed(slot);
if(!slotIsUsed || !cfg.confirmQuickGameSave)
{
S_LocalSound(SFX_MENU_ACCEPT, NULL);
G_SaveGame(slot);
return;
}
if(!slotIsUsed || confirm || !cfg.confirmQuickGameSave)
{
// Try to schedule a GA_LOADGAME action.
S_LocalSound(SFX_MENU_ACCEPT, NULL);
return G_SaveGame2(slot, name);
}

if(slotIsUsed)
{
{
savegameconfirmresponse_params_t p;
const gamesaveinfo_t* info = SV_GetGameSaveInfoForSlot(slot);
sprintf(buf, QSPROMPT, Str_Text(&info->name));
}
else
{
char identifier[11];
dd_snprintf(identifier, 10, "#%10.i", slot);
dd_snprintf(buf, 80, QLPROMPT, identifier);
}
dd_snprintf(buf, 80, QSPROMPT, Str_Text(&info->name));

S_LocalSound(SFX_QUICKSAVE_PROMPT, NULL);
Hu_MsgStart(MSG_YESNO, buf, G_QuickSaveGameResponse, NULL);
}
p.slot = slot;
p.name = name;

D_CMD(LoadGameName)
{
int slot;
if(!G_IsLoadGamePossible()) return false;

slot = SV_ParseGameSaveSlot(argv[1]);
if(slot >= 0)
{
// A known slot identifier. Try to schedule a GA_LOADGAME action.
return G_LoadGame(slot);
}

// Clearly the caller needs some assistance...
Con_Message("Failed to determine game-save slot from \"%s\"\n", argv[1]);

// We'll open the load menu if caller is the console.
// Reasoning: User attempted to load a named game-save however the name
// specified didn't match anything known. Opening the load menu allows
// the user to see the names of the known game-saves.
if(CMDS_CONSOLE == src)
{
Con_Message("Opening game-save load menu...\n");
openLoadMenu();
S_LocalSound(SFX_QUICKSAVE_PROMPT, NULL);
Hu_MsgStart(MSG_YESNO, buf, saveGameConfirmResponse, (void*)&p);
}
return true;
}

// No action means the command failed.
return false;
}

D_CMD(LoadGame)
{
if(!G_IsLoadGamePossible()) return false;
openLoadMenu();
return true;
}

D_CMD(SaveGameName)
{
int slot;
if(!G_IsSaveGamePossible()) return false;

slot = SV_ParseGameSaveSlot(argv[1]);
if(slot >= 0)
else if(!stricmp(argv[1], "quick") || !stricmp(argv[1], "<quick>"))
{
// A known slot identifier. Try to schedule a GA_SAVEGAME action.
// We do not care if there is a save already present in this slot.
return G_SaveGame2(slot, argc > 2? argv[2] : NULL);
// No quick-save slot has been nominated - allow doing so now.
Hu_MenuCommand(MCMD_OPEN);
Hu_MenuUpdateGameSaveWidgets();
Hu_MenuSetActivePage(Hu_MenuFindPageByName("SaveGame"));
menuNominatingQuickSaveSlot = true;
return true;
}

// Clearly the caller needs some assistance...
Expand All @@ -3475,23 +3481,10 @@ D_CMD(SaveGameName)
return false;
}

D_CMD(SaveGame)
{
if(!G_IsSaveGamePossible()) return false;
openSaveMenu();
return true;
}

D_CMD(QuickLoadGame)
{
G_QuickLoadGame();
return true;
}

D_CMD(QuickSaveGame)
{
G_QuickSaveGame();
return true;
/// @todo Implement console command scripts?
return DD_Execute(true, "savegame quick");
}

D_CMD(HelpScreen)
Expand Down

0 comments on commit 64b2abc

Please sign in to comment.