/*
-Copyright (C) 1996-1997 Id Software, Inc.
-Copyright (C) 2000-2020 Ashley Rose "LadyHavoc" Hale
-Copyright (C) 2020 David "Cloudwalk" Knapp
-Copyright (C) 2020 Kristus <kristustf@gmail.com>
+Copyright (C) 2000-2021 DarkPlaces contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
*/
-#include "quakedef.h"
+#include "darkplaces.h"
+#include "com_game.h"
// Game mods
{ GAME_MOONHELM, GAME_MOONHELM, "moonhelm", "-moonhelm", "MoonHelm", "MoonHelm", "data", NULL, "mh", "moonhelm" }, // COMMANDLINEOPTION: Game: -moonhelm runs the game MoonHelm
{ GAME_VORETOURNAMENT, GAME_VORETOURNAMENT, "voretournament", "-voretournament", "Vore Tournament", "Vore_Tournament", "data", NULL, "voretournament", "voretournament" }, // COMMANDLINEOPTION: Game: -voretournament runs the multiplayer game Vore Tournament
{ GAME_DOOMBRINGER, GAME_DOOMBRINGER, "doombringer", "-doombringer", "DOOMBRINGER", "DOOMBRINGER", "dbdata", NULL, "doombringer", "doombringer" }, // COMMANDLINEOPTION: Game: -doombringer runs the game DOOMBRINGER
+{ GAME_BATTLEMETAL, GAME_NORMAL, "battlemetal", "-battlemetal", "battlemetal", "battlemetal", "metaldata", NULL, "battlemetal", "battlemetal" }, // COMMANDLINEOPTION: Game: -battlemetal runs the game battleMETAL
+{ GAME_QUAKE15, GAME_NORMAL, "quake15", "-quake15", "Quake 1.5", "Quake_1.5", "id1", "quake15", "quake15", "darkplaces" }, // COMMANDLINEOPTION: Game: -quake15 runs the Quake 1.5 or Quake Combat+ mod
};
static void COM_SetGameType(int index);
{
char name [MAX_OSPATH];
int i;
- int index = 0;
+ int index = GAME_NORMAL;
#ifdef FORCEGAME
COM_ToLowerString(FORCEGAME, name, sizeof (name));
// 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))
+ if (Sys_CheckParm (gamemode_info[i].cmdline))
index = i;
com_startupgamemode = gamemode_info[index].mode;
COM_SetGameType(index);
}
-void COM_ChangeGameTypeForGameDirs(void)
+int COM_ChangeGameTypeForGameDirs(unsigned numgamedirs, const char *gamedirs[], qbool failmissing, qbool init)
{
- int i;
- int index = -1;
+ unsigned i, gamemode_count = sizeof(gamemode_info) / sizeof(gamemode_info[0]);
+ int j, index = -1;
+ addgamedirs_t ret = GAMEDIRS_SUCCESS;
// 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++)
+ for (i = 0; i < gamemode_count; i++)
{
if (gamemode_info[i].group == com_startupgamegroup && !(gamemode_info[i].gamedirname2 && gamemode_info[i].gamedirname2[0]))
{
break;
}
}
- // now that we have a base game, see if there is a matching derivative game (two gamedirs)
- if (fs_numgamedirs)
+ if (index < 0)
+ Sys_Error("BUG: failed to find the base game!");
+
+ // See if there is a derivative game matching the startup one (two gamedirs),
+ // this prevents a Quake expansion (eg Rogue) getting switched to Quake during startup,
+ // not used when changing gamedirs later so that it's possible to change from the startup mod to the base one.
+ if (init)
{
- for (i = 0;i < (int)(sizeof (gamemode_info) / sizeof (gamemode_info[0]));i++)
+ for (i = 0; i < gamemode_count; 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))
+ if (gamemode_info[i].group == com_startupgamegroup && (gamemode_info[i].gamedirname2 && gamemode_info[i].gamedirname2[0]) && gamemode_info[i].mode == com_startupgamemode)
{
index = i;
break;
}
}
}
+
+ // See if the base game or mod can be identified by a gamedir,
+ // if more than one matches the last is used because the last gamedir is the primary.
+ for (j = numgamedirs - 1; j >= 0; --j)
+ {
+ for (i = 0; i < gamemode_count; i++)
+ {
+ if (gamemode_info[i].group == com_startupgamegroup)
+ if ((gamemode_info[i].gamedirname2 && gamemode_info[i].gamedirname2[0] && !strcasecmp(gamedirs[j], gamemode_info[i].gamedirname2))
+ || (!gamemode_info[i].gamedirname2 && !strcasecmp(gamedirs[j], gamemode_info[i].gamedirname1)))
+ {
+ index = i;
+ goto double_break;
+ }
+ }
+ }
+double_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);
+ COM_SetGameType(index);
+
+ ret = FS_SetGameDirs(numgamedirs, gamedirs, failmissing, !init);
+ if (ret == GAMEDIRS_SUCCESS)
+ {
+ Con_Printf("Game is %s using %s", gamename, fs_numgamedirs > 1 ? "gamedirs" : "gamedir");
+ for (j = 0; j < fs_numgamedirs; ++j)
+ Con_Printf(" %s%s", (strcasecmp(fs_gamedirs[j], gamedirname1) && (!gamedirname2 || strcasecmp(fs_gamedirs[j], gamedirname2))) ? "^7" : "^9", fs_gamedirs[j]);
+ Con_Printf("\n");
+
+ Con_Printf("gamename for server filtering: %s\n", gamenetworkfiltername);
+ }
+ return ret;
}
static void COM_SetGameType(int index)
{
static char gamenetworkfilternamebuffer[64];
- int i, t;
+ int t;
+
if (index < 0 || index >= (int)(sizeof (gamemode_info) / sizeof (gamemode_info[0])))
index = 0;
gamemode = gamemode_info[index].mode;
if (gamemode == com_startupgamemode)
{
- if((t = COM_CheckParm("-customgamename")) && t + 1 < sys.argc)
+ if((t = Sys_CheckParm("-customgamename")) && t + 1 < sys.argc)
gamename = gamenetworkfiltername = sys.argv[t+1];
- if((t = COM_CheckParm("-customgamenetworkfiltername")) && t + 1 < sys.argc)
+ if((t = Sys_CheckParm("-customgamenetworkfiltername")) && t + 1 < sys.argc)
gamenetworkfiltername = sys.argv[t+1];
- if((t = COM_CheckParm("-customgamedirname1")) && t + 1 < sys.argc)
+ if((t = Sys_CheckParm("-customgamedirname1")) && t + 1 < sys.argc)
gamedirname1 = sys.argv[t+1];
- if((t = COM_CheckParm("-customgamedirname2")) && t + 1 < sys.argc)
+ if((t = Sys_CheckParm("-customgamedirname2")) && t + 1 < sys.argc)
gamedirname2 = *sys.argv[t+1] ? sys.argv[t+1] : NULL;
- if((t = COM_CheckParm("-customgamescreenshotname")) && t + 1 < sys.argc)
+ if((t = Sys_CheckParm("-customgamescreenshotname")) && t + 1 < sys.argc)
gamescreenshotname = sys.argv[t+1];
- if((t = COM_CheckParm("-customgameuserdirname")) && t + 1 < sys.argc)
+ if((t = Sys_CheckParm("-customgameuserdirname")) && t + 1 < sys.argc)
gameuserdirname = sys.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");
-
if (strchr(gamenetworkfiltername, ' '))
{
char *s;
// if there are spaces in the game's network filter name it would
// cause parse errors in getservers in dpmaster, so we need to replace
// them with _ characters
- strlcpy(gamenetworkfilternamebuffer, gamenetworkfiltername, sizeof(gamenetworkfilternamebuffer));
+ dp_strlcpy(gamenetworkfilternamebuffer, gamenetworkfiltername, sizeof(gamenetworkfilternamebuffer));
while ((s = strchr(gamenetworkfilternamebuffer, ' ')) != NULL)
*s = '_';
gamenetworkfiltername = gamenetworkfilternamebuffer;
}
-
- Con_Printf("gamename for server filtering: %s\n", gamenetworkfiltername);
}