From b1a8aaaee6d26247423e17d2a2ba8ea1cc9692a8 Mon Sep 17 00:00:00 2001 From: havoc Date: Fri, 25 Feb 2011 19:05:21 +0000 Subject: [PATCH] reworked the entire config loading system for the gamedir command gamedir switch now fully resets command/alias/cvar state FS_Rescan function now automatically switches gamemode based on first specified gamedir (mission pack hud, gameplayfix cvars, etc) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10864 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_parse.c | 9 +- cmd.c | 81 ++++++++++++++++++ cmd.h | 5 ++ common.c | 227 ++++++++++++++++++++++++++------------------------- common.h | 2 + cvar.c | 102 ++++++++++++++++++----- cvar.h | 13 +++ fs.c | 24 +++++- host.c | 53 +++++++----- host_cmd.c | 28 ++----- menu.c | 194 ++++++++++++++++--------------------------- r_shadow.c | 5 -- sbar.c | 7 +- sv_main.c | 71 +++++----------- vid_shared.c | 15 +++- view.c | 5 +- zone.c | 6 +- 17 files changed, 475 insertions(+), 372 deletions(-) diff --git a/cl_parse.c b/cl_parse.c index dd9f5504..08c726fa 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -166,7 +166,6 @@ cvar_t cl_worldname = {CVAR_READONLY, "cl_worldname", "", "name of current world cvar_t cl_worldnamenoextension = {CVAR_READONLY, "cl_worldnamenoextension", "", "name of current worldmodel without extension"}; cvar_t cl_worldbasename = {CVAR_READONLY, "cl_worldbasename", "", "name of current worldmodel without maps/ prefix or extension"}; -cvar_t demo_nehahra = {0, "demo_nehahra", "0", "reads all quake demos as nehahra movie protocol"}; cvar_t developer_networkentities = {0, "developer_networkentities", "0", "prints received entities, value is 0-4 (higher for more info)"}; cvar_t cl_gameplayfix_soundsmovewithentities = {0, "cl_gameplayfix_soundsmovewithentities", "1", "causes sounds made by lifts, players, projectiles, and any other entities, to move with the entity, so for example a rocket noise follows the rocket rather than staying at the starting position"}; cvar_t cl_sound_wizardhit = {0, "cl_sound_wizardhit", "wizard/hit.wav", "sound to play during TE_WIZSPIKE (empty cvar disables sound)"}; @@ -1651,7 +1650,7 @@ void CL_ParseServerInfo (void) return; } // hack for unmarked Nehahra movie demos which had a custom protocol - if (protocol == PROTOCOL_QUAKEDP && cls.demoplayback && demo_nehahra.integer) + if (protocol == PROTOCOL_QUAKEDP && cls.demoplayback && gamemode == GAME_NEHAHRA) protocol = PROTOCOL_NEHAHRAMOVIE; cls.protocol = protocol; Con_DPrintf("Server protocol is %s\n", Protocol_NameForEnum(cls.protocol)); @@ -3782,7 +3781,7 @@ void CL_ParseServerMessage(void) if (protocol == PROTOCOL_UNKNOWN) Host_Error("CL_ParseServerMessage: Server is unrecognized protocol number (%i)", i); // hack for unmarked Nehahra movie demos which had a custom protocol - if (protocol == PROTOCOL_QUAKEDP && cls.demoplayback && demo_nehahra.integer) + if (protocol == PROTOCOL_QUAKEDP && cls.demoplayback && gamemode == GAME_NEHAHRA) protocol = PROTOCOL_NEHAHRAMOVIE; cls.protocol = protocol; break; @@ -4193,10 +4192,6 @@ void CL_Parse_Init(void) Cvar_RegisterVariable(&cl_worldnamenoextension); Cvar_RegisterVariable(&cl_worldbasename); - // LordHavoc: added demo_nehahra cvar - Cvar_RegisterVariable (&demo_nehahra); - if (gamemode == GAME_NEHAHRA) - Cvar_SetValue("demo_nehahra", 1); Cvar_RegisterVariable(&developer_networkentities); Cvar_RegisterVariable(&cl_gameplayfix_soundsmovewithentities); diff --git a/cmd.c b/cmd.c index 7b156277..a395eed6 100644 --- a/cmd.c +++ b/cmd.c @@ -26,6 +26,8 @@ typedef struct cmdalias_s struct cmdalias_s *next; char name[MAX_ALIAS_NAME]; char *value; + qboolean initstate; // indicates this command existed at init + char *initialvalue; // backup copy of value at init } cmdalias_t; static cmdalias_t *cmd_alias; @@ -492,6 +494,24 @@ static void Cmd_Exec_f (void) Cbuf_InsertText ("\n"); Cbuf_InsertText (f); Mem_Free(f); + + // special defaults for specific games go here, these execute before default.cfg + // Nehahra pushable crates malfunction in some levels if this is on + // Nehahra NPC AI is confused by blowupfallenzombies + if (gamemode == GAME_NEHAHRA) + Cbuf_InsertText("\nsv_gameplayfix_upwardvelocityclearsongroundflag 0\nsv_gameplayfix_blowupfallenzombies 0\n\n"); + // hipnotic mission pack has issues in their 'friendly monster' ai, which seem to attempt to attack themselves for some reason when findradius() returns non-solid entities. + // hipnotic mission pack has issues with bobbing water entities 'jittering' between different heights on alternate frames at the default 0.0138889 ticrate, 0.02 avoids this issue + // hipnotic mission pack has issues in their proximity mine sticking code, which causes them to bounce off. + if (gamemode == GAME_HIPNOTIC) + Cbuf_InsertText("\nsv_gameplayfix_blowupfallenzombies 0\nsys_ticrate 0.02\nsv_gameplayfix_slidemoveprojectiles 0\n\n"); + // rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area + if (gamemode == GAME_ROGUE) + Cbuf_InsertText("\nsv_gameplayfix_findradiusdistancetobox 0\n\n"); + if (gamemode == GAME_NEXUIZ) + Cbuf_InsertText("\nsv_gameplayfix_q2airaccelerate 1\nsv_gameplayfix_stepmultipletimes 1\n\n"); + if (gamemode == GAME_TENEBRAE) + Cbuf_InsertText("\nr_shadow_gloss 2\nr_shadow_bumpscale_basetexture 4\n\n"); } @@ -694,6 +714,8 @@ static void Cmd_UnAlias_f (void) { if(!strcmp(s, a->name)) { + if (a->initstate) // we can not remove init aliases + continue; if(a == cmd_alias) cmd_alias = a->next; if(p) @@ -724,6 +746,7 @@ typedef struct cmd_function_s xcommand_t consolefunction; xcommand_t clientfunction; qboolean csqcfunc; + qboolean initstate; // indicates this command existed at init } cmd_function_t; static int cmd_argc; @@ -1874,3 +1897,61 @@ int Cmd_CheckParm (const char *parm) return 0; } + + +void Cmd_SaveInitState(void) +{ + cmd_function_t *f; + cmdalias_t *a; + for (f = cmd_functions;f;f = f->next) + f->initstate = true; + for (a = cmd_alias;a;a = a->next) + { + a->initstate = true; + a->initialvalue = Mem_strdup(zonemempool, a->value); + } + Cvar_SaveInitState(); +} + +void Cmd_RestoreInitState(void) +{ + cmd_function_t *f, **fp; + cmdalias_t *a, **ap; + for (fp = &cmd_functions;(f = *fp);) + { + if (f->initstate) + fp = &f->next; + else + { + // destroy this command, it didn't exist at init + Con_DPrintf("Cmd_RestoreInitState: Destroying command %s\n", f->name); + *fp = f->next; + Z_Free(f); + } + } + for (ap = &cmd_alias;(a = *ap);) + { + if (a->initstate) + { + // restore this alias, it existed at init + if (strcmp(a->value ? a->value : "", a->initialvalue ? a->initialvalue : "")) + { + Con_DPrintf("Cmd_RestoreInitState: Restoring alias %s\n", a->name); + if (a->value) + Z_Free(a->value); + a->value = Mem_strdup(zonemempool, a->initialvalue); + } + ap = &a->next; + } + else + { + // free this alias, it didn't exist at init... + Con_DPrintf("Cmd_RestoreInitState: Destroying alias %s\n", a->name); + *ap = a->next; + if (a->value) + Z_Free(a->value); + Z_Free(a); + } + } + Cvar_RestoreInitState(); +} diff --git a/cmd.h b/cmd.h index a4881c65..cb96abaa 100644 --- a/cmd.h +++ b/cmd.h @@ -89,6 +89,11 @@ extern cmd_source_t cmd_source; void Cmd_Init (void); void Cmd_Shutdown (void); +// called by Host_Init, this marks cvars, commands and aliases with their init values +void Cmd_SaveInitState (void); +// called by FS_GameDir_f, this restores cvars, commands and aliases to init values +void Cmd_RestoreInitState (void); + void Cmd_AddCommand_WithClientCommand (const char *cmd_name, xcommand_t consolefunction, xcommand_t clientfunction, const char *description); void Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *description); // called by the init functions of other parts of the program to diff --git a/common.c b/common.c index 11a350bf..b75a348e 100644 --- a/common.c +++ b/common.c @@ -1419,8 +1419,13 @@ int COM_CheckParm (const char *parm) // Game mods +gamemode_t com_startupgamemode; +gamemode_t com_startupgamegroup; + typedef struct gamemode_info_s { + gamemode_t mode; // this gamemode + gamemode_t group; // different games with same group can switch automatically when gamedirs change const char* prog_name; // not null const char* cmdline; // not null const char* gamename; // not null @@ -1431,136 +1436,136 @@ typedef struct gamemode_info_s } gamemode_info_t; static const gamemode_info_t gamemode_info [GAME_COUNT] = -{// prog_name cmdline gamename basegame modgame screenshotprefix userdir - -// GAME_NORMAL -// COMMANDLINEOPTION: Game: -quake runs the game Quake (default) -{ "", "-quake", "DarkPlaces-Quake", "id1", NULL, "dp", "darkplaces" }, -// GAME_HIPNOTIC -// COMMANDLINEOPTION: Game: -hipnotic runs Quake mission pack 1: The Scourge of Armagon -{ "hipnotic", "-hipnotic", "Darkplaces-Hipnotic", "id1", "hipnotic", "dp", "darkplaces" }, -// GAME_ROGUE -// COMMANDLINEOPTION: Game: -rogue runs Quake mission pack 2: The Dissolution of Eternity -{ "rogue", "-rogue", "Darkplaces-Rogue", "id1", "rogue", "dp", "darkplaces" }, -// GAME_NEHAHRA -// COMMANDLINEOPTION: Game: -nehahra runs The Seal of Nehahra movie and game -{ "nehahra", "-nehahra", "DarkPlaces-Nehahra", "id1", "nehahra", "dp", "darkplaces" }, -// GAME_NEXUIZ -// COMMANDLINEOPTION: Game: -nexuiz runs the multiplayer game Nexuiz -{ "nexuiz", "-nexuiz", "Nexuiz", "data", NULL, "nexuiz", "nexuiz" }, -// GAME_XONOTIC -// COMMANDLINEOPTION: Game: -xonotic runs the multiplayer game Xonotic -{ "xonotic", "-xonotic", "Xonotic", "data", NULL, "xonotic", "xonotic" }, -// GAME_TRANSFUSION -// COMMANDLINEOPTION: Game: -transfusion runs Transfusion (the recreation of Blood in Quake) -{ "transfusion", "-transfusion", "Transfusion", "basetf", NULL, "transfusion", "transfusion" }, -// GAME_GOODVSBAD2 -// COMMANDLINEOPTION: Game: -goodvsbad2 runs the psychadelic RTS FPS game Good Vs Bad 2 -{ "gvb2", "-goodvsbad2", "GoodVs.Bad2", "rts", NULL, "gvb2", "gvb2" }, -// GAME_TEU -// COMMANDLINEOPTION: Game: -teu runs The Evil Unleashed (this option is obsolete as they are not using darkplaces) -{ "teu", "-teu", "TheEvilUnleashed", "baseteu", NULL, "teu", "teu" }, -// GAME_BATTLEMECH -// COMMANDLINEOPTION: Game: -battlemech runs the multiplayer topdown deathmatch game BattleMech -{ "battlemech", "-battlemech", "Battlemech", "base", NULL, "battlemech", "battlemech" }, -// GAME_ZYMOTIC -// COMMANDLINEOPTION: Game: -zymotic runs the singleplayer game Zymotic -{ "zymotic", "-zymotic", "Zymotic", "basezym", NULL, "zymotic", "zymotic" }, -// GAME_SETHERAL -// COMMANDLINEOPTION: Game: -setheral runs the multiplayer game Setheral -{ "setheral", "-setheral", "Setheral", "data", NULL, "setheral", "setheral" }, -// GAME_SOM -// COMMANDLINEOPTION: Game: -som runs the multiplayer game Son Of Man -{ "som", "-som", "Son of Man", "id1", "sonofman", "som", "darkplaces" }, -// GAME_TENEBRAE -// COMMANDLINEOPTION: Game: -tenebrae runs the graphics test mod known as Tenebrae (some features not implemented) -{ "tenebrae", "-tenebrae", "DarkPlaces-Tenebrae", "id1", "tenebrae", "dp", "darkplaces" }, -// GAME_NEOTERIC -// COMMANDLINEOPTION: Game: -neoteric runs the game Neoteric -{ "neoteric", "-neoteric", "Neoteric", "id1", "neobase", "neo", "darkplaces" }, -// GAME_OPENQUARTZ -// COMMANDLINEOPTION: Game: -openquartz runs the game OpenQuartz, a standalone GPL replacement of the quake content -{ "openquartz", "-openquartz", "OpenQuartz", "id1", NULL, "openquartz", "darkplaces" }, -// GAME_PRYDON -// COMMANDLINEOPTION: Game: -prydon runs the topdown point and click action-RPG Prydon Gate -{ "prydon", "-prydon", "PrydonGate", "id1", "prydon", "prydon", "darkplaces" }, -// GAME_DELUXEQUAKE -// COMMANDLINEOPTION: Game: -dq runs the game Deluxe Quake -{ "dq", "-dq", "Deluxe Quake", "basedq", "extradq", "basedq", "dq" }, -// GAME_THEHUNTED -// COMMANDLINEOPTION: Game: -thehunted runs the game The Hunted -{ "thehunted", "-thehunted", "The Hunted", "thdata", NULL, "th", "thehunted" }, -// GAME_DEFEATINDETAIL2 -// COMMANDLINEOPTION: Game: -did2 runs the game Defeat In Detail 2 -{ "did2", "-did2", "Defeat In Detail 2", "data", NULL, "did2_", "did2" }, -// GAME_DARSANA -// COMMANDLINEOPTION: Game: -darsana runs the game Darsana -{ "darsana", "-darsana", "Darsana", "ddata", NULL, "darsana", "darsana" }, -// GAME_CONTAGIONTHEORY -// COMMANDLINEOPTION: Game: -contagiontheory runs the game Contagion Theory -{ "contagiontheory", "-contagiontheory", "Contagion Theory", "ctdata", NULL, "ct", "contagiontheory" }, -// GAME_EDU2P -// COMMANDLINEOPTION: Game: -edu2p runs the game Edu2 prototype -{ "edu2p", "-edu2p", "EDU2 Prototype", "id1", "edu2", "edu2_p", "edu2prototype" }, -// GAME_PROPHECY -// COMMANDLINEOPTION: Game: -prophecy runs the game Prophecy -{ "prophecy", "-prophecy", "Prophecy", "data", NULL, "prophecy", "prophecy" }, -// GAME_BLOODOMNICIDE -// COMMANDLINEOPTION: Game: -omnicide runs the game Blood Omnicide -{ "omnicide", "-omnicide", "Blood Omnicide", "kain", NULL, "omnicide", "omnicide" }, -// GAME_STEELSTORM -// COMMANDLINEOPTION: Game: -steelstorm runs the game Steel Storm -{ "steelstorm", "-steelstorm", "Steel-Storm", "gamedata", NULL, "ss", "steelstorm" }, -// GAME_STRAPBOMB -// COMMANDLINEOPTION: Game: -strapbomb runs the game Strap-on-bomb Car -{ "strapbomb", "-strapbomb", "Strap-on-bomb Car", "id1", NULL, "strap", "strapbomb" }, -// GAME_MOONHELM -// COMMANDLINEOPTION: Game: -moonhelm runs the game MoonHelm -{ "moonhelm", "-moonhelm", "MoonHelm", "data", NULL, "mh", "moonhelm" }, +{// game basegame prog_name cmdline gamename basegame modgame screenshot userdir // commandline option +{ GAME_NORMAL, GAME_NORMAL, "", "-quake", "DarkPlaces-Quake", "id1", NULL, "dp", "darkplaces" }, // COMMANDLINEOPTION: Game: -quake runs the game Quake (default) +{ GAME_HIPNOTIC, GAME_NORMAL, "hipnotic", "-hipnotic", "Darkplaces-Hipnotic", "id1", "hipnotic", "dp", "darkplaces" }, // COMMANDLINEOPTION: Game: -hipnotic runs Quake mission pack 1: The Scourge of Armagon +{ GAME_ROGUE, GAME_NORMAL, "rogue", "-rogue", "Darkplaces-Rogue", "id1", "rogue", "dp", "darkplaces" }, // COMMANDLINEOPTION: Game: -rogue runs Quake mission pack 2: The Dissolution of Eternity +{ GAME_NEHAHRA, GAME_NORMAL, "nehahra", "-nehahra", "DarkPlaces-Nehahra", "id1", "nehahra", "dp", "darkplaces" }, // COMMANDLINEOPTION: Game: -nehahra runs The Seal of Nehahra movie and game +{ GAME_NEXUIZ, GAME_NEXUIZ, "nexuiz", "-nexuiz", "Nexuiz", "data", NULL, "nexuiz", "nexuiz" }, // COMMANDLINEOPTION: Game: -nexuiz runs the multiplayer game Nexuiz +{ GAME_XONOTIC, GAME_XONOTIC, "xonotic", "-xonotic", "Xonotic", "data", NULL, "xonotic", "xonotic" }, // COMMANDLINEOPTION: Game: -xonotic runs the multiplayer game Xonotic +{ GAME_TRANSFUSION, GAME_TRANSFUSION, "transfusion", "-transfusion", "Transfusion", "basetf", NULL, "transfusion", "transfusion" }, // COMMANDLINEOPTION: Game: -transfusion runs Transfusion (the recreation of Blood in Quake) +{ GAME_GOODVSBAD2, GAME_GOODVSBAD2, "gvb2", "-goodvsbad2", "GoodVs.Bad2", "rts", NULL, "gvb2", "gvb2" }, // COMMANDLINEOPTION: Game: -goodvsbad2 runs the psychadelic RTS FPS game Good Vs Bad 2 +{ GAME_TEU, GAME_TEU, "teu", "-teu", "TheEvilUnleashed", "baseteu", NULL, "teu", "teu" }, // COMMANDLINEOPTION: Game: -teu runs The Evil Unleashed (this option is obsolete as they are not using darkplaces) +{ GAME_BATTLEMECH, GAME_BATTLEMECH, "battlemech", "-battlemech", "Battlemech", "base", NULL, "battlemech", "battlemech" }, // COMMANDLINEOPTION: Game: -battlemech runs the multiplayer topdown deathmatch game BattleMech +{ GAME_ZYMOTIC, GAME_ZYMOTIC, "zymotic", "-zymotic", "Zymotic", "basezym", NULL, "zymotic", "zymotic" }, // COMMANDLINEOPTION: Game: -zymotic runs the singleplayer game Zymotic +{ GAME_SETHERAL, GAME_SETHERAL, "setheral", "-setheral", "Setheral", "data", NULL, "setheral", "setheral" }, // COMMANDLINEOPTION: Game: -setheral runs the multiplayer game Setheral +{ GAME_SOM, GAME_NORMAL, "som", "-som", "Son of Man", "id1", "sonofman", "som", "darkplaces" }, // COMMANDLINEOPTION: Game: -som runs the multiplayer game Son Of Man +{ GAME_TENEBRAE, GAME_NORMAL, "tenebrae", "-tenebrae", "DarkPlaces-Tenebrae", "id1", "tenebrae", "dp", "darkplaces" }, // COMMANDLINEOPTION: Game: -tenebrae runs the graphics test mod known as Tenebrae (some features not implemented) +{ GAME_NEOTERIC, GAME_NORMAL, "neoteric", "-neoteric", "Neoteric", "id1", "neobase", "neo", "darkplaces" }, // COMMANDLINEOPTION: Game: -neoteric runs the game Neoteric +{ GAME_OPENQUARTZ, GAME_NORMAL, "openquartz", "-openquartz", "OpenQuartz", "id1", NULL, "openquartz", "darkplaces" }, // COMMANDLINEOPTION: Game: -openquartz runs the game OpenQuartz, a standalone GPL replacement of the quake content +{ GAME_PRYDON, GAME_NORMAL, "prydon", "-prydon", "PrydonGate", "id1", "prydon", "prydon", "darkplaces" }, // COMMANDLINEOPTION: Game: -prydon runs the topdown point and click action-RPG Prydon Gate +{ GAME_DELUXEQUAKE, GAME_DELUXEQUAKE, "dq", "-dq", "Deluxe Quake", "basedq", "extradq", "basedq", "dq" }, // COMMANDLINEOPTION: Game: -dq runs the game Deluxe Quake +{ GAME_THEHUNTED, GAME_THEHUNTED, "thehunted", "-thehunted", "The Hunted", "thdata", NULL, "th", "thehunted" }, // COMMANDLINEOPTION: Game: -thehunted runs the game The Hunted +{ GAME_DEFEATINDETAIL2, GAME_DEFEATINDETAIL2, "did2", "-did2", "Defeat In Detail 2", "data", NULL, "did2_", "did2" }, // COMMANDLINEOPTION: Game: -did2 runs the game Defeat In Detail 2 +{ GAME_DARSANA, GAME_DARSANA, "darsana", "-darsana", "Darsana", "ddata", NULL, "darsana", "darsana" }, // COMMANDLINEOPTION: Game: -darsana runs the game Darsana +{ GAME_CONTAGIONTHEORY, GAME_CONTAGIONTHEORY, "contagiontheory", "-contagiontheory", "Contagion Theory", "ctdata", NULL, "ct", "contagiontheory" }, // COMMANDLINEOPTION: Game: -contagiontheory runs the game Contagion Theory +{ GAME_EDU2P, GAME_EDU2P, "edu2p", "-edu2p", "EDU2 Prototype", "id1", "edu2", "edu2_p", "edu2prototype" }, // COMMANDLINEOPTION: Game: -edu2p runs the game Edu2 prototype +{ GAME_PROPHECY, GAME_PROPHECY, "prophecy", "-prophecy", "Prophecy", "data", NULL, "prophecy", "prophecy" }, // COMMANDLINEOPTION: Game: -prophecy runs the game Prophecy +{ GAME_BLOODOMNICIDE, GAME_BLOODOMNICIDE, "omnicide", "-omnicide", "Blood Omnicide", "kain", NULL, "omnicide", "omnicide" }, // COMMANDLINEOPTION: Game: -omnicide runs the game Blood Omnicide +{ GAME_STEELSTORM, GAME_STEELSTORM, "steelstorm", "-steelstorm", "Steel-Storm", "gamedata", NULL, "ss", "steelstorm" }, // COMMANDLINEOPTION: Game: -steelstorm runs the game Steel Storm +{ GAME_STRAPBOMB, GAME_STRAPBOMB, "strapbomb", "-strapbomb", "Strap-on-bomb Car", "id1", NULL, "strap", "strapbomb" }, // COMMANDLINEOPTION: Game: -strapbomb runs the game Strap-on-bomb Car +{ GAME_MOONHELM, GAME_MOONHELM, "moonhelm", "-moonhelm", "MoonHelm", "data", NULL, "mh", "moonhelm" }, // COMMANDLINEOPTION: Game: -moonhelm runs the game MoonHelm }; +static void COM_SetGameType(int index); void COM_InitGameType (void) { char name [MAX_OSPATH]; - unsigned int i; - int t; + int i; + int index = 0; FS_StripExtension (com_argv[0], name, sizeof (name)); COM_ToLowerString (name, name, sizeof (name)); - // Check the binary name; default to GAME_NORMAL (0) - gamemode = GAME_NORMAL; - for (i = 1; i < sizeof (gamemode_info) / sizeof (gamemode_info[0]); i++) + // check executable filename for keywords + for (i = 1;i < (int)(sizeof (gamemode_info) / sizeof (gamemode_info[0]));i++) if (strstr (name, gamemode_info[i].prog_name)) { - gamemode = (gamemode_t)i; + index = i; break; } - // Look for a command-line option - for (i = 0; i < sizeof (gamemode_info) / sizeof (gamemode_info[0]); i++) + // check commandline options for keywords + for (i = 0;i < (int)(sizeof (gamemode_info) / sizeof (gamemode_info[0]));i++) if (COM_CheckParm (gamemode_info[i].cmdline)) { - gamemode = (gamemode_t)i; + index = i; + break; + } + + com_startupgamemode = gamemode_info[index].mode; + com_startupgamegroup = gamemode_info[index].group; + COM_SetGameType(index); +} + +void COM_ChangeGameTypeForGameDirs(void) +{ + int i; + int index = -1; + // this will not not change the gamegroup + // first check if a base game (single gamedir) matches + for (i = 0;i < (int)(sizeof (gamemode_info) / sizeof (gamemode_info[0]));i++) + { + if (gamemode_info[i].group == com_startupgamegroup && !(gamemode_info[i].gamedirname2 && gamemode_info[i].gamedirname2[0])) + { + index = i; break; } + } + // now that we have a base game, see if there is a matching derivative game (two gamedirs) + if (fs_numgamedirs) + { + for (i = 0;i < (int)(sizeof (gamemode_info) / sizeof (gamemode_info[0]));i++) + { + if (gamemode_info[i].group == com_startupgamegroup && (gamemode_info[i].gamedirname2 && gamemode_info[i].gamedirname2[0]) && !strcasecmp(fs_gamedirs[0], gamemode_info[i].gamedirname2)) + { + index = i; + break; + } + } + } + // we now have a good guess at which game this is meant to be... + if (index >= 0 && gamemode != gamemode_info[index].mode) + COM_SetGameType(index); +} + +static void COM_SetGameType(int index) +{ + int i, t; + if (index < 0 || index >= (int)(sizeof (gamemode_info) / sizeof (gamemode_info[0]))) + index = 0; + gamemode = gamemode_info[index].mode; + gamename = gamemode_info[index].gamename; + gamedirname1 = gamemode_info[index].gamedirname1; + gamedirname2 = gamemode_info[index].gamedirname2; + gamescreenshotname = gamemode_info[index].gamescreenshotname; + gameuserdirname = gamemode_info[index].gameuserdirname; + + if (gamemode == com_startupgamemode) + { + if((t = COM_CheckParm("-customgamename")) && t + 1 < com_argc) + gamename = com_argv[t+1]; + if((t = COM_CheckParm("-customgamedirname1")) && t + 1 < com_argc) + gamedirname1 = com_argv[t+1]; + if((t = COM_CheckParm("-customgamedirname2")) && t + 1 < com_argc) + gamedirname2 = *com_argv[t+1] ? com_argv[t+1] : NULL; + if((t = COM_CheckParm("-customgamescreenshotname")) && t + 1 < com_argc) + gamescreenshotname = com_argv[t+1]; + if((t = COM_CheckParm("-customgameuserdirname")) && t + 1 < com_argc) + gameuserdirname = com_argv[t+1]; + } - gamename = gamemode_info[gamemode].gamename; - gamedirname1 = gamemode_info[gamemode].gamedirname1; - gamedirname2 = gamemode_info[gamemode].gamedirname2; - gamescreenshotname = gamemode_info[gamemode].gamescreenshotname; - gameuserdirname = gamemode_info[gamemode].gameuserdirname; - - if((t = COM_CheckParm("-customgamename")) && t + 1 < com_argc) - gamename = com_argv[t+1]; - if((t = COM_CheckParm("-customgamedirname1")) && t + 1 < com_argc) - gamedirname1 = com_argv[t+1]; - if((t = COM_CheckParm("-customgamedirname2")) && t + 1 < com_argc) - gamedirname2 = *com_argv[t+1] ? com_argv[t+1] : NULL; - if((t = COM_CheckParm("-customgamescreenshotname")) && t + 1 < com_argc) - gamescreenshotname = com_argv[t+1]; - if((t = COM_CheckParm("-customgameuserdirname")) && t + 1 < com_argc) - gameuserdirname = com_argv[t+1]; + if (gamedirname2 && gamedirname2[0]) + Con_Printf("Game is %s using base gamedirs %s %s", gamename, gamedirname1, gamedirname2); + else + Con_Printf("Game is %s using base gamedir %s", gamename, gamedirname1); + for (i = 0;i < fs_numgamedirs;i++) + { + if (i == 0) + Con_Printf(", with mod gamedirs"); + Con_Printf(" %s", fs_gamedirs[i]); + } + Con_Printf("\n"); } diff --git a/common.h b/common.h index f3516c5d..ecd8b856 100644 --- a/common.h +++ b/common.h @@ -293,6 +293,8 @@ extern const char *gamescreenshotname; extern const char *gameuserdirname; extern char com_modname[MAX_OSPATH]; +void COM_ChangeGameTypeForGameDirs(void); + void COM_ToLowerString (const char *in, char *out, size_t size_out); void COM_ToUpperString (const char *in, char *out, size_t size_out); int COM_StringBeginsWith(const char *s, const char *match); diff --git a/cvar.c b/cvar.c index 8d5af144..221a5244 100644 --- a/cvar.c +++ b/cvar.c @@ -557,7 +557,6 @@ cvar_t *Cvar_Get (const char *name, const char *value, int flags, const char *ne { int hashindex; cvar_t *current, *next, *cvar; - size_t alloclen; if (developer_extra.integer) Con_DPrintf("Cvar_Get(\"%s\", \"%s\", %i);\n", name, value, flags); @@ -574,11 +573,7 @@ cvar_t *Cvar_Get (const char *name, const char *value, int flags, const char *ne Z_Free((char *)cvar->description); if(*newdescription) - { - alloclen = strlen(newdescription) + 1; - cvar->description = (char *)Z_Malloc(alloclen); - memcpy((char *)cvar->description, newdescription, alloclen); - } + cvar->description = (char *)Mem_strdup(zonemempool, newdescription); else cvar->description = cvar_dummy_description; } @@ -604,23 +599,14 @@ cvar_t *Cvar_Get (const char *name, const char *value, int flags, const char *ne // FIXME: these never get Z_Free'd cvar = (cvar_t *)Z_Malloc(sizeof(cvar_t)); cvar->flags = flags | CVAR_ALLOCATED; - alloclen = strlen(name) + 1; - cvar->name = (char *)Z_Malloc(alloclen); - memcpy((char *)cvar->name, name, alloclen); - alloclen = strlen(value) + 1; - cvar->string = (char *)Z_Malloc(alloclen); - memcpy((char *)cvar->string, value, alloclen); - cvar->defstring = (char *)Z_Malloc(alloclen); - memcpy((char *)cvar->defstring, value, alloclen); + cvar->name = (char *)Mem_strdup(zonemempool, name); + cvar->string = (char *)Mem_strdup(zonemempool, value); + cvar->defstring = (char *)Mem_strdup(zonemempool, value); cvar->value = atof (cvar->string); cvar->integer = (int) cvar->value; if(newdescription && *newdescription) - { - alloclen = strlen(newdescription) + 1; - cvar->description = (char *)Z_Malloc(alloclen); - memcpy((char *)cvar->description, newdescription, alloclen); - } + cvar->description = (char *)Mem_strdup(zonemempool, newdescription); else cvar->description = cvar_dummy_description; // actually checked by VM_cvar_type @@ -710,6 +696,84 @@ void Cvar_LockDefaults_f (void) } } +void Cvar_SaveInitState(void) +{ + cvar_t *c; + for (c = cvar_vars;c;c = c->next) + { + c->initstate = true; + c->initflags = c->flags; + c->initdefstring = Mem_strdup(zonemempool, c->defstring); + c->initstring = Mem_strdup(zonemempool, c->string); + c->initvalue = c->value; + c->initinteger = c->integer; + VectorCopy(c->vector, c->initvector); + } +} + +void Cvar_RestoreInitState(void) +{ + int hashindex; + cvar_t *c, **cp; + cvar_t *c2, **cp2; + for (cp = &cvar_vars;(c = *cp);) + { + if (c->initstate) + { + // restore this cvar, it existed at init + if (((c->flags ^ c->initflags) & CVAR_MAXFLAGSVAL) + || strcmp(c->defstring ? c->defstring : "", c->initdefstring ? c->initdefstring : "") + || strcmp(c->string ? c->string : "", c->initstring ? c->initstring : "")) + { + Con_DPrintf("Cvar_RestoreInitState: Restoring cvar \"%s\"\n", c->name); + if (c->defstring) + Z_Free((char *)c->defstring); + c->defstring = Mem_strdup(zonemempool, c->initdefstring); + if (c->string) + Z_Free((char *)c->string); + c->string = Mem_strdup(zonemempool, c->initstring); + } + c->flags = c->initflags; + c->value = c->initvalue; + c->integer = c->initinteger; + VectorCopy(c->initvector, c->vector); + cp = &c->next; + } + else + { + if (!(c->flags & CVAR_ALLOCATED)) + { + Con_DPrintf("Cvar_RestoreInitState: Unable to destroy cvar \"%s\", it was registered after init!\n", c->name); + continue; + } + // remove this cvar, it did not exist at init + Con_DPrintf("Cvar_RestoreInitState: Destroying cvar \"%s\"\n", c->name); + // unlink struct from hash + hashindex = CRC_Block((const unsigned char *)c->name, strlen(c->name)) % CVAR_HASHSIZE; + for (cp2 = &cvar_hashtable[hashindex];(c2 = *cp2);) + { + if (c2 == c) + { + *cp2 = c2->nextonhashchain; + break; + } + else + cp2 = &c2->next; + } + // unlink struct from main list + *cp = c->next; + // free strings + if (c->defstring) + Z_Free((char *)c->defstring); + if (c->string) + Z_Free((char *)c->string); + if (c->description && c->description != cvar_dummy_description) + Z_Free((char *)c->description); + // free struct + Z_Free(c); + } + } +} void Cvar_ResetToDefaults_All_f (void) { diff --git a/cvar.h b/cvar.h index 1509f756..e80edc07 100644 --- a/cvar.h +++ b/cvar.h @@ -124,6 +124,16 @@ typedef struct cvar_s const char *defstring; + // values at init (for Cvar_RestoreInitState) + qboolean initstate; // indicates this existed at init + int initflags; + const char *initstring; + const char *initdescription; + int initinteger; + float initvalue; + float initvector[3]; + const char *initdefstring; + unsigned int globaldefindex_progid[3]; int globaldefindex[3]; int globaldefindex_stringno[3]; @@ -178,6 +188,9 @@ qboolean Cvar_Command (void); // command. Returns true if the command was a variable reference that // was handled. (print or change) +void Cvar_SaveInitState(void); +void Cvar_RestoreInitState(void); + void Cvar_UnlockDefaults (void); void Cvar_LockDefaults_f (void); void Cvar_ResetToDefaults_All_f (void); diff --git a/fs.c b/fs.c index 3cd3b7d9..e18216eb 100644 --- a/fs.c +++ b/fs.c @@ -1309,10 +1309,17 @@ void FS_Rescan (void) { int i; qboolean fs_modified = false; + qboolean reset = false; char gamedirbuf[MAX_INPUTLINE]; + if (fs_searchpaths) + reset = true; FS_ClearSearchPath(); + // automatically activate gamemode for the gamedirs specified + if (reset) + COM_ChangeGameTypeForGameDirs(); + // add the game-specific paths // gamedirname1 (typically id1) FS_AddGameHierarchy (gamedirname1); @@ -1406,6 +1413,8 @@ FS_ChangeGameDirs */ extern void Host_SaveConfig (void); extern void Host_LoadConfig_f (void); +extern qboolean vid_opened; +extern void VID_Stop(void); qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean complain, qboolean failmissing) { int i; @@ -1454,14 +1463,21 @@ qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean // reinitialize filesystem to detect the new paks FS_Rescan(); - // exec the new config - Host_LoadConfig_f(); + if (cls.demoplayback) + { + CL_Disconnect_f(); + cls.demonum = 0; + } // unload all sounds so they will be reloaded from the new files as needed S_UnloadAllSounds_f(); - // reinitialize renderer (this reloads hud/console background/etc) - R_Modules_Restart(); + // close down the video subsystem, it will start up again when the config finishes... + VID_Stop(); + vid_opened = false; + + // restart the video subsystem after the config is executed + Cbuf_InsertText("\nloadconfig\nvid_restart\n\n"); return true; } diff --git a/host.c b/host.c index 18a8c04b..f3de7a18 100644 --- a/host.c +++ b/host.c @@ -290,6 +290,20 @@ void Host_SaveConfig_f(void) Host_SaveConfig_to(file); } +void Host_AddConfigText(void) +{ + // set up the default startmap_sp and startmap_dm aliases (mods can + // override these) and then execute the quake.rc startup script + if (gamemode == GAME_NEHAHRA) + Cbuf_InsertText("alias startmap_sp \"map nehstart\"\nalias startmap_dm \"map nehstart\"\nexec " STARTCONFIGFILENAME "\n"); + else if (gamemode == GAME_TRANSFUSION) + Cbuf_InsertText("alias startmap_sp \"map e1m1\"\n""alias startmap_dm \"map bb1\"\nexec " STARTCONFIGFILENAME "\n"); + else if (gamemode == GAME_TEU) + Cbuf_InsertText("alias startmap_sp \"map start\"\nalias startmap_dm \"map start\"\nexec teu.rc\n"); + else + Cbuf_InsertText("alias startmap_sp \"map start\"\nalias startmap_dm \"map start\"\nexec " STARTCONFIGFILENAME "\n"); +} + /* =============== Host_LoadConfig_f @@ -299,10 +313,12 @@ Resets key bindings and cvars to defaults and then reloads scripts */ void Host_LoadConfig_f(void) { - // unlock the cvar default strings so they can be updated by the new default.cfg - Cvar_UnlockDefaults(); + // reset all cvars, commands and aliases to init values + Cmd_RestoreInitState(); + // prepend a menu restart command to execute after the config + Cbuf_InsertText("\nmenu_restart\n"); // reset cvars to their defaults, and then exec startup scripts again - Cbuf_InsertText("cvar_resettodefaults_all;exec " STARTCONFIGFILENAME "\n"); + Host_AddConfigText(); } /* @@ -1151,16 +1167,19 @@ static void Host_Init (void) CL_Init(); } - // set up the default startmap_sp and startmap_dm aliases (mods can - // override these) and then execute the quake.rc startup script - if (gamemode == GAME_NEHAHRA) - Cbuf_AddText("alias startmap_sp \"map nehstart\"\nalias startmap_dm \"map nehstart\"\nexec " STARTCONFIGFILENAME "\n"); - else if (gamemode == GAME_TRANSFUSION) - Cbuf_AddText("alias startmap_sp \"map e1m1\"\n""alias startmap_dm \"map bb1\"\nexec " STARTCONFIGFILENAME "\n"); - else if (gamemode == GAME_TEU) - Cbuf_AddText("alias startmap_sp \"map start\"\nalias startmap_dm \"map start\"\nexec teu.rc\n"); - else - Cbuf_AddText("alias startmap_sp \"map start\"\nalias startmap_dm \"map start\"\nexec " STARTCONFIGFILENAME "\n"); + // save off current state of aliases, commands and cvars for later restore if FS_GameDir_f is called + // NOTE: menu commands are freed by Cmd_RestoreInitState + Cmd_SaveInitState(); + + // FIXME: put this into some neat design, but the menu should be allowed to crash + // without crashing the whole game, so this should just be a short-time solution + + // here comes the not so critical stuff + if (setjmp(host_abortframe)) { + return; + } + + Host_AddConfigText(); Cbuf_Execute(); // if stuffcmds wasn't run, then quake.rc is probably missing, use default @@ -1173,14 +1192,6 @@ static void Host_Init (void) // put up the loading image so the user doesn't stare at a black screen... SCR_BeginLoadingPlaque(); - // FIXME: put this into some neat design, but the menu should be allowed to crash - // without crashing the whole game, so this should just be a short-time solution - - // here comes the not so critical stuff - if (setjmp(host_abortframe)) { - return; - } - if (cls.state != ca_dedicated) { MR_Init(); diff --git a/host_cmd.c b/host_cmd.c index fb79076e..9b2ee270 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -2910,22 +2910,11 @@ void Host_InitCommands (void) Cmd_AddCommand_WithClientCommand ("status", Host_Status_f, Host_Status_f, "print server status information"); Cmd_AddCommand ("quit", Host_Quit_f, "quit the game"); - if (gamemode == GAME_NEHAHRA) - { - Cmd_AddCommand_WithClientCommand ("max", NULL, Host_God_f, "god mode (invulnerability)"); - Cmd_AddCommand_WithClientCommand ("monster", NULL, Host_Notarget_f, "notarget mode (monsters do not see you)"); - Cmd_AddCommand_WithClientCommand ("scrag", NULL, Host_Fly_f, "fly mode (flight)"); - Cmd_AddCommand_WithClientCommand ("wraith", NULL, Host_Noclip_f, "noclip mode (flight without collisions, move through walls)"); - Cmd_AddCommand_WithClientCommand ("gimme", NULL, Host_Give_f, "alter inventory"); - } - else - { - Cmd_AddCommand_WithClientCommand ("god", NULL, Host_God_f, "god mode (invulnerability)"); - Cmd_AddCommand_WithClientCommand ("notarget", NULL, Host_Notarget_f, "notarget mode (monsters do not see you)"); - Cmd_AddCommand_WithClientCommand ("fly", NULL, Host_Fly_f, "fly mode (flight)"); - Cmd_AddCommand_WithClientCommand ("noclip", NULL, Host_Noclip_f, "noclip mode (flight without collisions, move through walls)"); - Cmd_AddCommand_WithClientCommand ("give", NULL, Host_Give_f, "alter inventory"); - } + Cmd_AddCommand_WithClientCommand ("god", NULL, Host_God_f, "god mode (invulnerability)"); + Cmd_AddCommand_WithClientCommand ("notarget", NULL, Host_Notarget_f, "notarget mode (monsters do not see you)"); + Cmd_AddCommand_WithClientCommand ("fly", NULL, Host_Fly_f, "fly mode (flight)"); + Cmd_AddCommand_WithClientCommand ("noclip", NULL, Host_Noclip_f, "noclip mode (flight without collisions, move through walls)"); + Cmd_AddCommand_WithClientCommand ("give", NULL, Host_Give_f, "alter inventory"); Cmd_AddCommand ("map", Host_Map_f, "kick everyone off the server and start a new level"); Cmd_AddCommand ("restart", Host_Restart_f, "restart current level"); Cmd_AddCommand ("changelevel", Host_Changelevel_f, "change to another level, bringing along all connected clients"); @@ -2957,11 +2946,8 @@ void Host_InitCommands (void) Cmd_AddCommand_WithClientCommand ("color", Host_Color_f, Host_Color_f, "change your player shirt and pants colors"); Cvar_RegisterVariable (&cl_rate); Cmd_AddCommand_WithClientCommand ("rate", Host_Rate_f, Host_Rate_f, "change your network connection speed"); - if (gamemode == GAME_NEHAHRA) - { - Cvar_RegisterVariable (&cl_pmodel); - Cmd_AddCommand_WithClientCommand ("pmodel", Host_PModel_f, Host_PModel_f, "change your player model choice (Nehahra specific)"); - } + Cvar_RegisterVariable (&cl_pmodel); + Cmd_AddCommand_WithClientCommand ("pmodel", Host_PModel_f, Host_PModel_f, "(Nehahra-only) change your player model choice"); // BLACK: This isnt game specific anymore (it was GAME_NEXUIZ at first) Cvar_RegisterVariable (&cl_playermodel); diff --git a/menu.c b/menu.c index 26eb371a..9644edba 100644 --- a/menu.c +++ b/menu.c @@ -362,8 +362,35 @@ void M_Menu_Main_f (void) { const char *s; s = "gfx/mainmenu"; + if (gamemode == GAME_NEHAHRA) { + if (FS_FileExists("maps/neh1m4.bsp")) + { + if (FS_FileExists("hearing.dem")) + { + Con_DPrint("Main menu: Nehahra movie and game detected.\n"); + NehGameType = TYPE_BOTH; + } + else + { + Con_DPrint("Nehahra game detected.\n"); + NehGameType = TYPE_GAME; + } + } + else + { + if (FS_FileExists("hearing.dem")) + { + Con_DPrint("Nehahra movie detected.\n"); + NehGameType = TYPE_DEMO; + } + else + { + Con_DPrint("Nehahra not found.\n"); + NehGameType = TYPE_GAME; // could just complain, but... + } + } if (NehGameType == TYPE_DEMO) MAIN_ITEMS = 4; else if (NehGameType == TYPE_GAME) @@ -2521,6 +2548,33 @@ void M_Menu_Keys_f (void) key_dest = key_menu_grabbed; m_state = m_keys; m_entersound = true; + + if (gamemode == GAME_TRANSFUSION) + { + numcommands = sizeof(transfusionbindnames) / sizeof(transfusionbindnames[0]); + bindnames = transfusionbindnames; + } + else if (gamemode == GAME_GOODVSBAD2) + { + numcommands = sizeof(goodvsbad2bindnames) / sizeof(goodvsbad2bindnames[0]); + bindnames = goodvsbad2bindnames; + } + else + { + numcommands = sizeof(quakebindnames) / sizeof(quakebindnames[0]); + bindnames = quakebindnames; + } + + // Make sure "keys_cursor" doesn't start on a section in the binding list + keys_cursor = 0; + while (bindnames[keys_cursor][0][0] == '\0') + { + keys_cursor++; + + // Only sections? There may be a problem somewhere... + if (keys_cursor >= numcommands) + Sys_Error ("M_Init: The key binding list only contains sections"); + } } #define NUMKEYS 5 @@ -3879,26 +3933,9 @@ static gameinfo_t gamelist[] = {GAME_OPENQUARTZ, &openquartzgame, &openquartzgame}, {GAME_DEFEATINDETAIL2, &defeatindetail2game, &defeatindetail2game}, {GAME_PRYDON, &prydongame, &prydongame}, - {GAME_NORMAL, NULL, NULL} // terminator }; -static gamelevels_t *lookupgameinfo(void) -{ - int i = 0; - while (gamelist[i].gameid != gamemode) - { - if (gamelist[i].notregistered == NULL) - { - i = 0; - break; - } - i++; - } - if (registered.integer) - return gamelist[i].registered; - else - return gamelist[i].notregistered; -} +static gamelevels_t *gameoptions_levels = NULL; static int startepisode; static int startlevel; @@ -3908,6 +3945,7 @@ static double m_serverInfoMessageTime; void M_Menu_GameOptions_f (void) { + int i; key_dest = key_menu; m_state = m_gameoptions; m_entersound = true; @@ -3915,6 +3953,11 @@ void M_Menu_GameOptions_f (void) maxplayers = svs.maxclients; if (maxplayers < 2) maxplayers = min(8, MAX_SCOREBOARD); + // pick game level list based on gamemode (use GAME_NORMAL if no matches) + gameoptions_levels = registered.integer ? gamelist[0].registered : gamelist[0].notregistered; + for (i = 0;i < (int)(sizeof(gamelist)/sizeof(gamelist[0]));i++) + if (gamelist[i].gameid == gamemode) + gameoptions_levels = registered.integer ? gamelist[i].registered : gamelist[i].notregistered; } @@ -3926,7 +3969,6 @@ void M_GameOptions_Draw (void) { cachepic_t *p; int x; - gamelevels_t *g; M_Background(320, 200); @@ -4050,17 +4092,15 @@ void M_GameOptions_Draw (void) M_DrawTextBox (0, 132, 38, 1); M_Print(8, 140, hostname.string); - g = lookupgameinfo(); - if (gamemode != GAME_GOODVSBAD2) { M_Print(0, 160, " Episode"); - M_Print(160, 160, g->episodes[startepisode].description); + M_Print(160, 160, gameoptions_levels->episodes[startepisode].description); } M_Print(0, 168, " Level"); - M_Print(160, 168, g->levels[g->episodes[startepisode].firstLevel + startlevel].description); - M_Print(160, 176, g->levels[g->episodes[startepisode].firstLevel + startlevel].name); + M_Print(160, 168, gameoptions_levels->levels[gameoptions_levels->episodes[startepisode].firstLevel + startlevel].description); + M_Print(160, 176, gameoptions_levels->levels[gameoptions_levels->episodes[startepisode].firstLevel + startlevel].name); // line cursor if (gameoptions_cursor == 9) @@ -4088,7 +4128,6 @@ void M_GameOptions_Draw (void) static void M_NetStart_Change (int dir) { - gamelevels_t *g; int count; switch (gameoptions_cursor) @@ -4225,12 +4264,11 @@ static void M_NetStart_Change (int dir) if (gamemode == GAME_GOODVSBAD2) break; startepisode += dir; - g = lookupgameinfo(); if (startepisode < 0) - startepisode = g->numepisodes - 1; + startepisode = gameoptions_levels->numepisodes - 1; - if (startepisode >= g->numepisodes) + if (startepisode >= gameoptions_levels->numepisodes) startepisode = 0; startlevel = 0; @@ -4238,12 +4276,11 @@ static void M_NetStart_Change (int dir) case 11: startlevel += dir; - g = lookupgameinfo(); if (startlevel < 0) - startlevel = g->episodes[startepisode].levels - 1; + startlevel = gameoptions_levels->episodes[startepisode].levels - 1; - if (startlevel >= g->episodes[startepisode].levels) + if (startlevel >= gameoptions_levels->episodes[startepisode].levels) startlevel = 0; break; } @@ -4251,7 +4288,6 @@ static void M_NetStart_Change (int dir) static void M_GameOptions_Key (int key, int ascii) { - gamelevels_t *g; int l; char hostnamebuf[128]; @@ -4297,8 +4333,7 @@ static void M_GameOptions_Key (int key, int ascii) Cbuf_AddText ("disconnect\n"); Cbuf_AddText ( va ("maxplayers %u\n", maxplayers) ); - g = lookupgameinfo(); - Cbuf_AddText ( va ("map %s\n", g->levels[g->episodes[startepisode].firstLevel + startlevel].name) ); + Cbuf_AddText ( va ("map %s\n", gameoptions_levels->levels[gameoptions_levels->episodes[startepisode].firstLevel + startlevel].name) ); return; } @@ -4488,9 +4523,8 @@ void ModList_RebuildList(void) if (modlist_count >= MODLIST_TOTALSIZE) break; // check all dirs to see if they "appear" to be mods // reject any dirs that are part of the base game - // (such as "id1" and "hipnotic" when in GAME_HIPNOTIC mode) if (gamedirname1 && !strcasecmp(gamedirname1, list.strings[i])) continue; - if (gamedirname2 && !strcasecmp(gamedirname2, list.strings[i])) continue; + //if (gamedirname2 && !strcasecmp(gamedirname2, list.strings[i])) continue; if (FS_CheckNastyPath (list.strings[i], true)) continue; if (!FS_CheckGameDir(list.strings[i])) continue; @@ -4704,64 +4738,6 @@ void M_Init (void) Cmd_AddCommand ("menu_transfusion_episode", M_Menu_Transfusion_Episode_f, "open the transfusion episode select menu"); Cmd_AddCommand ("menu_transfusion_skill", M_Menu_Transfusion_Skill_f, "open the transfusion skill select menu"); Cmd_AddCommand ("menu_credits", M_Menu_Credits_f, "open the credits menu"); - - if (gamemode == GAME_TRANSFUSION) - { - numcommands = sizeof(transfusionbindnames) / sizeof(transfusionbindnames[0]); - bindnames = transfusionbindnames; - } - else if (gamemode == GAME_GOODVSBAD2) - { - numcommands = sizeof(goodvsbad2bindnames) / sizeof(goodvsbad2bindnames[0]); - bindnames = goodvsbad2bindnames; - } - else - { - numcommands = sizeof(quakebindnames) / sizeof(quakebindnames[0]); - bindnames = quakebindnames; - } - - // Make sure "keys_cursor" doesn't start on a section in the binding list - keys_cursor = 0; - while (bindnames[keys_cursor][0][0] == '\0') - { - keys_cursor++; - - // Only sections? There may be a problem somewhere... - if (keys_cursor >= numcommands) - Sys_Error ("M_Init: The key binding list only contains sections"); - } - - - if (gamemode == GAME_NEHAHRA) - { - if (FS_FileExists("maps/neh1m4.bsp")) - { - if (FS_FileExists("hearing.dem")) - { - Con_Print("Nehahra movie and game detected.\n"); - NehGameType = TYPE_BOTH; - } - else - { - Con_Print("Nehahra game detected.\n"); - NehGameType = TYPE_GAME; - } - } - else - { - if (FS_FileExists("hearing.dem")) - { - Con_Print("Nehahra movie detected.\n"); - NehGameType = TYPE_DEMO; - } - else - { - Con_Print("Nehahra not found.\n"); - NehGameType = TYPE_GAME; // could just complain, but... - } - } - } } void M_Draw (void) @@ -5026,10 +5002,6 @@ void M_Shutdown(void) key_dest = key_game; } -void M_Restart(void) -{ -} - //============================================================================ // Menu prog handling @@ -5199,11 +5171,6 @@ void MP_Init (void) PRVM_End; } -void MP_Restart(void) -{ - MP_Init(); -} - //============================================================================ // Menu router @@ -5215,8 +5182,6 @@ void (*MR_NewMap) (void); void MR_SetRouting(qboolean forceold) { - static qboolean m_init = FALSE, mp_init = FALSE; - // if the menu prog isnt available or forceqmenu ist set, use the old menu if(!FS_FileExists(M_PROG_FILENAME) || forceqmenu.integer || forceold) { @@ -5226,15 +5191,7 @@ void MR_SetRouting(qboolean forceold) MR_ToggleMenu = M_ToggleMenu; MR_Shutdown = M_Shutdown; MR_NewMap = M_NewMap; - - // init - if(!m_init) - { - M_Init(); - m_init = TRUE; - } - else - M_Restart(); + M_Init(); } else { @@ -5244,14 +5201,7 @@ void MR_SetRouting(qboolean forceold) MR_ToggleMenu = MP_ToggleMenu; MR_Shutdown = MP_Shutdown; MR_NewMap = MP_NewMap; - - if(!mp_init) - { - MP_Init(); - mp_init = TRUE; - } - else - MP_Restart(); + MP_Init(); } } diff --git a/r_shadow.c b/r_shadow.c index 0030b2f8..971b196a 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -743,11 +743,6 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&gl_flashblend); Cvar_RegisterVariable(&gl_ext_separatestencil); Cvar_RegisterVariable(&gl_ext_stenciltwoside); - if (gamemode == GAME_TENEBRAE) - { - Cvar_SetValue("r_shadow_gloss", 2); - Cvar_SetValue("r_shadow_bumpscale_basetexture", 4); - } R_Shadow_EditLights_Init(); Mem_ExpandableArray_NewArray(&r_shadow_worldlightsarray, r_main_mempool, sizeof(dlight_t), 128); maxshadowtriangles = 0; diff --git a/sbar.c b/sbar.c index 4de44543..28d7f604 100644 --- a/sbar.c +++ b/sbar.c @@ -401,11 +401,8 @@ void Sbar_Init (void) Cvar_RegisterVariable(&crosshair_color_alpha); Cvar_RegisterVariable(&crosshair_size); - if(gamemode == GAME_NEXUIZ) - { - Cvar_RegisterVariable(&sbar_flagstatus_right); // this cvar makes no sense in other games - Cvar_RegisterVariable(&sbar_flagstatus_pos); // this cvar makes no sense in other games - } + Cvar_RegisterVariable(&sbar_flagstatus_right); // (GAME_NEXUZI ONLY) + Cvar_RegisterVariable(&sbar_flagstatus_pos); // (GAME_NEXUIZ ONLY) R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap, NULL, NULL); } diff --git a/sv_main.c b/sv_main.c index a73bb657..68001f50 100644 --- a/sv_main.c +++ b/sv_main.c @@ -487,29 +487,26 @@ void SV_Init (void) Cvar_RegisterVariable (&temp1); // LordHavoc: Nehahra uses these to pass data around cutscene demos - if (gamemode == GAME_NEHAHRA) - { - Cvar_RegisterVariable (&nehx00); - Cvar_RegisterVariable (&nehx01); - Cvar_RegisterVariable (&nehx02); - Cvar_RegisterVariable (&nehx03); - Cvar_RegisterVariable (&nehx04); - Cvar_RegisterVariable (&nehx05); - Cvar_RegisterVariable (&nehx06); - Cvar_RegisterVariable (&nehx07); - Cvar_RegisterVariable (&nehx08); - Cvar_RegisterVariable (&nehx09); - Cvar_RegisterVariable (&nehx10); - Cvar_RegisterVariable (&nehx11); - Cvar_RegisterVariable (&nehx12); - Cvar_RegisterVariable (&nehx13); - Cvar_RegisterVariable (&nehx14); - Cvar_RegisterVariable (&nehx15); - Cvar_RegisterVariable (&nehx16); - Cvar_RegisterVariable (&nehx17); - Cvar_RegisterVariable (&nehx18); - Cvar_RegisterVariable (&nehx19); - } + Cvar_RegisterVariable (&nehx00); + Cvar_RegisterVariable (&nehx01); + Cvar_RegisterVariable (&nehx02); + Cvar_RegisterVariable (&nehx03); + Cvar_RegisterVariable (&nehx04); + Cvar_RegisterVariable (&nehx05); + Cvar_RegisterVariable (&nehx06); + Cvar_RegisterVariable (&nehx07); + Cvar_RegisterVariable (&nehx08); + Cvar_RegisterVariable (&nehx09); + Cvar_RegisterVariable (&nehx10); + Cvar_RegisterVariable (&nehx11); + Cvar_RegisterVariable (&nehx12); + Cvar_RegisterVariable (&nehx13); + Cvar_RegisterVariable (&nehx14); + Cvar_RegisterVariable (&nehx15); + Cvar_RegisterVariable (&nehx16); + Cvar_RegisterVariable (&nehx17); + Cvar_RegisterVariable (&nehx18); + Cvar_RegisterVariable (&nehx19); Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well Cvar_RegisterVariable (&sv_autodemo_perclient); @@ -518,34 +515,6 @@ void SV_Init (void) Cvar_RegisterVariable (&halflifebsp); - // any special defaults for gamemodes go here - if (gamemode == GAME_NEHAHRA) - { - // Nehahra pushable crates malfunction in some levels if this is on - Cvar_SetValueQuick (&sv_gameplayfix_upwardvelocityclearsongroundflag, 0); - // Nehahra NPC AI is confused by this feature - Cvar_SetValueQuick (&sv_gameplayfix_blowupfallenzombies, 0); - } - if (gamemode == GAME_HIPNOTIC) - { - // hipnotic mission pack has issues in their 'friendly monster' ai, which seem to attempt to attack themselves for some reason when findradius() returns non-solid entities. - Cvar_SetValueQuick (&sv_gameplayfix_blowupfallenzombies, 0); - // hipnotic mission pack has issues with bobbing water entities 'jittering' between different heights on alternate frames at the default 0.0138889 ticrate, 0.02 avoids this issue - Cvar_SetValueQuick (&sys_ticrate, 0.02); - // hipnotic mission pack has issues in their proximity mine sticking code, which causes them to bounce off. - Cvar_SetValueQuick (&sv_gameplayfix_slidemoveprojectiles, 0); - } - if (gamemode == GAME_ROGUE) - { - // rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area - Cvar_SetValueQuick (&sv_gameplayfix_findradiusdistancetobox, 0); - } - if (gamemode == GAME_NEXUIZ) - { - Cvar_SetValueQuick (&sv_gameplayfix_q2airaccelerate, 1); - Cvar_SetValueQuick (&sv_gameplayfix_stepmultipletimes, 1); - } - sv_mempool = Mem_AllocPool("server", 0, NULL); } diff --git a/vid_shared.c b/vid_shared.c index 05c5bea5..8335b14d 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -1279,6 +1279,7 @@ static void VID_CloseSystems(void) } qboolean vid_commandlinecheck = true; +extern qboolean vid_opened; void VID_Restart_f(void) { @@ -1286,6 +1287,12 @@ void VID_Restart_f(void) if (vid_commandlinecheck) return; + if (!vid_opened) + { + SCR_BeginLoadingPlaque(); + return; + } + Con_Printf("VID_Restart: changing from %s %dx%dx%dbpp%s%s, to %s %dx%dx%dbpp%s%s.\n", vid.mode.fullscreen ? "fullscreen" : "window", vid.mode.width, vid.mode.height, vid.mode.bitsperpixel, vid.mode.fullscreen && vid.mode.userefreshrate ? va("x%.2fhz", vid.mode.refreshrate) : "", vid.mode.samples > 1 ? va(" (%ix AA)", vid.mode.samples) : "", vid_fullscreen.integer ? "fullscreen" : "window", vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, vid_fullscreen.integer && vid_userefreshrate.integer ? va("x%.2fhz", vid_refreshrate.value) : "", vid_samples.integer > 1 ? va(" (%ix AA)", vid_samples.integer) : ""); @@ -1311,7 +1318,7 @@ const char *vidfallbacks[][2] = {NULL, NULL} }; -// this is only called once by Host_StartVideo +// this is only called once by Host_StartVideo and again on each FS_GameDir_f void VID_Start(void) { int i, width, height, success; @@ -1361,6 +1368,12 @@ void VID_Start(void) VID_OpenSystems(); } +void VID_Stop(void) +{ + VID_CloseSystems(); + VID_Shutdown(); +} + int VID_SortModes_Compare(const void *a_, const void *b_) { vid_mode_t *a = (vid_mode_t *) a_; diff --git a/view.c b/view.c index 6be70a6d..3066ef91 100644 --- a/view.c +++ b/view.c @@ -103,7 +103,7 @@ cvar_t chase_up = {CVAR_SAVE, "chase_up", "24", "chase cam distance from the pla cvar_t chase_active = {CVAR_SAVE, "chase_active", "0", "enables chase cam"}; cvar_t chase_overhead = {CVAR_SAVE, "chase_overhead", "0", "chase cam looks straight down if this is not zero"}; // GAME_GOODVSBAD2 -cvar_t chase_stevie = {0, "chase_stevie", "0", "chase cam view from above (used only by GoodVsBad2)"}; +cvar_t chase_stevie = {0, "chase_stevie", "0", "(GOODVSBAD2 only) chase cam view from above"}; cvar_t v_deathtilt = {0, "v_deathtilt", "1", "whether to use sideways view when dead"}; cvar_t v_deathtiltangle = {0, "v_deathtiltangle", "80", "what roll angle to use when tilting the view while dead"}; @@ -1032,8 +1032,7 @@ void V_Init (void) Cvar_RegisterVariable (&chase_active); Cvar_RegisterVariable (&chase_overhead); Cvar_RegisterVariable (&chase_pitchangle); - if (gamemode == GAME_GOODVSBAD2) - Cvar_RegisterVariable (&chase_stevie); + Cvar_RegisterVariable (&chase_stevie); Cvar_RegisterVariable (&v_deathtilt); Cvar_RegisterVariable (&v_deathtiltangle); diff --git a/zone.c b/zone.c index 7c601cf0..585c1039 100644 --- a/zone.c +++ b/zone.c @@ -844,8 +844,10 @@ void MemStats_f(void) char* Mem_strdup (mempool_t *pool, const char* s) { char* p; - size_t sz = strlen (s) + 1; - if (s == NULL) return NULL; + size_t sz; + if (s == NULL) + return NULL; + sz = strlen (s) + 1; p = (char*)Mem_Alloc (pool, sz); strlcpy (p, s, sz); return p; -- 2.39.2