UFO: Alien Invasion
Loading...
Searching...
No Matches
cp_save_callbacks.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23*/
24
26#include "../../cl_shared.h"
27#include "cp_save_callbacks.h"
28#include "cp_campaign.h"
29#include "cp_save.h"
30#include "cp_popup.h"
32
34
38static void SAV_ListSaveGames_f (void)
39{
40 if (cgi->Cmd_Argc() < 1) {
41 cgi->Com_Printf("usage: %s\n", cgi->Cmd_Argv(0));
42 return;
43 }
44
45 char pathMask[MAX_OSPATH];
46 cgi->GetRelativeSavePath(pathMask, sizeof(pathMask));
47 Q_strcat(pathMask, sizeof(pathMask), "/*.savx");
48
49 cgi->FS_BuildFileList(pathMask);
50 const char* path;
51 int idx = 0;
52 while ((path = cgi->FS_NextFileFromFileList(pathMask)) != nullptr) {
53 char fileName[MAX_OSPATH];
54 saveFileHeader_t header;
55 Com_StripExtension(path, fileName, sizeof(fileName));
56 const char *basename = Com_SkipPath(fileName);
57
58 if (SAV_LoadHeader(basename, &header))
59 cgi->UI_ExecuteConfunc("ui_add_savegame %i \"%s\" \"%s\" \"%s\" \"%s\"", idx++,
60 header.name, header.gameDate, header.realDate, basename);
61 }
62 cgi->FS_NextFileFromFileList(nullptr);
63}
64
65
70static void SAV_GameLoad_f (void)
71{
72 const char* error = nullptr;
73
74 /* get argument */
75 if (cgi->Cmd_Argc() < 2) {
76 cgi->Com_Printf("Usage: %s <filename>\n", cgi->Cmd_Argv(0));
77 return;
78 }
79
80 /* Check if savegame exists */
81 char buf[MAX_OSPATH];
82 cgi->GetRelativeSavePath(buf, sizeof(buf));
83 if (cgi->FS_CheckFile("%s%s.%s", buf, cgi->Cmd_Argv(1), SAVEGAME_EXTENSION) <= 0) {
84 cgi->Com_Printf("savegame file '%s' doesn't exist or an empty file\n", cgi->Cmd_Argv(1));
85 return;
86 }
87
88 cgi->Com_DPrintf(DEBUG_CLIENT, "load file '%s'\n", cgi->Cmd_Argv(1));
89
90 /* load and go to map */
91 if (!SAV_GameLoad(cgi->Cmd_Argv(1), &error)) {
92 cgi->Cbuf_Execute(); /* wipe outstanding campaign commands */
93 cgi->Cmd_ExecuteString("game_exit");
94 cgi->Cmd_ExecuteString("game_setmode campaign");
95 cgi->UI_Popup(_("Error"), "%s\n%s", _("Error loading game."), error ? error : "");
96 }
97}
98
104static void SAV_GameContinue_f (void)
105{
106 const char* error = nullptr;
107
108 if (cgi->CL_OnBattlescape()) {
109 cgi->UI_PopWindow(false);
110 return;
111 }
112
113 if (!CP_IsRunning()) {
114 /* try to load the last saved campaign */
115 if (!SAV_GameLoad(cl_lastsave->string, &error)) {
116 cgi->Cbuf_Execute(); /* wipe outstanding campaign commands */
117 cgi->UI_Popup(_("Error"), "%s\n%s", _("Error loading game."), error ? error : "");
118 cgi->Cmd_ExecuteString("game_exit");
119 }
120 } else {
121 /* just continue the current running game */
122 cgi->UI_PopWindow(false);
123 }
124}
125
131static void SAV_GameSave_f (void)
132{
133 /* get argument */
134 if (cgi->Cmd_Argc() < 2) {
135 cgi->Com_Printf("Usage: %s <filename> <comment|*cvar>\n", cgi->Cmd_Argv(0));
136 return;
137 }
138
139 /* get comment */
140 char comment[MAX_VAR] = "";
141 if (cgi->Cmd_Argc() > 2) {
142 const char* arg = cgi->Cmd_Argv(2);
143 Q_strncpyz(comment, arg, sizeof(comment));
144 }
145
146 char* error = nullptr;
147 const bool result = SAV_GameSave(cgi->Cmd_Argv(1), comment, &error);
148 if (result)
149 return;
150
151 if (error)
152 CP_Popup(_("Note"), "%s\n%s", _("Error saving game."), error);
153 else
154 CP_Popup(_("Note"), "%s\n%s", "%s\n", _("Error saving game."));
155}
156
160static void SAV_GameDelete_f (void)
161{
162 if (cgi->Cmd_Argc() != 2) {
163 cgi->Com_Printf("Usage: %s <filename>\n", cgi->Cmd_Argv(0));
164 return;
165 }
166 const char* savegame = cgi->Cmd_Argv(1);
167 char buf[MAX_OSPATH];
168
169 cgi->GetAbsoluteSavePath(buf, sizeof(buf));
170 Q_strcat(buf, sizeof(buf), "%s.%s", savegame, SAVEGAME_EXTENSION);
171
172 cgi->FS_RemoveFile(buf);
173}
174
179static void SAV_GameQuickLoadInit_f (void)
180{
181 if (cgi->CL_OnBattlescape()) {
182 return;
183 }
184
185 char buf[MAX_OSPATH];
186 cgi->GetRelativeSavePath(buf, sizeof(buf));
187 if (cgi->FS_CheckFile("%sslotquick.%s", buf, SAVEGAME_EXTENSION) > 0) {
188 cgi->UI_PushWindow("quickload");
189 }
190}
191
195static void SAV_GameQuickSave_f (void)
196{
197 if (!CP_IsRunning())
198 return;
199 if (cgi->CL_OnBattlescape())
200 return;
201
202 char* error = nullptr;
203 bool result = SAV_GameSave("slotquick", _("QuickSave"), &error);
204 if (!result)
205 cgi->Com_Printf("Error saving the xml game: %s\n", error ? error : "");
206 else
207 MS_AddNewMessage(_("Quicksave"), _("Campaign was successfully saved."), MSG_INFO);
208}
209
214static void SAV_GameQuickLoad_f (void)
215{
216 const char* error = nullptr;
217
218 if (cgi->CL_OnBattlescape()) {
219 cgi->Com_Printf("Could not load the campaign while you are on the battlefield\n");
220 return;
221 }
222
223 if (!SAV_GameLoad("slotquick", &error)) {
224 cgi->Cbuf_Execute(); /* wipe outstanding campaign commands */
225 CP_Popup(_("Error"), "%s\n%s", _("Error loading game."), error ? error : "");
226 } else {
227 MS_AddNewMessage(_("Campaign loaded"), _("Quicksave campaign was successfully loaded."), MSG_INFO);
229 }
230}
231
235static void SAV_GameSaveAllowed_f (void)
236{
237 if (cgi->Cmd_Argc() < 2) {
238 cgi->Com_Printf("Usage: %s <confunc_callback>\n", cgi->Cmd_Argv(0));
239 return;
240 }
241 const char* callback = cgi->Cmd_Argv(1);
242
243 char* error = nullptr;
244 bool allowed = SAV_GameSaveAllowed(&error);
245
246 cgi->UI_ExecuteConfunc("%s %s \"%s\"", callback, allowed ? "true" : "false", error ? error : "");
247}
248
249static const cmdList_t saveCallbacks[] = {
250 {"game_listsaves", SAV_ListSaveGames_f, "Lists available savegames"},
251 {"game_load", SAV_GameLoad_f, "Loads a given filename"},
252 {"game_saveallowed", SAV_GameSaveAllowed_f, "Checks if saving the game is allowed"},
253 {"game_save", SAV_GameSave_f, "Saves to a given filename"},
254 {"game_delete", SAV_GameDelete_f, "Deletes a given filename"},
255 {"game_continue", SAV_GameContinue_f, "Continue with the last saved game"},
256 {"game_quickloadinit", SAV_GameQuickLoadInit_f, "Load the game from the quick save slot."},
257 {"game_quickload", SAV_GameQuickLoad_f, "Load the game from the quick save slot."},
258 {"game_quicksave", SAV_GameQuickSave_f, "Save to the quick save slot."},
259 {nullptr, nullptr, nullptr}
260};
261
266{
267 cgi->Cmd_TableAddList(saveCallbacks);
268
269 cl_lastsave = cgi->Cvar_Get("cl_lastsave", "", CVAR_ARCHIVE, "Last saved slot - use for the continue-campaign function");
270}
271
276{
277 cgi->Cmd_TableRemoveList(saveCallbacks);
278}
Share stuff between the different cgame implementations.
#define _(String)
Definition cl_shared.h:44
bool CP_IsRunning(void)
Checks whether a campaign mode game is running.
Header file for single player campaign control.
const cgame_import_t * cgi
uiMessageListNodeMessage_t * MS_AddNewMessage(const char *title, const char *text, messageType_t type, technology_t *pedia, bool popup, bool playSound)
Adds a new message to message stack.
@ MSG_INFO
Definition cp_messages.h:34
void CP_CheckBaseAttacks(void)
Check and start baseattack missions.
Campaign mission headers.
void CP_Popup(const char *title, const char *text,...)
Wrapper around UI_Popup.
Definition cp_popup.cpp:474
bool SAV_GameLoad(const char *file, const char **error)
Loads the given savegame from an xml File.
Definition cp_save.cpp:152
bool SAV_LoadHeader(const char *filename, saveFileHeader_t *header)
Loads and verifies a savegame header.
Definition cp_save.cpp:114
bool SAV_GameSaveAllowed(char **error=nullptr)
Determines if saving is allowed.
Definition cp_save.cpp:267
bool SAV_GameSave(const char *filename, const char *comment, char **error)
This is a savegame function which stores the game in xml-Format.
Definition cp_save.cpp:293
Defines some savefile structures.
#define SAVEGAME_EXTENSION
Definition cp_save.h:34
static void SAV_GameLoad_f(void)
Console command to load a savegame.
void SAV_InitCallbacks(void)
Register UI callbacks for the savegame-subsystem.
static void SAV_GameQuickSave_f(void)
Saves to the quick save slot.
static const cmdList_t saveCallbacks[]
static void SAV_GameQuickLoadInit_f(void)
Checks whether there is a quicksave file and opens the quickload menu if there is one.
void SAV_ShutdownCallbacks(void)
UnregisterUI callbacks for the savegame-subsystem.
static void SAV_GameContinue_f(void)
Loads the last saved game.
static void SAV_GameQuickLoad_f(void)
Loads the quick save slot.
static void SAV_GameDelete_f(void)
Removes savegame file.
static void SAV_GameSave_f(void)
Console command binding for save function.
static void SAV_GameSaveAllowed_f(void)
Returns whether saving game is allowed.
static cvar_t * cl_lastsave
static void SAV_ListSaveGames_f(void)
Console command to list savegames.
Header file for Savegame UI callbacks.
#define CVAR_ARCHIVE
Definition cvar.h:40
#define DEBUG_CLIENT
Definition defines.h:59
Filesystem header file.
#define MAX_OSPATH
Definition filesys.h:44
voidpf void * buf
Definition ioapi.h:42
#define MAX_VAR
Definition shared.h:36
void Com_StripExtension(const char *in, char *out, const size_t size)
Removes the file extension from a filename.
Definition shared.cpp:259
const char * Com_SkipPath(const char *pathname)
Returns just the filename from a given path.
Definition shared.cpp:37
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition shared.cpp:457
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition shared.cpp:475
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
Definition cvar.h:71
char realDate[32]
Definition cp_save.h:44
char gameDate[32]
Definition cp_save.h:43
char name[32]
Definition cp_save.h:42