mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-02-16 17:11:33 +00:00
Squashed commit
This commit is contained in:
parent
2ef231c073
commit
19f22aaf82
38 changed files with 1019 additions and 199 deletions
|
@ -314,7 +314,10 @@ typedef struct xcommand_s
|
|||
const char *name;
|
||||
struct xcommand_s *next;
|
||||
com_func_t function;
|
||||
com_func_t basefunction;
|
||||
com_flags_t flags;
|
||||
boolean luacmd;
|
||||
boolean replaced;
|
||||
} xcommand_t;
|
||||
|
||||
static xcommand_t *com_commands = NULL; // current commands
|
||||
|
@ -514,7 +517,10 @@ void COM_AddCommand(const char *name, com_func_t func, com_flags_t flags)
|
|||
cmd->name = name;
|
||||
cmd->function = func;
|
||||
cmd->flags = flags;
|
||||
cmd->basefunction = func;
|
||||
cmd->next = com_commands;
|
||||
cmd->luacmd = false;
|
||||
cmd->replaced = false;
|
||||
com_commands = cmd;
|
||||
}
|
||||
|
||||
|
@ -538,6 +544,8 @@ int COM_AddLuaCommand(const char *name)
|
|||
{
|
||||
// replace the built in command.
|
||||
cmd->function = COM_Lua_f;
|
||||
cmd->replaced = true;
|
||||
cmd->luacmd = true;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -548,10 +556,97 @@ int COM_AddLuaCommand(const char *name)
|
|||
cmd->function = COM_Lua_f;
|
||||
cmd->flags = COM_LUA;
|
||||
cmd->next = com_commands;
|
||||
cmd->luacmd = false;
|
||||
com_commands = cmd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Delete Lua-defined CCMDs and CVARs.
|
||||
*/
|
||||
void COM_RemoveLuaCommands(void)
|
||||
{
|
||||
consvar_t *cvar, *prevcvar = NULL;
|
||||
xcommand_t *cmd, *prevcmd = NULL;
|
||||
|
||||
cvar = consvar_vars;
|
||||
while (cvar)
|
||||
{
|
||||
if (cvar->flags & CV_LUAVAR)
|
||||
{
|
||||
// head
|
||||
if (cvar == consvar_vars)
|
||||
consvar_vars = cvar->next;
|
||||
if (prevcvar && prevcvar->next == cvar)
|
||||
prevcvar->next = cvar->next;
|
||||
}
|
||||
prevcvar = cvar;
|
||||
cvar = cvar->next;
|
||||
}
|
||||
|
||||
// Fix the tail
|
||||
if (prevcvar->flags & CV_LUAVAR)
|
||||
{
|
||||
cvar = consvar_vars;
|
||||
while (cvar)
|
||||
{
|
||||
if (cvar->next == prevcvar)
|
||||
{
|
||||
cvar->next = NULL;
|
||||
break;
|
||||
}
|
||||
cvar = cvar->next;
|
||||
}
|
||||
}
|
||||
|
||||
cmd = com_commands;
|
||||
while (cmd)
|
||||
{
|
||||
if (cmd->luacmd)
|
||||
{
|
||||
if (cmd->replaced)
|
||||
{
|
||||
cmd->function = cmd->basefunction;
|
||||
cmd->luacmd = false;
|
||||
cmd->replaced = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// head
|
||||
if (cmd == com_commands)
|
||||
com_commands = cmd->next;
|
||||
if (prevcmd && prevcmd->next == cmd)
|
||||
prevcmd->next = cmd->next;
|
||||
}
|
||||
}
|
||||
prevcmd = cmd;
|
||||
cmd = cmd->next;
|
||||
}
|
||||
|
||||
// Fix the tail
|
||||
if (prevcmd->luacmd)
|
||||
{
|
||||
if (prevcmd->replaced)
|
||||
{
|
||||
prevcmd->function = prevcmd->basefunction;
|
||||
prevcmd->luacmd = false;
|
||||
prevcmd->replaced = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = com_commands;
|
||||
while (cmd)
|
||||
{
|
||||
if (cmd->next == prevcmd)
|
||||
{
|
||||
cmd->next = NULL;
|
||||
break;
|
||||
}
|
||||
cmd = cmd->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Tests if a command exists.
|
||||
*
|
||||
* \param com_name Name to test for.
|
||||
|
|
|
@ -38,6 +38,7 @@ typedef void (*com_func_t)(void);
|
|||
|
||||
void COM_AddCommand(const char *name, com_func_t func, com_flags_t flags);
|
||||
int COM_AddLuaCommand(const char *name);
|
||||
void COM_RemoveLuaCommands(void);
|
||||
|
||||
size_t COM_Argc(void);
|
||||
const char *COM_Argv(size_t arg); // if argv > argc, returns empty string
|
||||
|
@ -121,6 +122,7 @@ typedef enum
|
|||
// used on menus
|
||||
CV_CHEAT = 2048, // Don't let this be used in multiplayer unless cheats are on.
|
||||
CV_ALLOWLUA = 4096,/* Let this be called from Lua */
|
||||
CV_LUAVAR = 8192, // Was registered from Lua
|
||||
} cvflags_t;
|
||||
|
||||
typedef struct CV_PossibleValue_s
|
||||
|
|
89
src/d_main.c
89
src/d_main.c
|
@ -79,7 +79,8 @@
|
|||
#endif
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h" // 3D View Rendering
|
||||
#include "hardware/hw_main.h"
|
||||
#include "hardware/hw_glob.h"
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS
|
||||
|
@ -133,6 +134,9 @@ menucolor_t *menucolorhead, *menucolortail;
|
|||
char savegamename[256];
|
||||
char liveeventbackup[256];
|
||||
|
||||
char basesavegamename[256];
|
||||
char baseliveeventbackup[256];
|
||||
|
||||
char srb2home[256] = ".";
|
||||
char srb2path[256] = ".";
|
||||
boolean usehome = true;
|
||||
|
@ -1333,6 +1337,9 @@ void D_SRB2Main(void)
|
|||
|
||||
snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", userhome);
|
||||
#endif // DEFAULTDIR
|
||||
|
||||
strcpy(basesavegamename, savegamename);
|
||||
strcpy(baseliveeventbackup, liveeventbackup);
|
||||
}
|
||||
|
||||
configfile[sizeof configfile - 1] = '\0';
|
||||
|
@ -1751,6 +1758,86 @@ void D_SRB2Main(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Reload all files.
|
||||
void D_ReloadFiles(void)
|
||||
{
|
||||
// Set the initial state
|
||||
G_InitialState();
|
||||
|
||||
// Free textures
|
||||
R_FlushTextureCache();
|
||||
|
||||
numtextures = 0;
|
||||
|
||||
// Unload the level
|
||||
P_UnloadLevel();
|
||||
|
||||
// Free patches
|
||||
Patch_FreeTag(PU_PATCH);
|
||||
Patch_FreeTag(PU_PATCH_LOWPRIORITY);
|
||||
Patch_FreeTag(PU_PATCH_ROTATED);
|
||||
Patch_FreeTag(PU_SPRITE);
|
||||
Patch_FreeTag(PU_HUDGFX);
|
||||
|
||||
// Load SOC and Lua.
|
||||
for (INT32 i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (W_IsFilePresent(i))
|
||||
W_LoadFileScripts(i, i < mainwads);
|
||||
}
|
||||
|
||||
// Reload textures and sprites.
|
||||
R_LoadTextures();
|
||||
R_InitSprites();
|
||||
R_ReInitColormaps(0);
|
||||
|
||||
// Reload ANIMATED / ANIMDEFS
|
||||
P_InitPicAnims();
|
||||
|
||||
// Flush and reload HUD graphics
|
||||
ST_UnloadGraphics();
|
||||
HU_LoadGraphics();
|
||||
ST_LoadGraphics();
|
||||
ST_ReloadSkinFaceGraphics();
|
||||
}
|
||||
|
||||
void D_RestartGame(void)
|
||||
{
|
||||
if (netgame)
|
||||
{
|
||||
CONS_Printf(M_GetText("You can't restart the game while in a netgame.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the current configuration file, and the gamedata.
|
||||
D_SaveUserPrefs();
|
||||
|
||||
// We're deleting some files
|
||||
while (numwadfiles > mainwads + 1) // don't delete music.dta
|
||||
{
|
||||
W_UnloadFile(wadfiles[numwadfiles - 1]);
|
||||
wadfiles[numwadfiles - 1] = NULL;
|
||||
numwadfiles--;
|
||||
}
|
||||
|
||||
// Put everything back on its place
|
||||
D_ReloadFiles();
|
||||
|
||||
// Load the default game data.
|
||||
G_LoadGameData(clientGamedata);
|
||||
M_CopyGameData(serverGamedata, clientGamedata);
|
||||
|
||||
// Done. Start the intro.
|
||||
F_StartIntro();
|
||||
}
|
||||
|
||||
// Save the current configuration file, and the gamedata.
|
||||
void D_SaveUserPrefs(void)
|
||||
{
|
||||
M_SaveConfig(NULL);
|
||||
G_SaveGameData(clientGamedata);
|
||||
}
|
||||
|
||||
const char *D_Home(void)
|
||||
{
|
||||
const char *userhome = NULL;
|
||||
|
|
|
@ -38,6 +38,15 @@ void D_SRB2Loop(void) FUNCNORETURN;
|
|||
//
|
||||
void D_SRB2Main(void);
|
||||
|
||||
// Restart the game
|
||||
void D_RestartGame(void);
|
||||
|
||||
// Set the initial state and reload files.
|
||||
void D_ReloadFiles(void);
|
||||
|
||||
// Save the current configuration file, and the gamedata.
|
||||
void D_SaveUserPrefs(void);
|
||||
|
||||
// Called by IO functions when input is detected.
|
||||
void D_PostEvent(const event_t *ev);
|
||||
void D_ProcessEvents(void);
|
||||
|
|
152
src/d_netcmd.c
152
src/d_netcmd.c
|
@ -69,6 +69,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum);
|
|||
static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Addfoldercmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Delfilecmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Pause(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Suicide(UINT8 **cp, INT32 playernum);
|
||||
static void Got_RandomSeed(UINT8 **cp, INT32 playernum);
|
||||
|
@ -121,11 +122,14 @@ static void Command_ResetCamera_f(void);
|
|||
|
||||
static void Command_Addfile(void);
|
||||
static void Command_Addfolder(void);
|
||||
static void Command_Delfile(void);
|
||||
static void Command_ListWADS_f(void);
|
||||
static void Command_RunSOC(void);
|
||||
static void Command_Pause(void);
|
||||
static void Command_Suicide(void);
|
||||
|
||||
static void Command_Restartgame(void);
|
||||
|
||||
static void Command_Version_f(void);
|
||||
#ifdef UPDATE_ALERT
|
||||
static void Command_ModDetails_f(void);
|
||||
|
@ -421,6 +425,7 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
|
|||
"RUNSOC",
|
||||
"REQADDFILE",
|
||||
"REQADDFOLDER",
|
||||
"DELFILE",
|
||||
"SETMOTD",
|
||||
"SUICIDE",
|
||||
"LUACMD",
|
||||
|
@ -457,6 +462,7 @@ void D_RegisterServerCommands(void)
|
|||
RegisterNetXCmd(XD_ADDFOLDER, Got_Addfoldercmd);
|
||||
RegisterNetXCmd(XD_REQADDFILE, Got_RequestAddfilecmd);
|
||||
RegisterNetXCmd(XD_REQADDFOLDER, Got_RequestAddfoldercmd);
|
||||
RegisterNetXCmd(XD_DELFILE, Got_Delfilecmd);
|
||||
RegisterNetXCmd(XD_PAUSE, Got_Pause);
|
||||
RegisterNetXCmd(XD_SUICIDE, Got_Suicide);
|
||||
RegisterNetXCmd(XD_RUNSOC, Got_RunSOCcmd);
|
||||
|
@ -489,12 +495,15 @@ void D_RegisterServerCommands(void)
|
|||
|
||||
COM_AddCommand("addfolder", Command_Addfolder, COM_LUA);
|
||||
COM_AddCommand("addfile", Command_Addfile, COM_LUA);
|
||||
COM_AddCommand("delfile", Command_Delfile, COM_LUA);
|
||||
COM_AddCommand("listwad", Command_ListWADS_f, COM_LUA);
|
||||
|
||||
COM_AddCommand("runsoc", Command_RunSOC, COM_LUA);
|
||||
COM_AddCommand("pause", Command_Pause, COM_LUA);
|
||||
COM_AddCommand("suicide", Command_Suicide, COM_LUA);
|
||||
|
||||
COM_AddCommand("restartgame", Command_Restartgame, 0);
|
||||
|
||||
COM_AddCommand("gametype", Command_ShowGametype_f, COM_LUA);
|
||||
COM_AddCommand("version", Command_Version_f, COM_LUA);
|
||||
#ifdef UPDATE_ALERT
|
||||
|
@ -3470,7 +3479,7 @@ static void Command_Addfile(void)
|
|||
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (wadfiles[i]->type == RET_FOLDER)
|
||||
if (!W_IsFilePresent(i) || wadfiles[i]->type == RET_FOLDER)
|
||||
continue;
|
||||
|
||||
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
|
||||
|
@ -3595,7 +3604,7 @@ static void Command_Addfolder(void)
|
|||
// Check if the folder is already added.
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (wadfiles[i]->type != RET_FOLDER)
|
||||
if (!W_IsFilePresent(i) || wadfiles[i]->type != RET_FOLDER)
|
||||
continue;
|
||||
|
||||
if (samepaths(wadfiles[i]->path, fullpath) > 0)
|
||||
|
@ -3618,6 +3627,101 @@ static void Command_Addfolder(void)
|
|||
}
|
||||
}
|
||||
|
||||
/** Removes an added pwad at runtime.
|
||||
*/
|
||||
static void Command_Delfile(void)
|
||||
{
|
||||
const char *fn, *p;
|
||||
char buf[256];
|
||||
char *buf_p = buf;
|
||||
INT32 i;
|
||||
UINT16 found = UINT16_MAX;
|
||||
|
||||
if (netgame && !(server || IsPlayerAdmin(consoleplayer)))
|
||||
{
|
||||
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (numwadfiles <= mainwads)
|
||||
{
|
||||
CONS_Printf(M_GetText("No additional WADs are loaded.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (COM_Argc() != 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("delfile <wadfile.wad>: delete wad file\n"));
|
||||
return;
|
||||
}
|
||||
else
|
||||
fn = COM_Argv(1);
|
||||
|
||||
// Disallow non-printing characters and semicolons.
|
||||
for (i = 0; fn[i] != '\0'; i++)
|
||||
if (!isprint(fn[i]) || fn[i] == ';')
|
||||
return;
|
||||
|
||||
p = fn+strlen(fn);
|
||||
while(--p >= fn)
|
||||
if (*p == '\\' || *p == '/' || *p == ':')
|
||||
break;
|
||||
++p;
|
||||
|
||||
// Delete file on your client if it isn't important.
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (!W_IsFilePresent(i))
|
||||
continue;
|
||||
|
||||
char *wadname = va("%s", wadfiles[i]->filename);
|
||||
nameonly(wadname);
|
||||
if (!stricmp(wadname, p))
|
||||
{
|
||||
// found the file we want to delete
|
||||
found = i;
|
||||
|
||||
// WADs added at game setup (srb2.pk3, zones.pk3, etc.)
|
||||
if (i <= mainwads)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), p);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!wadfiles[i]->important)
|
||||
{
|
||||
P_DelWadFile(i);
|
||||
return;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found == UINT16_MAX)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("File %s is not added\n"), p);
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete file on your client if you aren't in a netgame.
|
||||
if (!(netgame || multiplayer))
|
||||
{
|
||||
P_DelWadFile(i);
|
||||
return;
|
||||
}
|
||||
|
||||
WRITESTRINGN(buf_p,p,240);
|
||||
SendNetXCmd(XD_DELFILE, buf, buf_p - buf);
|
||||
}
|
||||
|
||||
static void Command_Restartgame(void)
|
||||
{
|
||||
D_RestartGame();
|
||||
}
|
||||
|
||||
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char filename[241];
|
||||
|
@ -3823,6 +3927,48 @@ static void Got_Addfoldercmd(UINT8 **cp, INT32 playernum)
|
|||
G_SetGameModified(true);
|
||||
}
|
||||
|
||||
static void Got_Delfilecmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char filename[241];
|
||||
size_t i;
|
||||
boolean found = false;
|
||||
|
||||
READSTRINGN(*cp, filename, 240);
|
||||
|
||||
if (playernum != serverplayer)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal delfile command received from %s\n"), player_names[playernum]);
|
||||
if (server)
|
||||
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (!W_IsFilePresent(i))
|
||||
continue;
|
||||
|
||||
char *wadname = va("%s", wadfiles[i]->filename);
|
||||
if (!stricmp(wadname, filename))
|
||||
{
|
||||
// found the file we want to delete
|
||||
found = true;
|
||||
|
||||
// WADs added at game setup (srb2.pk3, zones.pk3, etc.)
|
||||
if (i <= mainwads)
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), filename);
|
||||
else
|
||||
{
|
||||
P_DelWadFile(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
CONS_Alert(CONS_ERROR, M_GetText("File %s is not added\n"), filename);
|
||||
}
|
||||
|
||||
static void Command_ListWADS_f(void)
|
||||
{
|
||||
INT32 i = numwadfiles;
|
||||
|
@ -3836,6 +3982,8 @@ static void Command_ListWADS_f(void)
|
|||
|
||||
for (i--; i >= 0; i--)
|
||||
{
|
||||
if (!W_IsFilePresent(i))
|
||||
continue;
|
||||
nameonly(tempname = va("%s", wadfiles[i]->filename));
|
||||
if (!i)
|
||||
CONS_Printf("\x82 IWAD\x80: %s\n", tempname);
|
||||
|
|
|
@ -141,12 +141,13 @@ typedef enum
|
|||
XD_RUNSOC, // 16
|
||||
XD_REQADDFILE, // 17
|
||||
XD_REQADDFOLDER,// 18
|
||||
XD_SETMOTD, // 19
|
||||
XD_SUICIDE, // 20
|
||||
XD_DEMOTED, // 21
|
||||
XD_LUACMD, // 22
|
||||
XD_LUAVAR, // 23
|
||||
XD_LUAFILE, // 24
|
||||
XD_DELFILE, // 19
|
||||
XD_SETMOTD, // 20
|
||||
XD_SUICIDE, // 21
|
||||
XD_DEMOTED, // 22
|
||||
XD_LUACMD, // 23
|
||||
XD_LUAVAR, // 24
|
||||
XD_LUAFILE, // 25
|
||||
MAXNETXCMD
|
||||
} netxcmd_t;
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ static UINT16 GetWadNumFromFileNeededId(UINT8 id)
|
|||
|
||||
for (wadnum = mainwads; wadnum < numwadfiles; wadnum++)
|
||||
{
|
||||
if (!wadfiles[wadnum]->important)
|
||||
if (!W_IsFilePresent(wadnum) || !wadfiles[wadnum]->important)
|
||||
continue;
|
||||
if (id == 0)
|
||||
return wadnum;
|
||||
|
@ -151,6 +151,9 @@ UINT8 *PutFileNeeded(UINT16 firstfile)
|
|||
|
||||
for (i = mainwads; i < numwadfiles; i++) //mainwads, otherwise we start on the first mainwad
|
||||
{
|
||||
if (!W_IsFilePresent(i))
|
||||
continue;
|
||||
|
||||
// If it has only music/sound lumps, don't put it in the list
|
||||
if (!wadfiles[i]->important)
|
||||
continue;
|
||||
|
@ -459,6 +462,12 @@ INT32 CL_CheckFiles(void)
|
|||
CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n");
|
||||
for (i = 0, j = mainwads; i < fileneedednum || j < numwadfiles;)
|
||||
{
|
||||
if (!W_IsFilePresent(j))
|
||||
{
|
||||
++j;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (j < numwadfiles && !wadfiles[j]->important)
|
||||
{
|
||||
// Unimportant on our side.
|
||||
|
@ -500,6 +509,8 @@ INT32 CL_CheckFiles(void)
|
|||
// Check in already loaded files
|
||||
for (j = mainwads; j < numwadfiles; j++)
|
||||
{
|
||||
if (!W_IsFilePresent(j))
|
||||
continue;
|
||||
nameonly(strcpy(wadfilename, wadfiles[j]->filename));
|
||||
if (!stricmp(wadfilename, fileneeded[i].filename) &&
|
||||
!memcmp(wadfiles[j]->md5sum, fileneeded[i].md5sum, 16))
|
||||
|
|
|
@ -162,32 +162,6 @@ void clear_conditionsets(void)
|
|||
M_ClearConditionSet(i+1);
|
||||
}
|
||||
|
||||
void clear_levels(void)
|
||||
{
|
||||
INT16 i;
|
||||
|
||||
// This is potentially dangerous but if we're resetting these headers,
|
||||
// we may as well try to save some memory, right?
|
||||
for (i = 0; i < NUMMAPS; ++i)
|
||||
{
|
||||
if (!mapheaderinfo[i] || i == (tutorialmap-1))
|
||||
continue;
|
||||
|
||||
// Custom map header info
|
||||
// (no need to set num to 0, we're freeing the entire header shortly)
|
||||
Z_Free(mapheaderinfo[i]->customopts);
|
||||
|
||||
P_DeleteFlickies(i);
|
||||
P_DeleteGrades(i);
|
||||
|
||||
Z_Free(mapheaderinfo[i]);
|
||||
mapheaderinfo[i] = NULL;
|
||||
}
|
||||
|
||||
// Realloc the one for the current gamemap as a safeguard
|
||||
P_AllocMapHeader(gamemap-1);
|
||||
}
|
||||
|
||||
static boolean findFreeSlot(INT32 *num)
|
||||
{
|
||||
// Send the character select entry to a free slot.
|
||||
|
|
|
@ -83,6 +83,5 @@ void readfreeslots(MYFILE *f);
|
|||
void readPlayer(MYFILE *f, INT32 num);
|
||||
void clear_emblems(void);
|
||||
void clear_unlockables(void);
|
||||
void clear_levels(void);
|
||||
void clear_conditionsets(void);
|
||||
#endif
|
||||
|
|
|
@ -25,14 +25,6 @@ extern char *FREE_MOBJS[NUMMOBJFREESLOTS];
|
|||
extern char *FREE_SKINCOLORS[NUMCOLORFREESLOTS];
|
||||
extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
|
||||
|
||||
#define initfreeslots() {\
|
||||
memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);\
|
||||
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\
|
||||
memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);\
|
||||
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\
|
||||
memset(actionsoverridden, LUA_REFNIL, sizeof(actionsoverridden));\
|
||||
}
|
||||
|
||||
struct flickytypes_s {
|
||||
const char *name;
|
||||
const mobjtype_t type;
|
||||
|
|
|
@ -178,7 +178,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
|
|||
INT32 i;
|
||||
|
||||
if (!deh_loaded)
|
||||
initfreeslots();
|
||||
DEH_Init();
|
||||
|
||||
deh_num_warning = 0;
|
||||
|
||||
|
@ -559,10 +559,10 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
|
|||
}
|
||||
|
||||
if (clearall || fastcmp(word2, "CONDITIONSETS"))
|
||||
clear_conditionsets();
|
||||
P_ClearConditionSets();
|
||||
|
||||
if (clearall || fastcmp(word2, "LEVELS"))
|
||||
clear_levels();
|
||||
P_ClearLevels();
|
||||
}
|
||||
else
|
||||
deh_warning("Unknown word: %s", word);
|
||||
|
@ -594,14 +594,12 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
|
|||
}
|
||||
|
||||
dbg_line = -1;
|
||||
|
||||
if (deh_num_warning)
|
||||
{
|
||||
CONS_Printf(M_GetText("%d warning%s in the SOC lump\n"), deh_num_warning, deh_num_warning == 1 ? "" : "s");
|
||||
if (devparm) {
|
||||
if (devparm)
|
||||
I_Error("%s%s",va(M_GetText("%d warning%s in the SOC lump\n"), deh_num_warning, deh_num_warning == 1 ? "" : "s"), M_GetText("See log.txt for details.\n"));
|
||||
//while (!I_GetKey())
|
||||
//I_OsPolling();
|
||||
}
|
||||
}
|
||||
|
||||
deh_loaded = true;
|
||||
|
@ -627,3 +625,14 @@ void DEH_LoadDehackedLump(lumpnum_t lumpnum)
|
|||
{
|
||||
DEH_LoadDehackedLumpPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum), false);
|
||||
}
|
||||
|
||||
void DEH_Init(void)
|
||||
{
|
||||
deh_loaded = false;
|
||||
|
||||
memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);
|
||||
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);
|
||||
memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);
|
||||
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));
|
||||
memset(actionsoverridden, LUA_REFNIL, sizeof(actionsoverridden));
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@ typedef enum
|
|||
void DEH_LoadDehackedLump(lumpnum_t lumpnum);
|
||||
void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump, boolean mainfile);
|
||||
|
||||
void DEH_Init(void);
|
||||
void DEH_Check(void);
|
||||
|
||||
fixed_t get_number(const char *word);
|
||||
FUNCPRINTF void deh_warning(const char *first, ...);
|
||||
void deh_strlcpy(char *dst, const char *src, size_t size, const char *warntext);
|
||||
|
|
|
@ -514,9 +514,13 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...) FUNCDEBUG;
|
|||
|
||||
// Things that used to be in dstrings.h
|
||||
#define SAVEGAMENAME "srb2sav"
|
||||
|
||||
extern char savegamename[256];
|
||||
extern char liveeventbackup[256];
|
||||
|
||||
extern char basesavegamename[256];
|
||||
extern char baseliveeventbackup[256];
|
||||
|
||||
// m_misc.h
|
||||
#ifdef GETTEXT
|
||||
#define M_GetText(String) gettext(String)
|
||||
|
|
|
@ -2354,7 +2354,7 @@ else if (strlen(name) <= 6) \
|
|||
else \
|
||||
arr[0] = 0;
|
||||
|
||||
static void F_CacheTitleScreen(void)
|
||||
void F_CacheTitleScreen(void)
|
||||
{
|
||||
switch(curttmode)
|
||||
{
|
||||
|
|
|
@ -41,6 +41,7 @@ void F_GameEndDrawer(void);
|
|||
void F_IntroDrawer(void);
|
||||
void F_TitleScreenDrawer(void);
|
||||
void F_SkyScroll(const char *patchname);
|
||||
void F_CacheTitleScreen(void);
|
||||
|
||||
void F_GameEvaluationDrawer(void);
|
||||
void F_StartGameEvaluation(void);
|
||||
|
@ -103,7 +104,6 @@ extern INT16 ttloop;
|
|||
extern UINT16 tttics;
|
||||
extern boolean ttavailable[6];
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TITLEMAP_OFF = 0,
|
||||
|
|
|
@ -1140,6 +1140,9 @@ boolean preparefilemenu(boolean samedepth)
|
|||
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (!W_IsFilePresent(i))
|
||||
continue;
|
||||
|
||||
if (!filenamebuf[i][0])
|
||||
{
|
||||
strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH);
|
||||
|
|
227
src/g_game.c
227
src/g_game.c
|
@ -45,12 +45,16 @@
|
|||
#include "v_video.h"
|
||||
#include "lua_hook.h"
|
||||
#include "b_bot.h"
|
||||
#include "deh_soc.h"
|
||||
#include "m_cond.h" // condition sets
|
||||
#include "lua_script.h"
|
||||
#include "r_fps.h" // frame interpolation/uncapped
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_hud.h"
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_glob.h"
|
||||
#endif
|
||||
|
||||
gameaction_t gameaction;
|
||||
gamestate_t gamestate = GS_NULL;
|
||||
UINT8 ultimatemode = false;
|
||||
|
@ -65,9 +69,13 @@ JoyType_t Joystick2;
|
|||
// 1024 bytes is plenty for a savegame
|
||||
#define SAVEGAMESIZE (1024)
|
||||
|
||||
char gamedatafilename[64] = "gamedata.dat";
|
||||
char timeattackfolder[64] = "main";
|
||||
char customversionstring[32] = "\0";
|
||||
#define DEFAULTGAMEDATAFILENAME "gamedata.dat"
|
||||
#define DEFAULTTIMEATTACKFOLDER "main"
|
||||
#define DEFAULTCUSTOMVERSIONSTR "\0"
|
||||
|
||||
char gamedatafilename[64] = DEFAULTGAMEDATAFILENAME;
|
||||
char timeattackfolder[64] = DEFAULTTIMEATTACKFOLDER;
|
||||
char customversionstring[32] = DEFAULTCUSTOMVERSIONSTR;
|
||||
|
||||
static void G_DoCompleted(void);
|
||||
static void G_DoStartContinue(void);
|
||||
|
@ -99,15 +107,15 @@ boolean savemoddata = false;
|
|||
boolean usedCheats = false; // Set when a gamedata-preventing cheat command is used.
|
||||
UINT8 paused;
|
||||
UINT8 modeattacking = ATTACKING_NONE;
|
||||
boolean disableSpeedAdjust = false;
|
||||
boolean disableSpeedAdjust;
|
||||
boolean imcontinuing = false;
|
||||
boolean runemeraldmanager = false;
|
||||
UINT16 emeraldspawndelay = 60*TICRATE;
|
||||
UINT16 emeraldspawndelay;
|
||||
|
||||
// menu demo things
|
||||
UINT8 numDemos = 0;
|
||||
UINT32 demoDelayTime = 15*TICRATE;
|
||||
UINT32 demoIdleTime = 3*TICRATE;
|
||||
UINT8 numDemos;
|
||||
UINT32 demoDelayTime;
|
||||
UINT32 demoIdleTime;
|
||||
|
||||
boolean netgame; // only true if packets are broadcast
|
||||
boolean multiplayer;
|
||||
|
@ -128,8 +136,8 @@ tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
|
|||
INT16 spstage_start, spmarathon_start;
|
||||
INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
|
||||
|
||||
INT16 titlemap = 0;
|
||||
boolean hidetitlepics = false;
|
||||
INT16 titlemap;
|
||||
boolean hidetitlepics;
|
||||
INT16 bootmap; //bootmap for loading a map on startup
|
||||
|
||||
INT16 tutorialmap = 0; // map to load for tutorial
|
||||
|
@ -140,12 +148,12 @@ INT32 tutorialfreelook = 0; // store cv_alwaysfreelook user value
|
|||
INT32 tutorialmousemove = 0; // store cv_mousemove user value
|
||||
INT32 tutorialanalog = 0; // store cv_analog[0] user value
|
||||
|
||||
boolean looptitle = false;
|
||||
boolean looptitle;
|
||||
|
||||
UINT16 skincolor_redteam = SKINCOLOR_RED;
|
||||
UINT16 skincolor_blueteam = SKINCOLOR_BLUE;
|
||||
UINT16 skincolor_redring = SKINCOLOR_SALMON;
|
||||
UINT16 skincolor_bluering = SKINCOLOR_CORNFLOWER;
|
||||
UINT16 skincolor_redteam;
|
||||
UINT16 skincolor_blueteam;
|
||||
UINT16 skincolor_redring;
|
||||
UINT16 skincolor_bluering;
|
||||
|
||||
tic_t countdowntimer = 0;
|
||||
boolean countdowntimeup = false;
|
||||
|
@ -199,23 +207,23 @@ boolean CheckForFloatBob;
|
|||
boolean CheckForReverseGravity;
|
||||
|
||||
// Powerup durations
|
||||
UINT16 invulntics = 20*TICRATE;
|
||||
UINT16 sneakertics = 20*TICRATE;
|
||||
UINT16 flashingtics = 3*TICRATE;
|
||||
UINT16 tailsflytics = 8*TICRATE;
|
||||
UINT16 underwatertics = 30*TICRATE;
|
||||
UINT16 spacetimetics = 11*TICRATE + (TICRATE/2);
|
||||
UINT16 extralifetics = 4*TICRATE;
|
||||
UINT16 nightslinktics = 2*TICRATE;
|
||||
UINT16 invulntics;
|
||||
UINT16 sneakertics;
|
||||
UINT16 flashingtics;
|
||||
UINT16 tailsflytics;
|
||||
UINT16 underwatertics;
|
||||
UINT16 spacetimetics;
|
||||
UINT16 extralifetics;
|
||||
UINT16 nightslinktics;
|
||||
|
||||
INT32 gameovertics = 11*TICRATE;
|
||||
INT32 gameovertics;
|
||||
|
||||
UINT8 ammoremovaltics = 2*TICRATE;
|
||||
UINT8 ammoremovaltics;
|
||||
|
||||
UINT8 use1upSound = 0;
|
||||
UINT8 maxXtraLife = 2; // Max extra lives from rings
|
||||
UINT8 useContinues = 0; // Set to 1 to enable continues outside of no-save scenarioes
|
||||
UINT8 shareEmblems = 0; // Set to 1 to share all picked up emblems in multiplayer
|
||||
UINT8 use1upSound;
|
||||
UINT8 maxXtraLife; // Max extra lives from rings
|
||||
UINT8 useContinues; // Set to 1 to enable continues outside of no-save scenarioes
|
||||
UINT8 shareEmblems; // Set to 1 to share all picked up emblems in multiplayer
|
||||
|
||||
UINT8 introtoplay;
|
||||
UINT8 creditscutscene;
|
||||
|
@ -4328,6 +4336,106 @@ void G_EndGame(void)
|
|||
D_StartTitle();
|
||||
}
|
||||
|
||||
// Set the game to its initial state.
|
||||
void G_InitialState(void)
|
||||
{
|
||||
// Delete all skins.
|
||||
R_DelSkins();
|
||||
|
||||
// Stop all sound effects.
|
||||
S_StopSounds();
|
||||
S_ClearSfx();
|
||||
|
||||
for (INT32 i = 0; i < NUMSFX; i++)
|
||||
{
|
||||
if (S_sfx[i].lumpnum != LUMPERROR)
|
||||
{
|
||||
S_RemoveSoundFx(i);
|
||||
I_FreeSfx(&S_sfx[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// delete Lua-added console commands and variables
|
||||
COM_RemoveLuaCommands();
|
||||
|
||||
// Clear the Lua state
|
||||
LUA_Shutdown();
|
||||
|
||||
// Clear unlockables and emblems
|
||||
clear_emblems();
|
||||
clear_unlockables();
|
||||
clear_conditionsets();
|
||||
|
||||
numemblems = 0;
|
||||
numextraemblems = 0;
|
||||
|
||||
// Clear condition sets and level headers
|
||||
P_ClearConditionSets();
|
||||
P_ClearLevels();
|
||||
|
||||
// reload default editable variables
|
||||
G_LoadGameSettings();
|
||||
G_SetDefaultSaveNames();
|
||||
G_SetDefaultDataStrings();
|
||||
|
||||
// clear game data stuff
|
||||
modifiedgame = false;
|
||||
savemoddata = false;
|
||||
usedCheats = false;
|
||||
|
||||
G_ClearRecords(clientGamedata);
|
||||
M_ClearSecrets(clientGamedata);
|
||||
|
||||
ST_RestoreHudInfo();
|
||||
|
||||
DEH_Init();
|
||||
|
||||
P_ResetData(0xFF);
|
||||
}
|
||||
|
||||
// Restarts or exits the level after file deletion.
|
||||
void G_AfterFileDeletion(void)
|
||||
{
|
||||
// Load the default game data.
|
||||
G_LoadGameData(clientGamedata);
|
||||
M_CopyGameData(serverGamedata, clientGamedata);
|
||||
|
||||
if (!Playing())
|
||||
{
|
||||
if (gamestate == GS_TITLESCREEN)
|
||||
F_CacheTitleScreen();
|
||||
return;
|
||||
}
|
||||
|
||||
// reset the map
|
||||
if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION)
|
||||
{
|
||||
ST_Start();
|
||||
// load MAP01 if the current map doesn't exist anymore
|
||||
if (W_CheckNumForName(G_BuildMapName(gamemap)) == LUMPERROR)
|
||||
gamemap = 1;
|
||||
// same deal for nextmap
|
||||
if (W_CheckNumForName(G_BuildMapName(nextmap+1)) == LUMPERROR)
|
||||
nextmap = 0;
|
||||
// ...and nextmapoverride
|
||||
if (W_CheckNumForName(G_BuildMapName(nextmapoverride)) == LUMPERROR)
|
||||
nextmapoverride = 1;
|
||||
if (gamestate == GS_INTERMISSION)
|
||||
{
|
||||
Y_EndIntermission();
|
||||
G_AfterIntermission();
|
||||
}
|
||||
else
|
||||
G_DoLoadLevel(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(netgame || splitscreen))
|
||||
F_StartIntro();
|
||||
else if (server)
|
||||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// G_LoadGameSettings
|
||||
//
|
||||
|
@ -4342,10 +4450,65 @@ void G_LoadGameSettings(void)
|
|||
smpstage_start = 60;
|
||||
smpstage_end = 66; // 7 multiplayer special stages too
|
||||
|
||||
emeraldspawndelay = 60*TICRATE;
|
||||
disableSpeedAdjust = false;
|
||||
|
||||
// menu demo things
|
||||
numDemos = 0;
|
||||
demoDelayTime = 15*TICRATE;
|
||||
demoIdleTime = 3*TICRATE;
|
||||
|
||||
// team modes skincolors
|
||||
skincolor_redteam = SKINCOLOR_RED;
|
||||
skincolor_blueteam = SKINCOLOR_BLUE;
|
||||
skincolor_redring = SKINCOLOR_SALMON;
|
||||
skincolor_bluering = SKINCOLOR_CORNFLOWER;
|
||||
|
||||
// Powerup durations
|
||||
invulntics = 20*TICRATE;
|
||||
sneakertics = 20*TICRATE;
|
||||
flashingtics = 3*TICRATE;
|
||||
tailsflytics = 8*TICRATE;
|
||||
underwatertics = 30*TICRATE;
|
||||
spacetimetics = 11*TICRATE + (TICRATE/2);
|
||||
extralifetics = 4*TICRATE;
|
||||
nightslinktics = 2*TICRATE;
|
||||
|
||||
gameovertics = 11*TICRATE;
|
||||
ammoremovaltics = 2*TICRATE;
|
||||
|
||||
startchar = 0;
|
||||
use1upSound = 0;
|
||||
maxXtraLife = 2; // Max extra lives from rings
|
||||
useContinues = 0;
|
||||
shareEmblems = 0;
|
||||
|
||||
titlemap = 0;
|
||||
titlescrollxspeed = 20;
|
||||
titlescrollyspeed = 0;
|
||||
ttmode = TTMODE_OLD;
|
||||
|
||||
hidetitlepics = false;
|
||||
looptitle = false;
|
||||
introtoplay = 0;
|
||||
|
||||
// initialize free sfx slots for skin sounds
|
||||
S_InitRuntimeSounds();
|
||||
}
|
||||
|
||||
void G_SetDefaultSaveNames(void)
|
||||
{
|
||||
strcpy(savegamename, basesavegamename);
|
||||
strcpy(liveeventbackup, baseliveeventbackup);
|
||||
}
|
||||
|
||||
void G_SetDefaultDataStrings(void)
|
||||
{
|
||||
strcpy(gamedatafilename, DEFAULTGAMEDATAFILENAME);
|
||||
strcpy(timeattackfolder, DEFAULTTIMEATTACKFOLDER);
|
||||
strcpy(customversionstring, DEFAULTCUSTOMVERSIONSTR);
|
||||
}
|
||||
|
||||
#define GAMEDATA_ID 0x86E4A27C // Change every major version, as usual
|
||||
#define COMPAT_GAMEDATA_ID 0xFCAFE211 // Can be removed entirely for 2.3
|
||||
|
||||
|
@ -4708,7 +4871,7 @@ void G_SaveGameData(gamedata_t *data)
|
|||
#define VERSIONSIZE 16
|
||||
|
||||
//
|
||||
// G_InitFromSavegame
|
||||
// G_LoadGame
|
||||
// Can be called by the startup code or the menu task.
|
||||
//
|
||||
void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
||||
|
|
|
@ -243,6 +243,12 @@ boolean G_GetModeAttackRetryFlag(void);
|
|||
void G_LoadGameData(gamedata_t *data);
|
||||
void G_LoadGameSettings(void);
|
||||
|
||||
void G_SetDefaultSaveNames(void);
|
||||
void G_SetDefaultDataStrings(void);
|
||||
|
||||
void G_InitialState(void);
|
||||
void G_AfterFileDeletion(void);
|
||||
|
||||
void G_SetGameModified(boolean silent);
|
||||
void G_SetUsedCheats(boolean silent);
|
||||
|
||||
|
|
|
@ -7008,11 +7008,11 @@ customshaderxlat_t shaderxlat[] =
|
|||
|
||||
void HWR_LoadAllCustomShaders(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
// read every custom shader
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i]));
|
||||
for (INT32 i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (W_IsFilePresent(i))
|
||||
HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
|
||||
|
|
|
@ -450,7 +450,8 @@ static int lib_cvRegisterVar(lua_State *L)
|
|||
return luaL_error(L, M_GetText("Variable %s has CV_CALL without a function"), cvar->name);
|
||||
}
|
||||
|
||||
cvar->flags |= CV_ALLOWLUA;
|
||||
cvar->flags |= CV_ALLOWLUA | CV_LUAVAR;
|
||||
|
||||
// actually time to register it to the console now! Finally!
|
||||
cvar->flags |= CV_MODIFIED;
|
||||
CV_RegisterVar(cvar);
|
||||
|
|
|
@ -149,3 +149,5 @@ int LUA_HookPlayerCmd(player_t *, ticcmd_t *);
|
|||
int LUA_HookMusicChange(const char *oldname, struct MusicChange *);
|
||||
fixed_t LUA_HookPlayerHeight(player_t *player);
|
||||
int LUA_HookPlayerCanEnterSpinGaps(player_t *player);
|
||||
|
||||
void LUA_ClearHooks(void);
|
||||
|
|
|
@ -152,6 +152,7 @@ static void add_string_hook(lua_State *L, int type)
|
|||
lua_pushstring(L, string);
|
||||
get_table(L);
|
||||
add_hook_to_table(L, 1 + lua_objlen(L, -1));
|
||||
Z_Free(string);
|
||||
}
|
||||
else
|
||||
add_hook_to_table(L, ++hook->numGeneric);
|
||||
|
@ -260,6 +261,49 @@ int lib_hudadd(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void free_hook(hook_t *hook)
|
||||
{
|
||||
Z_Free(hook->ids);
|
||||
hook->ids = NULL;
|
||||
hook->numHooks = 0;
|
||||
}
|
||||
|
||||
static void free_all_hooks(void)
|
||||
{
|
||||
// Free hookIds
|
||||
for (size_t i = 0; i < HOOK(MAX); i++)
|
||||
free_hook(&hookIds[i]);
|
||||
|
||||
// Free hudHookIds
|
||||
for (size_t i = 0; i < HUD_HOOK(MAX); i++)
|
||||
free_hook(&hudHookIds[i]);
|
||||
|
||||
// Free mobjHookIds
|
||||
for (size_t i = 0; i < NUMMOBJTYPES; i++)
|
||||
{
|
||||
for (size_t j = 0; j < MOBJ_HOOK(MAX); j++)
|
||||
free_hook(&mobjHookIds[i][j]);
|
||||
}
|
||||
|
||||
// Free stringHooks
|
||||
for (size_t i = 0; i < STRING_HOOK(MAX); i++)
|
||||
{
|
||||
stringHooks[i].numGeneric = 0;
|
||||
stringHooks[i].ref = 0;
|
||||
}
|
||||
|
||||
Z_Free(hookRefs);
|
||||
Z_Free(hooksErrored);
|
||||
|
||||
hookRefs = NULL;
|
||||
hooksErrored = NULL;
|
||||
}
|
||||
|
||||
void LUA_ClearHooks(void)
|
||||
{
|
||||
free_all_hooks();
|
||||
}
|
||||
|
||||
typedef struct Hook_State Hook_State;
|
||||
typedef void (*Hook_Callback)(Hook_State *);
|
||||
|
||||
|
|
|
@ -526,18 +526,27 @@ static int setglobals(lua_State *L)
|
|||
return luaL_error(L, "Implicit global " LUA_QS " prevented. Create a local variable instead.", csname);
|
||||
}
|
||||
|
||||
// Clear the Lua state
|
||||
void LUA_Shutdown(void)
|
||||
{
|
||||
if (gL)
|
||||
{
|
||||
LUA_ClearHooks();
|
||||
lua_close(gL);
|
||||
}
|
||||
|
||||
gL = NULL;
|
||||
}
|
||||
|
||||
// Clear and create a new Lua state, laddo!
|
||||
// There's SCRIPTIN to be had!
|
||||
static void LUA_ClearState(void)
|
||||
void LUA_ClearState(void)
|
||||
{
|
||||
lua_State *L;
|
||||
int i;
|
||||
|
||||
// close previous state
|
||||
if (gL)
|
||||
lua_close(gL);
|
||||
gL = NULL;
|
||||
|
||||
LUA_Shutdown();
|
||||
CONS_Printf(M_GetText("Pardon me while I initialize the Lua scripting interface...\n"));
|
||||
|
||||
// allocate state
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
#define luaL_checkangle(L, i) ((angle_t)luaL_checkinteger(L, i))
|
||||
#define lua_pushangle(L, a) lua_pushinteger(L, a)
|
||||
|
||||
void LUA_ClearState(void);
|
||||
void LUA_Shutdown(void);
|
||||
|
||||
#ifdef _DEBUG
|
||||
void LUA_ClearExtVars(void);
|
||||
#endif
|
||||
|
|
|
@ -41,8 +41,8 @@ extraemblem_t extraemblems[MAXEXTRAEMBLEMS];
|
|||
unlockable_t unlockables[MAXUNLOCKABLES];
|
||||
|
||||
// Number of emblems and extra emblems
|
||||
INT32 numemblems = 0;
|
||||
INT32 numextraemblems = 0;
|
||||
INT32 numemblems;
|
||||
INT32 numextraemblems;
|
||||
|
||||
// Temporary holding place for nights data for the current map
|
||||
nightsdata_t ntemprecords[MAXPLAYERS];
|
||||
|
|
121
src/p_setup.c
121
src/p_setup.c
|
@ -339,7 +339,7 @@ void P_DeleteFlickies(INT16 i)
|
|||
* \param i Map number to clear header for.
|
||||
* \sa P_ClearMapHeaderInfo
|
||||
*/
|
||||
static void P_ClearSingleMapHeaderInfo(INT16 i)
|
||||
void P_ClearSingleMapHeaderInfo(INT16 i)
|
||||
{
|
||||
const INT16 num = (INT16)(i-1);
|
||||
mapheaderinfo[num]->lvlttl[0] = '\0';
|
||||
|
@ -413,6 +413,43 @@ void P_AllocMapHeader(INT16 i)
|
|||
P_ClearSingleMapHeaderInfo(i + 1);
|
||||
}
|
||||
|
||||
/** Clears condition sets.
|
||||
*/
|
||||
void P_ClearConditionSets(void)
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < MAXCONDITIONSETS; ++i)
|
||||
M_ClearConditionSet(i+1);
|
||||
}
|
||||
|
||||
/** Clears levels headers.
|
||||
*/
|
||||
void P_ClearLevels(void)
|
||||
{
|
||||
INT16 i;
|
||||
|
||||
// This is potentially dangerous but if we're resetting these headers,
|
||||
// we may as well try to save some memory, right?
|
||||
for (i = 0; i < NUMMAPS; ++i)
|
||||
{
|
||||
if (!mapheaderinfo[i] || i == (tutorialmap-1))
|
||||
continue;
|
||||
|
||||
// Custom map header info
|
||||
// (no need to set num to 0, we're freeing the entire header shortly)
|
||||
Z_Free(mapheaderinfo[i]->customopts);
|
||||
|
||||
P_DeleteFlickies(i);
|
||||
P_DeleteGrades(i);
|
||||
|
||||
Z_Free(mapheaderinfo[i]);
|
||||
mapheaderinfo[i] = NULL;
|
||||
}
|
||||
|
||||
// Realloc the one for the current gamemap as a safeguard
|
||||
P_AllocMapHeader(gamemap-1);
|
||||
}
|
||||
|
||||
/** NiGHTS Grades are a special structure,
|
||||
* we initialize them here.
|
||||
*
|
||||
|
@ -7618,6 +7655,55 @@ static void P_InitGametype(void)
|
|||
: mapheaderinfo[gamemap - 1]->numlaps);
|
||||
}
|
||||
|
||||
void P_UnloadLevel(void)
|
||||
{
|
||||
LUA_InvalidateLevel();
|
||||
|
||||
if (sectors)
|
||||
{
|
||||
for (sector_t *ss = sectors; sectors+numsectors != ss; ss++)
|
||||
{
|
||||
Z_Free(ss->attached);
|
||||
Z_Free(ss->attachedsolid);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear pointers that would be left dangling by the purge
|
||||
R_FlushTranslationColormapCache();
|
||||
|
||||
#ifdef HWRENDER
|
||||
// Free GPU textures before freeing patches.
|
||||
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
|
||||
HWR_ClearAllTextures();
|
||||
#endif
|
||||
|
||||
R_InitializeLevelInterpolators();
|
||||
|
||||
P_InitThinkers();
|
||||
R_InitMobjInterpolators();
|
||||
P_InitCachedActions();
|
||||
|
||||
segs = NULL;
|
||||
sectors = NULL;
|
||||
subsectors = NULL;
|
||||
nodes = NULL;
|
||||
lines = NULL;
|
||||
sides = NULL;
|
||||
mapthings = NULL;
|
||||
spawnsectors = NULL;
|
||||
spawnlines = NULL;
|
||||
spawnsides = NULL;
|
||||
|
||||
numvertexes = 0;
|
||||
numsegs = 0;
|
||||
numsectors = 0;
|
||||
numsubsectors = 0;
|
||||
numnodes = 0;
|
||||
numlines = 0;
|
||||
numsides = 0;
|
||||
nummapthings = 0;
|
||||
}
|
||||
|
||||
/** Loads a level from a lump or external wad.
|
||||
*
|
||||
* \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot.
|
||||
|
@ -7629,7 +7715,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
// 99% of the things already did, so.
|
||||
// Map header should always be in place at this point
|
||||
INT32 i, ranspecialwipe = 0;
|
||||
sector_t *ss;
|
||||
|
||||
levelloading = true;
|
||||
|
||||
// This is needed. Don't touch.
|
||||
|
@ -7768,33 +7854,12 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
// Close text prompt before freeing the old level
|
||||
F_EndTextPrompt(false, true);
|
||||
|
||||
LUA_InvalidateLevel();
|
||||
|
||||
for (ss = sectors; sectors+numsectors != ss; ss++)
|
||||
{
|
||||
Z_Free(ss->attached);
|
||||
Z_Free(ss->attachedsolid);
|
||||
}
|
||||
|
||||
// Clear pointers that would be left dangling by the purge
|
||||
R_FlushTranslationColormapCache();
|
||||
|
||||
#ifdef HWRENDER
|
||||
// Free GPU textures before freeing patches.
|
||||
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
|
||||
HWR_ClearAllTextures();
|
||||
#endif
|
||||
P_UnloadLevel();
|
||||
|
||||
Patch_FreeTag(PU_PATCH_LOWPRIORITY);
|
||||
Patch_FreeTag(PU_PATCH_ROTATED);
|
||||
Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1);
|
||||
|
||||
R_InitializeLevelInterpolators();
|
||||
|
||||
P_InitThinkers();
|
||||
R_InitMobjInterpolators();
|
||||
P_InitCachedActions();
|
||||
|
||||
if (!fromnetsave && savedata.lives > 0)
|
||||
{
|
||||
numgameovers = savedata.numgameovers;
|
||||
|
@ -8255,3 +8320,11 @@ boolean P_AddFolder(const char *folderpath)
|
|||
return D_CheckPathAllowed(folderpath, "tried to add folder") &&
|
||||
P_LoadAddon(W_InitFolder(folderpath, false, false));
|
||||
}
|
||||
|
||||
boolean P_DelWadFile(const UINT16 wadnum)
|
||||
{
|
||||
if (wadnum == 0) // can't delete the IWAD
|
||||
return false;
|
||||
W_UnloadWadFile(wadnum);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -99,17 +99,24 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
|
|||
#endif
|
||||
void P_RespawnThings(void);
|
||||
boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate);
|
||||
void P_UnloadLevel(void);
|
||||
#ifdef HWRENDER
|
||||
void HWR_LoadLevel(void);
|
||||
#endif
|
||||
boolean P_AddWadFile(const char *wadfilename);
|
||||
boolean P_AddFolder(const char *folderpath);
|
||||
boolean P_DelWadFile(const UINT16 wadnum);
|
||||
boolean P_RunSOC(const char *socfilename);
|
||||
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
||||
void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
||||
//void P_WriteThings(void);
|
||||
size_t P_PrecacheLevelFlats(void);
|
||||
|
||||
void P_AllocMapHeader(INT16 i);
|
||||
void P_ClearSingleMapHeaderInfo(INT16 i);
|
||||
|
||||
void P_ClearConditionSets(void);
|
||||
void P_ClearLevels(void);
|
||||
|
||||
void P_SetDemoFlickies(INT16 i);
|
||||
void P_DeleteFlickies(INT16 i);
|
||||
|
|
|
@ -169,6 +169,9 @@ void P_InitPicAnims(void)
|
|||
{
|
||||
UINT16 animdefsLumpNum;
|
||||
|
||||
if (!W_IsFilePresent(w))
|
||||
continue;
|
||||
|
||||
// Find ANIMDEFS lump in the WAD
|
||||
animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0);
|
||||
|
||||
|
|
|
@ -232,6 +232,9 @@ static void R_InitExtraColormaps(void)
|
|||
|
||||
for (cfile = clump = 0; cfile < numwadfiles; cfile++, clump = 0)
|
||||
{
|
||||
if (!W_IsFilePresent(cfile))
|
||||
continue;
|
||||
|
||||
startnum = W_CheckNumForNamePwad("C_START", cfile, clump);
|
||||
if (startnum == INT16_MAX)
|
||||
continue;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_misc.h"
|
||||
#include "m_menu.h"
|
||||
#include "info.h" // spr2names
|
||||
#include "i_video.h" // rendermode
|
||||
#include "i_system.h"
|
||||
|
@ -944,6 +945,46 @@ next_token:
|
|||
#undef HUDNAMEWRITE
|
||||
#undef SYMBOLCONVERT
|
||||
|
||||
void R_DelSkins(void)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; i < MAXSKINS; i++)
|
||||
{
|
||||
if (!skins[i].name[0])
|
||||
{
|
||||
numskins--;
|
||||
continue;
|
||||
}
|
||||
|
||||
ST_UnLoadFaceGraphics(i);
|
||||
|
||||
for (j = 0; j < 32; j++)
|
||||
{
|
||||
if (!stricmp(skins[i].name, description[j].skinname))
|
||||
{
|
||||
memset(description[j].skinname, 0, SKINNAMESIZE*2+2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
{
|
||||
if (playeringame[j])
|
||||
{
|
||||
player_t *player = &players[j];
|
||||
skin_t *skin = player->mo->skin;
|
||||
if (!stricmp(skins[i].name, skin->name))
|
||||
SetPlayerSkinByNum(j, 0);
|
||||
}
|
||||
}
|
||||
|
||||
numskins--;
|
||||
}
|
||||
|
||||
M_InitCharacterTables();
|
||||
}
|
||||
|
||||
static UINT16 W_CheckForEitherSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
|
||||
{
|
||||
UINT16 i;
|
||||
|
@ -1083,7 +1124,8 @@ void R_RefreshSprite2(void)
|
|||
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
R_RefreshSprite2ForWad(i, old_spr2);
|
||||
if (W_IsFilePresent(i))
|
||||
R_RefreshSprite2ForWad(i, old_spr2);
|
||||
}
|
||||
|
||||
// Update previous value.
|
||||
|
|
|
@ -97,6 +97,7 @@ UINT32 R_GetSkinAvailabilities(void);
|
|||
INT32 R_SkinAvailable(const char *name);
|
||||
void R_AddSkins(UINT16 wadnum, boolean mainfile);
|
||||
void R_PatchSkins(UINT16 wadnum, boolean mainfile);
|
||||
void R_DelSkins(void);
|
||||
|
||||
UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player);
|
||||
|
||||
|
|
|
@ -1071,7 +1071,8 @@ void R_LoadTextures(void)
|
|||
|
||||
for (w = 0; w < numwadfiles; w++)
|
||||
{
|
||||
newtextures += R_CountTextures((UINT16)w);
|
||||
if (W_IsFilePresent(w))
|
||||
newtextures += R_CountTextures((UINT16)w);
|
||||
}
|
||||
|
||||
// If no textures found by this point, bomb out
|
||||
|
@ -1082,7 +1083,8 @@ void R_LoadTextures(void)
|
|||
|
||||
for (i = 0, w = 0; w < numwadfiles; w++)
|
||||
{
|
||||
i = R_DefineTextures(i, w);
|
||||
if (W_IsFilePresent(w))
|
||||
i = R_DefineTextures(i, w);
|
||||
}
|
||||
|
||||
R_FinishLoadingTextures(newtextures);
|
||||
|
@ -1574,6 +1576,8 @@ lumpnum_t R_GetFlatNumForName(const char *name)
|
|||
// Scan wad files backwards so patched flats take preference.
|
||||
for (i = numwadfiles - 1; i >= 0; i--)
|
||||
{
|
||||
if (!W_IsFilePresent(i))
|
||||
continue;
|
||||
switch (wadfiles[i]->type)
|
||||
{
|
||||
case RET_WAD:
|
||||
|
|
|
@ -566,7 +566,10 @@ void R_InitSprites(void)
|
|||
|
||||
// find sprites in each -file added pwad
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
R_AddSpriteDefs((UINT16)i);
|
||||
{
|
||||
if (W_IsFilePresent(i))
|
||||
R_AddSpriteDefs((UINT16)i);
|
||||
}
|
||||
|
||||
//
|
||||
// now check for skins
|
||||
|
@ -576,20 +579,13 @@ void R_InitSprites(void)
|
|||
R_InitSkins();
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (!W_IsFilePresent(i))
|
||||
continue;
|
||||
R_AddSkins((UINT16)i, true);
|
||||
R_PatchSkins((UINT16)i, true);
|
||||
R_LoadSpriteInfoLumps(i, wadfiles[i]->numlumps);
|
||||
}
|
||||
ST_ReloadSkinFaceGraphics();
|
||||
|
||||
//
|
||||
// check if all sprites have frames
|
||||
//
|
||||
/*
|
||||
for (i = 0; i < numsprites; i++)
|
||||
if (sprites[i].numframes < 1)
|
||||
CONS_Debug(DBG_SETUP, "R_InitSprites: sprite %s has no frames at all\n", sprnames[i]);
|
||||
*/
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -1676,9 +1676,11 @@ void S_LoadMusicDefs(UINT16 wadnum)
|
|||
//
|
||||
void S_InitMusicDefs(void)
|
||||
{
|
||||
UINT16 i;
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
S_LoadMusicDefs(i);
|
||||
for (UINT16 i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (W_IsFilePresent(i))
|
||||
S_LoadMusicDefs(i);
|
||||
}
|
||||
}
|
||||
|
||||
musicdef_t **soundtestdefs = NULL;
|
||||
|
|
|
@ -167,6 +167,8 @@ hudinfo_t hudinfo[NUMHUDITEMS] =
|
|||
{ 288, 176, V_SNAPTORIGHT|V_SNAPTOBOTTOM}, // HUD_POWERUPS
|
||||
};
|
||||
|
||||
static hudinfo_t basehudinfo[NUMHUDITEMS];
|
||||
|
||||
static huddrawlist_h luahuddrawlist_game[2];
|
||||
static huddrawlist_h luahuddrawlist_titlecard;
|
||||
|
||||
|
@ -395,6 +397,12 @@ void ST_ReloadSkinFaceGraphics(void)
|
|||
ST_LoadFaceGraphics(i);
|
||||
}
|
||||
|
||||
void ST_UnLoadFaceGraphics(INT32 skinnum)
|
||||
{
|
||||
W_UnlockCachedPatch(faceprefix[skinnum]);
|
||||
W_UnlockCachedPatch(superprefix[skinnum]);
|
||||
}
|
||||
|
||||
static inline void ST_InitData(void)
|
||||
{
|
||||
// 'link' the statusbar display to a player, which could be
|
||||
|
@ -446,6 +454,13 @@ void ST_Init(void)
|
|||
luahuddrawlist_game[0] = LUA_HUD_CreateDrawList();
|
||||
luahuddrawlist_game[1] = LUA_HUD_CreateDrawList();
|
||||
luahuddrawlist_titlecard = LUA_HUD_CreateDrawList();
|
||||
|
||||
memcpy(basehudinfo, hudinfo, sizeof(hudinfo));
|
||||
}
|
||||
|
||||
void ST_RestoreHudInfo(void)
|
||||
{
|
||||
memcpy(hudinfo, basehudinfo, sizeof(hudinfo));
|
||||
}
|
||||
|
||||
// change the status bar too, when pressing F12 while viewing a demo.
|
||||
|
|
|
@ -35,6 +35,8 @@ void ST_Start(void);
|
|||
// Called by startup code.
|
||||
void ST_Init(void);
|
||||
|
||||
void ST_RestoreHudInfo(void);
|
||||
|
||||
// Called by G_Responder() when pressing F12 while viewing a demo.
|
||||
void ST_changeDemoView(void);
|
||||
|
||||
|
@ -44,6 +46,7 @@ void ST_LoadGraphics(void);
|
|||
// face load graphics, called when skin changes
|
||||
void ST_LoadFaceGraphics(INT32 playernum);
|
||||
void ST_ReloadSkinFaceGraphics(void);
|
||||
void ST_UnLoadFaceGraphics(INT32 skinnum);
|
||||
|
||||
void ST_doPaletteStuff(void);
|
||||
|
||||
|
|
215
src/w_wad.c
215
src/w_wad.c
|
@ -54,6 +54,8 @@
|
|||
#include "d_netfil.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "dehacked.h"
|
||||
#include "d_main.h"
|
||||
#include "g_game.h"
|
||||
#include "r_defs.h"
|
||||
#include "r_data.h"
|
||||
#include "r_textures.h"
|
||||
|
@ -108,35 +110,51 @@ static UINT16 lumpnumcacheindex = 0;
|
|||
UINT16 numwadfiles; // number of active wadfiles
|
||||
wadfile_t **wadfiles; // 0 to numwadfiles-1 are valid
|
||||
|
||||
// W_Shutdown
|
||||
// Invalidates the cache of lump numbers. Call this whenever a wad is added or removed.
|
||||
static void W_InvalidateLumpnumCache(void)
|
||||
{
|
||||
memset(lumpnumcache, 0, sizeof (lumpnumcache));
|
||||
}
|
||||
|
||||
// Closes all of the WAD files before quitting
|
||||
// If not done on a Mac then open wad files
|
||||
// can prevent removable media they are on from
|
||||
// being ejected
|
||||
void W_Shutdown(void)
|
||||
{
|
||||
while (numwadfiles--)
|
||||
W_UnloadFile(wadfiles[numwadfiles]);
|
||||
}
|
||||
|
||||
void W_UnloadFile(wadfile_t *wad)
|
||||
{
|
||||
if (wad->handle)
|
||||
fclose(wad->handle);
|
||||
if (wad->path)
|
||||
Z_Free(wad->path);
|
||||
|
||||
Z_Free(wad->filename);
|
||||
|
||||
lumpinfo_t *lumpinfo = wad->lumpinfo;
|
||||
lumpcache_t *lumpcache = wad->lumpcache;
|
||||
lumpcache_t *patchcache = wad->patchcache;
|
||||
|
||||
while (wad->numlumps--)
|
||||
{
|
||||
wadfile_t *wad = wadfiles[numwadfiles];
|
||||
|
||||
if (wad->handle)
|
||||
fclose(wad->handle);
|
||||
Z_Free(wad->filename);
|
||||
if (wad->path)
|
||||
Z_Free(wad->path);
|
||||
while (wad->numlumps--)
|
||||
{
|
||||
if (wad->lumpinfo[wad->numlumps].diskpath)
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].diskpath);
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].longname);
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].fullname);
|
||||
}
|
||||
|
||||
Z_Free(wad->lumpinfo);
|
||||
Z_Free(wad);
|
||||
if (lumpcache[wad->numlumps])
|
||||
Z_Free(lumpcache[wad->numlumps]);
|
||||
if (patchcache[wad->numlumps])
|
||||
Z_Free(patchcache[wad->numlumps]);
|
||||
if (lumpinfo[wad->numlumps].diskpath)
|
||||
Z_Free(lumpinfo[wad->numlumps].diskpath);
|
||||
Z_Free(lumpinfo[wad->numlumps].longname);
|
||||
Z_Free(lumpinfo[wad->numlumps].fullname);
|
||||
}
|
||||
|
||||
Z_Free(wadfiles);
|
||||
Z_Free(lumpcache);
|
||||
Z_Free(patchcache);
|
||||
Z_Free(lumpinfo);
|
||||
|
||||
Z_Free(wad);
|
||||
|
||||
W_InvalidateLumpnumCache();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -331,12 +349,6 @@ static INT32 W_MakeFileMD5(const char *filename, void *resblock)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Invalidates the cache of lump numbers. Call this whenever a wad is added.
|
||||
static void W_InvalidateLumpnumCache(void)
|
||||
{
|
||||
memset(lumpnumcache, 0, sizeof (lumpnumcache));
|
||||
}
|
||||
|
||||
/** Detect a file type.
|
||||
* \todo Actually detect the wad/pkzip headers and whatnot, instead of just checking the extensions.
|
||||
*/
|
||||
|
@ -829,6 +841,24 @@ static void W_ReadFileShaders(wadfile_t *wadfile)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void W_AddFileToList(wadfile_t *wadfile)
|
||||
{
|
||||
UINT16 i = 0;
|
||||
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (!W_IsFilePresent(i))
|
||||
{
|
||||
wadfiles[i] = wadfile;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wadfiles = Z_Realloc(wadfiles, sizeof(wadfile_t *) * (numwadfiles + 1), PU_STATIC, NULL);
|
||||
wadfiles[numwadfiles] = wadfile;
|
||||
numwadfiles++;
|
||||
}
|
||||
|
||||
// Allocate a wadfile, setup the lumpinfo (directory) and
|
||||
// lumpcache, add the wadfile to the current active wadfiles
|
||||
//
|
||||
|
@ -847,9 +877,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
wadfile_t *wadfile;
|
||||
restype_t type;
|
||||
UINT16 numlumps = 0;
|
||||
#ifndef NOMD5
|
||||
size_t i;
|
||||
#endif
|
||||
UINT8 md5sum[16];
|
||||
int important;
|
||||
|
||||
|
@ -900,9 +928,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (wadfiles[i]->type == RET_FOLDER)
|
||||
if (!W_IsFilePresent(i) || wadfiles[i]->type == RET_FOLDER)
|
||||
continue;
|
||||
|
||||
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename);
|
||||
|
@ -911,6 +938,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
return W_InitFileError(filename, false);
|
||||
}
|
||||
}
|
||||
#else
|
||||
memset(wadfile->md5sum, 0x00, 16);
|
||||
#endif
|
||||
|
||||
switch(type = ResourceFileDetect(filename))
|
||||
|
@ -971,35 +1000,17 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
//
|
||||
// add the wadfile
|
||||
//
|
||||
W_AddFileToList(wadfile);
|
||||
|
||||
CONS_Printf(M_GetText("Added file %s (%u lumps)\n"), filename, numlumps);
|
||||
wadfiles = Z_Realloc(wadfiles, sizeof(wadfile_t *) * (numwadfiles + 1), PU_STATIC, NULL);
|
||||
wadfiles[numwadfiles] = wadfile;
|
||||
numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded
|
||||
|
||||
// Read shaders from file
|
||||
W_ReadFileShaders(wadfile);
|
||||
|
||||
// TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now.
|
||||
switch (wadfile->type)
|
||||
{
|
||||
case RET_WAD:
|
||||
W_LoadDehackedLumps(numwadfiles - 1, mainfile);
|
||||
break;
|
||||
case RET_PK3:
|
||||
W_LoadDehackedLumpsPK3(numwadfiles - 1, mainfile);
|
||||
break;
|
||||
case RET_SOC:
|
||||
CONS_Printf(M_GetText("Loading SOC from %s\n"), wadfile->filename);
|
||||
DEH_LoadDehackedLumpPwad(numwadfiles - 1, 0, mainfile);
|
||||
break;
|
||||
case RET_LUA:
|
||||
LUA_LoadLump(numwadfiles - 1, 0, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
W_LoadFileScripts(numwadfiles - 1, mainfile);
|
||||
W_InvalidateLumpnumCache();
|
||||
|
||||
return wadfile->numlumps;
|
||||
}
|
||||
|
||||
|
@ -1100,7 +1111,7 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
|
|||
// Check if the folder is already added.
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (wadfiles[i]->type != RET_FOLDER)
|
||||
if (!W_IsFilePresent(i) || wadfiles[i]->type != RET_FOLDER)
|
||||
continue;
|
||||
|
||||
if (samepaths(wadfiles[i]->path, fullpath) > 0)
|
||||
|
@ -1149,9 +1160,9 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
|
|||
Z_Calloc(numlumps * sizeof (*wadfile->lumpcache), PU_STATIC, &wadfile->lumpcache);
|
||||
Z_Calloc(numlumps * sizeof (*wadfile->patchcache), PU_STATIC, &wadfile->patchcache);
|
||||
|
||||
W_AddFileToList(wadfile);
|
||||
|
||||
CONS_Printf(M_GetText("Added folder %s (%u files, %u folders)\n"), fn, numlumps, foldercount);
|
||||
wadfiles[numwadfiles] = wadfile;
|
||||
numwadfiles++;
|
||||
|
||||
W_ReadFileShaders(wadfile);
|
||||
W_LoadDehackedLumpsPK3(numwadfiles - 1, mainfile);
|
||||
|
@ -1160,6 +1171,11 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
|
|||
return wadfile->numlumps;
|
||||
}
|
||||
|
||||
boolean W_IsFilePresent(UINT16 wadnum)
|
||||
{
|
||||
return wadfiles[wadnum] != NULL;
|
||||
}
|
||||
|
||||
/** Tries to load a series of files.
|
||||
* All files are wads unless they have an extension of ".soc" or ".lua".
|
||||
*
|
||||
|
@ -1188,6 +1204,58 @@ void W_InitMultipleFiles(addfilelist_t *list)
|
|||
}
|
||||
}
|
||||
|
||||
/** Loads all Lua and SOC scripts from a file.
|
||||
*
|
||||
* \sa W_InitFile
|
||||
* \sa D_ReloadFiles
|
||||
*/
|
||||
void W_LoadFileScripts(UINT16 wadfilenum, boolean mainfile)
|
||||
{
|
||||
wadfile_t *wadfile = wadfiles[wadfilenum];
|
||||
switch (wadfile->type)
|
||||
{
|
||||
case RET_WAD:
|
||||
W_LoadDehackedLumps(wadfilenum, mainfile);
|
||||
break;
|
||||
case RET_PK3:
|
||||
W_LoadDehackedLumpsPK3(wadfilenum, mainfile);
|
||||
break;
|
||||
case RET_SOC:
|
||||
CONS_Printf(M_GetText("Loading SOC from %s\n"), wadfile->filename);
|
||||
DEH_LoadDehackedLumpPwad(wadfilenum, 0, mainfile);
|
||||
break;
|
||||
case RET_LUA:
|
||||
LUA_LoadLump(wadfilenum, 0, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Unloads a file.
|
||||
*/
|
||||
void W_UnloadWadFile(UINT16 num)
|
||||
{
|
||||
char wadname[MAX_WADPATH];
|
||||
|
||||
if (num == numwadfiles-1)
|
||||
numwadfiles--;
|
||||
|
||||
nameonly(strcpy(wadname, wadfiles[num]->filename));
|
||||
CONS_Printf(M_GetText("Removing file %s...\n"), wadname);
|
||||
|
||||
// Save the current configuration file, and the gamedata.
|
||||
D_SaveUserPrefs();
|
||||
|
||||
// Delete the file
|
||||
W_UnloadFile(wadfiles[num]);
|
||||
wadfiles[num] = NULL;
|
||||
|
||||
// Set the initial state and reload files.
|
||||
D_ReloadFiles();
|
||||
G_AfterFileDeletion();
|
||||
}
|
||||
|
||||
/** Make sure a lump number is valid.
|
||||
* Compiles away to nothing if PARANOIA is not defined.
|
||||
*/
|
||||
|
@ -1207,6 +1275,9 @@ static boolean TestValidLump(UINT16 wad, UINT16 lump)
|
|||
|
||||
const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump)
|
||||
{
|
||||
if (!W_IsFilePresent(wad))
|
||||
return NULL;
|
||||
|
||||
if (lump >= wadfiles[wad]->numlumps || !TestValidLump(wad, 0))
|
||||
return NULL;
|
||||
|
||||
|
@ -1304,6 +1375,8 @@ UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlum
|
|||
{
|
||||
size_t name_length;
|
||||
INT32 i;
|
||||
if (!W_IsFilePresent(wad))
|
||||
return UINT16_MAX;
|
||||
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||
name_length = strlen(name);
|
||||
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
||||
|
@ -1325,7 +1398,10 @@ UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlum
|
|||
UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
|
||||
{
|
||||
INT32 i;
|
||||
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||
lumpinfo_t *lump_p;
|
||||
if (!W_IsFilePresent(wad))
|
||||
return UINT16_MAX;
|
||||
lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
||||
{
|
||||
if (strnicmp(name, lump_p->fullname, strlen(name)))
|
||||
|
@ -1339,7 +1415,10 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
|
|||
UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump)
|
||||
{
|
||||
INT32 i;
|
||||
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||
lumpinfo_t *lump_p;
|
||||
if (!W_IsFilePresent(wad))
|
||||
return UINT16_MAX;
|
||||
lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
||||
{
|
||||
if (!strnicmp(name, lump_p->fullname, strlen(name)))
|
||||
|
@ -1456,6 +1535,8 @@ lumpnum_t W_CheckNumForMap(const char *name)
|
|||
lumpinfo_t *p;
|
||||
for (i = numwadfiles - 1; i < numwadfiles; i--)
|
||||
{
|
||||
if (!W_IsFilePresent(i))
|
||||
continue;
|
||||
if (wadfiles[i]->type == RET_WAD)
|
||||
{
|
||||
for (lumpNum = 0; lumpNum < wadfiles[i]->numlumps; lumpNum++)
|
||||
|
@ -1536,6 +1617,8 @@ lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, con
|
|||
// scan wad files backwards so patch lump files take precedence
|
||||
for (i = numwadfiles - 1; i >= 0; i--)
|
||||
{
|
||||
if (!W_IsFilePresent(i))
|
||||
continue;
|
||||
if (wadfiles[i]->type == RET_WAD)
|
||||
{
|
||||
bsid = W_CheckNumForNamePwad(blockstart, (UINT16)i, 0);
|
||||
|
@ -1560,7 +1643,10 @@ UINT8 W_LumpExists(const char *name)
|
|||
INT32 i,j;
|
||||
for (i = numwadfiles - 1; i >= 0; i--)
|
||||
{
|
||||
lumpinfo_t *lump_p = wadfiles[i]->lumpinfo;
|
||||
lumpinfo_t *lump_p;
|
||||
if (!W_IsFilePresent(i))
|
||||
continue;
|
||||
lump_p = wadfiles[i]->lumpinfo;
|
||||
for (j = 0; j < wadfiles[i]->numlumps; ++j, ++lump_p)
|
||||
if (fastcmp(lump_p->longname, name))
|
||||
return true;
|
||||
|
@ -1628,6 +1714,9 @@ size_t W_LumpLength(lumpnum_t lumpnum)
|
|||
//
|
||||
boolean W_IsLumpWad(lumpnum_t lumpnum)
|
||||
{
|
||||
if (!W_IsFilePresent(WADFILENUM(lumpnum)))
|
||||
return false;
|
||||
|
||||
if (W_FileHasFolders(wadfiles[WADFILENUM(lumpnum)]))
|
||||
{
|
||||
const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->fullname;
|
||||
|
@ -1646,6 +1735,9 @@ boolean W_IsLumpWad(lumpnum_t lumpnum)
|
|||
//
|
||||
boolean W_IsLumpFolder(UINT16 wad, UINT16 lump)
|
||||
{
|
||||
if (!W_IsFilePresent(wad))
|
||||
return false;
|
||||
|
||||
if (W_FileHasFolders(wadfiles[wad]))
|
||||
{
|
||||
const char *name = wadfiles[wad]->lumpinfo[lump].fullname;
|
||||
|
@ -2177,6 +2269,9 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5)
|
|||
UINT8 realmd5[MD5_LEN];
|
||||
INT32 ix;
|
||||
|
||||
if (!W_IsFilePresent(wadfilenum))
|
||||
return;
|
||||
|
||||
I_Assert(strlen(matchmd5) == 2*MD5_LEN);
|
||||
I_Assert(wadfilenum < numwadfiles);
|
||||
// Convert an md5 string like "7d355827fa8f981482246d6c95f9bd48"
|
||||
|
|
11
src/w_wad.h
11
src/w_wad.h
|
@ -152,9 +152,11 @@ typedef struct
|
|||
// =========================================================================
|
||||
|
||||
void W_Shutdown(void);
|
||||
void W_UnloadFile(wadfile_t *wadfile);
|
||||
|
||||
// Opens a WAD file. Returns the FILE * handle for the file, or NULL if not found or could not be opened
|
||||
FILE *W_OpenWadFile(const char **filename, boolean useerrors);
|
||||
|
||||
// Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error
|
||||
UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup);
|
||||
// Adds a folder as a file
|
||||
|
@ -168,6 +170,15 @@ void W_InitMultipleFiles(addfilelist_t *list);
|
|||
INT32 W_IsPathToFolderValid(const char *path);
|
||||
char *W_GetFullFolderPath(const char *path);
|
||||
|
||||
// Checks if a file exists in the specified slot.
|
||||
boolean W_IsFilePresent(UINT16 wadnum);
|
||||
|
||||
// Loads all SOC and Lua scripts from a file.
|
||||
void W_LoadFileScripts(UINT16 wadfilenum, boolean mainfile);
|
||||
|
||||
// Unloads a file.
|
||||
void W_UnloadWadFile(UINT16 num);
|
||||
|
||||
const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump);
|
||||
const char *W_CheckNameForNum(lumpnum_t lumpnum);
|
||||
|
||||
|
|
Loading…
Reference in a new issue