Squashed commit

This commit is contained in:
Lactozilla 2023-07-27 21:21:46 -03:00
parent 2ef231c073
commit 19f22aaf82
38 changed files with 1019 additions and 199 deletions

View file

@ -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.

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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))

View file

@ -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.

View file

@ -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

View file

@ -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;

View file

@ -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));
}

View file

@ -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);

View file

@ -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)

View file

@ -2354,7 +2354,7 @@ else if (strlen(name) <= 6) \
else \
arr[0] = 0;
static void F_CacheTitleScreen(void)
void F_CacheTitleScreen(void)
{
switch(curttmode)
{

View file

@ -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,

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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);

View file

@ -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 *);

View file

@ -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

View file

@ -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

View file

@ -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];

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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.

View file

@ -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);

View file

@ -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:

View file

@ -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]);
*/
}
//

View file

@ -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;

View file

@ -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.

View file

@ -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);

View file

@ -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"

View file

@ -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);