Basic Double gamedir support

Post tutorials on how to do certain tasks within game or engine code here.
Post Reply
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Basic Double gamedir support

Post by Baker »

This example is done by modifying FitzQuake but doing so is virtually identical in GLQuake/WinQuake (if it isn't exactly identical --- I didn't check)

Open common.c and find this:

Code: Select all

	i = COM_CheckParm ("-game");
	if (i && i < com_argc-1)
	{
		com_modified = true;
		COM_AddGameDirectory (va("%s/%s", basedir, com_argv[i+1]));
	}
And add this immediately after:

Code: Select all

// Baker: begin "game2" modification

	i = COM_CheckParm ("-game2");
	if (i && i < com_argc-1)
	{
		com_modified = true;
		COM_AddGameDirectory (va("%s/%s", basedir, com_argv[i+1]));
	}

// Baker: end "game2" modification
Commentary on the functionality:
If you modify, say, FitzQuake using the above, start the engine with this command as an example:

// Note: you need to have maps or models or such in both gamedirs for this to be interesting
c:\quake\fitzquake085.exe -game mymod -game2 mymod2

Now here is how multiple gamedir works.

Folder priority is this:

Content chain of priority: game2 > game > id1

Quake's file system will first search for data in -game2 (mymod2 folder) and then fall back to -game (mymod folder) and then to id1 folder.

It will not run multiple progs.dat at the same time like some newcomers would hope. Like "-game ctf -game2 slide" would not suddenly give you Capture The Flag with hoverboards (it would run the progs.dat in -game2, in this case "Slide" and you'd be playing the Slide mod with the CTF folder models and maps available where not superceded by anything with the same filename in the Slide folder).

Anyway, as far as file priority goes -game2 has priority over -game.

So the progs.dat in -game2 would be used over a progs.dat in -game, which in turn has priority over a progs.dat in id1.

One thing this can be used for is doing an additive mod where you are extending some other mod while keeping the content separate. The Quoth mod uses this philosophy where a mapper can make their own stuff and put in "my_mapmod_folder" while falling back to the extended Quoth content.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
metlslime
Posts: 316
Joined: Tue Feb 05, 2008 11:03 pm

Post by metlslime »

two notes: first, you may need to increase MAX_HANDLES (a handle is needed for each pak file and another one for the lose files in a gamedir) -- with this feature added i think you will need 33 handles. (might have to check the math on that)

second, i think the right way to do this would be to add darkplaces style multi-gamedir support, where a single "gamedir" command (equivalent to "game" in fitzquake) takes multiple arguments:

Code: Select all

>game mymod warp quoth
In this example you'd be loading mymod, which needs warpspasm, which needs quoth. And here it is at the command line:

Code: Select all

quake.exe -game mymod warp quoth -window -etc -etc
NOTE: we'd need to check darkplaces implementation to see whether the "top" directory goes first or last in the list.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

metlslime wrote:second, i think the right way to do this would be to add darkplaces style multi-gamedir support, where a single "gamedir" command (equivalent to "game" in fitzquake) takes multiple arguments:

Code: Select all

>game mymod warp quoth
In this example you'd be loading mymod, which needs warpspasm, which needs quoth. And here it is at the command line:

Code: Select all

quake.exe -game mymod warp quoth -window -etc -etc
Fine! ;)

Slight modification of LordHavoc's code:

Code: Select all

	// -game <gamedir>
	// Adds basedir/gamedir as an override game
	// LordHavoc: now supports multiple -game directories
	for (i = 1;i < com_argc;i++)
	{
		if (!com_argv[i])
			continue;
		if (!strcmp (com_argv[i], "-game") && i < com_argc-1)
		{
			i++;
			com_modified = true;
			COM_AddGameDirectory (va("%s/%s", basedir, com_argv[i]));
		}
	}
I don't recall how FitzQuake stores the game name in a variable somewhere when, for instance, the "game" command is used with no arguments. But that'd need to happen.

DarkPlaces from the code above obviously, the final gamedir when multiple gamedirs are used has top priority

So "-game quoth warp mymod" ... mymod is priority #1, warp #2 and quoth #3

Modifying the existing Host_Game_f in FitzQuake would be a fair bit more work.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

This code in FitzQuake that controls the "game" command would need a bit of modification:

Code: Select all

/*
==================
Host_Game_f
==================
*/
void Host_Game_f (void)
{
	int i;
	searchpath_t *search = com_searchpaths;
	pack_t *pak;
	char   pakfile[MAX_OSPATH]; //FIXME: it's confusing to use this string for two different things

	if (Cmd_Argc() > 1)
	{

		if (!registered.value) //disable command for shareware quake
		{
			Con_Printf("You must have the registered version to use modified games\n");
			return;
		}

		if (strstr(Cmd_Argv(1), ".."))
		{
			Con_Printf ("Relative pathnames are not allowed.\n");
			return;
		}

		strcpy (pakfile, va("%s/%s", host_parms.basedir, Cmd_Argv(1)));
		if (!Q_strcasecmp(pakfile, com_gamedir)) //no change
		{
			Con_Printf("\"game\" is already \"%s\"\n", COM_SkipPath(com_gamedir));
			return;
		}

		com_modified = true;

		//Kill the server
		CL_Disconnect ();
		Host_ShutdownServer(true);

		//Write config file
		Host_WriteConfiguration ();

		//Kill the extra game if it is loaded
		if (NumGames(com_searchpaths) > 1 + com_nummissionpacks)
			KillGameDir(com_searchpaths);

		strcpy (com_gamedir, pakfile);

		if (Q_strcasecmp(Cmd_Argv(1), GAMENAME)) //game is not id1
		{
			search = Z_Malloc(sizeof(searchpath_t));
			strcpy (search->filename, pakfile);
			search->next = com_searchpaths;
			com_searchpaths = search;

			//Load the paks if any are found:
			for (i = 0; ; i++)
			{
				sprintf (pakfile, "%s/pak%i.pak", com_gamedir, i);
				pak = COM_LoadPackFile (pakfile);
				if (!pak)
				break;
				search = Z_Malloc(sizeof(searchpath_t));
				search->pack = pak;
				search->next = com_searchpaths;
				com_searchpaths = search;
			}
		}

		//clear out and reload appropriate data
		Cache_Flush ();
		if (!isDedicated)
		{
			TexMgr_NewGame ();
			Draw_NewGame ();
			R_NewGame ();
		}
		ExtraMaps_NewGame ();
		//Cbuf_InsertText ("exec quake.rc\n");

		Con_Printf("\"game\" changed to \"%s\"\n", COM_SkipPath(com_gamedir));
	}
	else //Diplay the current gamedir
		Con_Printf("\"game\" is \"%s\"\n", COM_SkipPath(com_gamedir));
}
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Post by frag.machine »

With not to use a cvar, allowing one to set a DOS/Unix-like search path via console (or even thru a nice menu option) and then parse its contents at the game start/restart ?

Code: Select all

cvar_t gamepath {"gamepath", "id1", false};
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

Any good system should be able to utilize both the command line and the "command" or cvar method of setting a gamedir.

A little bit of sweat and planning to make something "right" is the way to go. :D
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Post Reply