]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - com_game.c
CONTRIBUTING: Fix typos
[xonotic/darkplaces.git] / com_game.c
index a40f5c401353e6227d642c69c9c612bac708672c..74ca8552af296c973a97bceb5660804141cbce64 100644 (file)
@@ -1,8 +1,5 @@
 /*
-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
@@ -21,7 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 */
 
-#include "quakedef.h"
+#include "darkplaces.h"
+#include "com_game.h"
 
 // Game mods
 
@@ -87,6 +85,8 @@ static const gamemode_info_t gamemode_info [GAME_COUNT] =
 { 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);
@@ -94,7 +94,7 @@ void COM_InitGameType (void)
 {
        char name [MAX_OSPATH];
        int i;
-       int index = 0;
+       int index = GAME_NORMAL;
 
 #ifdef FORCEGAME
        COM_ToLowerString(FORCEGAME, name, sizeof (name));
@@ -109,7 +109,7 @@ void COM_InitGameType (void)
 
        // 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;
@@ -117,13 +117,15 @@ void COM_InitGameType (void)
        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]))
                {
@@ -131,27 +133,62 @@ void COM_ChangeGameTypeForGameDirs(void)
                        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;
@@ -164,43 +201,29 @@ static void COM_SetGameType(int index)
 
        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);
 }