summaryrefslogtreecommitdiff
path: root/src/doom
diff options
context:
space:
mode:
Diffstat (limited to 'src/doom')
-rw-r--r--src/doom/d_main.c191
-rw-r--r--src/doom/d_net.c770
-rw-r--r--src/doom/d_net.h1
-rw-r--r--src/doom/doomstat.h3
-rw-r--r--src/doom/dstrings.h9
-rw-r--r--src/doom/g_game.c33
-rw-r--r--src/doom/m_menu.c10
-rw-r--r--src/doom/p_map.c2
-rw-r--r--src/doom/p_setup.c12
-rw-r--r--src/doom/p_spec.c9
-rw-r--r--src/doom/r_data.c20
11 files changed, 699 insertions, 361 deletions
diff --git a/src/doom/d_main.c b/src/doom/d_main.c
index f3a4b037..2f116f1e 100644
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -122,8 +122,6 @@ int startmap;
boolean autostart;
int startloadgame;
-FILE* debugfile;
-
boolean advancedemo;
// Store demo, do not accept any inputs
@@ -424,14 +422,6 @@ void D_DoomLoop (void)
if (demorecording)
G_BeginRecording ();
- if (M_CheckParm ("-debugfile"))
- {
- char filename[20];
- sprintf (filename,"debug%i.txt",consoleplayer);
- printf ("debug output to: %s\n",filename);
- debugfile = fopen (filename,"w");
- }
-
TryRunTics();
I_SetWindowTitle(gamedescription);
@@ -457,9 +447,12 @@ void D_DoomLoop (void)
// process one or more tics
if (singletics)
{
+ static ticcmd_t cmds[MAXPLAYERS];
+
I_StartTic ();
D_ProcessEvents ();
- G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
+ netcmds = cmds;
+ G_BuildTiccmd(&cmds[consoleplayer]);
if (advancedemo)
D_DoAdvanceDemo ();
M_Ticker ();
@@ -533,7 +526,13 @@ void D_DoAdvanceDemo (void)
paused = false;
gameaction = ga_nothing;
- if (gamemode == retail && gameversion != exe_chex)
+ // The Ultimate Doom executable changed the demo sequence to add
+ // a DEMO4 demo. Final Doom was based on Ultimate, so also
+ // includes this change; however, the Final Doom IWADs do not
+ // include a DEMO4 lump, so the game bombs out with an error
+ // when it reaches this point in the demo sequence.
+
+ if (gameversion == exe_ultimate || gameversion == exe_final)
demosequence = (demosequence+1)%7;
else
demosequence = (demosequence+1)%6;
@@ -608,8 +607,12 @@ void D_StartTitle (void)
// These are from the original source: some of them are perhaps
// not used in any dehacked patches
-static char *banners[] =
+static char *banners[] =
{
+ // doom2.wad
+ " "
+ "DOOM 2: Hell on Earth v%i.%i"
+ " ",
// doom1.wad
" "
"DOOM Shareware Startup v%i.%i"
@@ -626,10 +629,6 @@ static char *banners[] =
" "
"The Ultimate DOOM Startup v%i.%i"
" ",
- // doom2.wad
- " "
- "DOOM 2: Hell on Earth v%i.%i"
- " ",
// tnt.wad
" "
"DOOM 2: TNT - Evilution v%i.%i"
@@ -830,6 +829,18 @@ static boolean CheckChex(char *iwadname)
chex_iwadname));
}
+// Check if the IWAD file is the Hacx IWAD.
+// Returns true if this is hacx.wad.
+
+static boolean CheckHacx(char *iwadname)
+{
+ char *hacx_iwadname = "hacx.wad";
+
+ return (strlen(iwadname) > strlen(hacx_iwadname)
+ && !strcasecmp(iwadname + strlen(iwadname) - strlen(hacx_iwadname),
+ hacx_iwadname));
+}
+
// print title for every printed line
char title[128];
@@ -900,6 +911,7 @@ static struct
GameVersion_t version;
} gameversions[] = {
{"Doom 1.9", "1.9", exe_doom_1_9},
+ {"Hacx", "hacx", exe_hacx},
{"Ultimate Doom", "ultimate", exe_ultimate},
{"Final Doom", "final", exe_final},
{"Chex Quest", "chex", exe_chex},
@@ -921,9 +933,9 @@ static void InitGameVersion(void)
// "ultimate" and "final".
//
- p = M_CheckParm("-gameversion");
+ p = M_CheckParmWithArgs("-gameversion", 1);
- if (p > 0)
+ if (p)
{
for (i=0; gameversions[i].description != NULL; ++i)
{
@@ -957,6 +969,12 @@ static void InitGameVersion(void)
gameversion = exe_chex;
}
+ else if (CheckHacx(iwadfile))
+ {
+ // hacx exe: identified by iwad filename
+
+ gameversion = exe_hacx;
+ }
else if (gamemode == shareware || gamemode == registered)
{
// original
@@ -1057,6 +1075,20 @@ static void D_Endoom(void)
I_Endoom(endoom);
}
+static void LoadHacxDeh(void)
+{
+ // If this is the HACX IWAD, we need to load the DEHACKED lump.
+
+ if (gameversion == exe_hacx)
+ {
+ if (!DEH_LoadLumpByName("DEHACKED"))
+ {
+ I_Error("DEHACKED lump not found. Please check that this is the "
+ "Hacx v1.2 IWAD.");
+ }
+ }
+}
+
//
// D_DoomMain
//
@@ -1094,6 +1126,21 @@ void D_DoomMain (void)
}
//!
+ // @category net
+ //
+ // Query the Internet master server for a global list of active
+ // servers.
+ //
+
+ if (M_CheckParm("-search"))
+ {
+ printf("\nSearching for servers on Internet ...\n");
+ p = NET_MasterQuery(NET_QueryPrintCallback, NULL);
+ printf("\n%i server(s) found.\n", p);
+ exit(0);
+ }
+
+ //!
// @arg <address>
// @category net
//
@@ -1101,11 +1148,12 @@ void D_DoomMain (void)
// address.
//
- p = M_CheckParm("-query");
+ p = M_CheckParmWithArgs("-query", 1);
- if (p > 0)
+ if (p)
{
NET_QueryAddress(myargv[p+1]);
+ exit(0);
}
//!
@@ -1114,8 +1162,13 @@ void D_DoomMain (void)
// Search the local LAN for running servers.
//
- if (M_CheckParm("-search"))
- NET_LANQuery();
+ if (M_CheckParm("-localsearch"))
+ {
+ printf("\nSearching for servers on local LAN ...\n");
+ p = NET_LANQuery(NET_QueryPrintCallback, NULL);
+ printf("\n%i server(s) found.\n", p);
+ exit(0);
+ }
#endif
@@ -1265,40 +1318,32 @@ void D_DoomMain (void)
D_AddFile(iwadfile);
modifiedgame = W_ParseCommandLine();
- // add any files specified on the command line with -file wadfile
- // to the wad list
+ //!
+ // @arg <files>
+ // @vanilla
//
- // convenience hack to allow -wart e m to add a wad file
- // prepend a tilde to the filename so wadfile will be reloadable
- p = M_CheckParm ("-wart");
+ // Load the specified PWAD files.
+ //
+
+ p = M_CheckParmWithArgs("-file", 1);
if (p)
{
- myargv[p][4] = 'p'; // big hack, change to -warp
+ // the parms after p are wadfile/lump names,
+ // until end of parms or another - preceded parm
+ modifiedgame = true; // homebrew levels
+ while (++p != myargc && myargv[p][0] != '-')
+ {
+ char *filename;
- // Map name handling.
- switch (gamemode )
- {
- case shareware:
- case retail:
- case registered:
- sprintf (file,"~"DEVMAPS"E%cM%c.wad",
- myargv[p+1][0], myargv[p+2][0]);
- printf("Warping to Episode %s, Map %s.\n",
- myargv[p+1],myargv[p+2]);
- break;
-
- case commercial:
- default:
- p = atoi (myargv[p+1]);
- if (p<10)
- sprintf (file,"~"DEVMAPS"cdata/map0%i.wad", p);
- else
- sprintf (file,"~"DEVMAPS"cdata/map%i.wad", p);
- break;
- }
- D_AddFile (file);
+ filename = D_TryFindWADByName(myargv[p]);
+
+ D_AddFile(filename);
+ }
}
+ // Debug:
+// W_PrintDirectory();
+
//!
// @arg <demo>
// @category demo
@@ -1307,7 +1352,7 @@ void D_DoomMain (void)
// Play back the demo named demo.lmp.
//
- p = M_CheckParm ("-playdemo");
+ p = M_CheckParmWithArgs ("-playdemo", 1);
if (!p)
{
@@ -1319,11 +1364,11 @@ void D_DoomMain (void)
// Play back the demo named demo.lmp, determining the framerate
// of the screen.
//
- p = M_CheckParm ("-timedemo");
+ p = M_CheckParmWithArgs("-timedemo", 1);
}
- if (p && p < myargc-1)
+ if (p)
{
if (!strcasecmp(myargv[p+1] + strlen(myargv[p+1]) - 4, ".lmp"))
{
@@ -1362,6 +1407,7 @@ void D_DoomMain (void)
D_IdentifyVersion();
InitGameVersion();
LoadChexDeh();
+ LoadHacxDeh();
D_SetGameDescription();
SetSaveGameDir(iwadfile);
@@ -1404,9 +1450,9 @@ void D_DoomMain (void)
// 0 disables all monsters.
//
- p = M_CheckParm ("-skill");
+ p = M_CheckParmWithArgs("-skill", 1);
- if (p && p < myargc-1)
+ if (p)
{
startskill = myargv[p+1][0]-'1';
autostart = true;
@@ -1419,9 +1465,9 @@ void D_DoomMain (void)
// Start playing on episode n (1-4)
//
- p = M_CheckParm ("-episode");
+ p = M_CheckParmWithArgs("-episode", 1);
- if (p && p < myargc-1)
+ if (p)
{
startepisode = myargv[p+1][0]-'0';
startmap = 1;
@@ -1438,12 +1484,11 @@ void D_DoomMain (void)
// For multiplayer games: exit each level after n minutes.
//
- p = M_CheckParm ("-timer");
+ p = M_CheckParmWithArgs("-timer", 1);
- if (p && p < myargc-1 && deathmatch)
+ if (p)
{
timelimit = atoi(myargv[p+1]);
- printf("timer: %i\n", timelimit);
}
//!
@@ -1455,10 +1500,8 @@ void D_DoomMain (void)
p = M_CheckParm ("-avg");
- if (p && p < myargc-1 && deathmatch)
+ if (p)
{
- DEH_printf("Austin Virtual Gaming: Levels will end "
- "after 20 minutes\n");
timelimit = 20;
}
@@ -1470,9 +1513,9 @@ void D_DoomMain (void)
// (Doom 2)
//
- p = M_CheckParm ("-warp");
+ p = M_CheckParmWithArgs("-warp", 1);
- if (p && p < myargc-1)
+ if (p)
{
if (gamemode == commercial)
startmap = atoi (myargv[p+1]);
@@ -1516,9 +1559,9 @@ void D_DoomMain (void)
// Load the game in slot s.
//
- p = M_CheckParm ("-loadgame");
+ p = M_CheckParmWithArgs("-loadgame", 1);
- if (p && p < myargc-1)
+ if (p)
{
startloadgame = atoi(myargv[p+1]);
}
@@ -1588,24 +1631,24 @@ void D_DoomMain (void)
// Record a demo named x.lmp.
//
- p = M_CheckParm ("-record");
+ p = M_CheckParmWithArgs("-record", 1);
- if (p && p < myargc-1)
+ if (p)
{
G_RecordDemo (myargv[p+1]);
autostart = true;
}
- p = M_CheckParm ("-playdemo");
- if (p && p < myargc-1)
+ p = M_CheckParmWithArgs("-playdemo", 1);
+ if (p)
{
singledemo = true; // quit after one demo
G_DeferedPlayDemo (demolumpname);
D_DoomLoop (); // never returns
}
- p = M_CheckParm ("-timedemo");
- if (p && p < myargc-1)
+ p = M_CheckParmWithArgs("-timedemo", 1);
+ if (p)
{
G_TimeDemo (demolumpname);
D_DoomLoop (); // never returns
diff --git a/src/doom/d_net.c b/src/doom/d_net.c
index 464922d4..dd1ec563 100644
--- a/src/doom/d_net.c
+++ b/src/doom/d_net.c
@@ -25,7 +25,7 @@
//
//-----------------------------------------------------------------------------
-
+#include <stdlib.h>
#include "doomfeatures.h"
@@ -49,26 +49,34 @@
#include "net_sdl.h"
#include "net_loop.h"
+// The complete set of data for a particular tic.
+
+typedef struct
+{
+ ticcmd_t cmds[MAXPLAYERS];
+ boolean ingame[MAXPLAYERS];
+} ticcmd_set_t;
//
// NETWORKING
//
// gametic is the tic about to (or currently being) run
-// maketic is the tick that hasn't had control made for it yet
-// nettics[] has the maketics for all players
+// maketic is the tic that hasn't had control made for it yet
+// recvtic is the latest tic received from the server.
//
-// a gametic cannot be run until nettics[] > gametic for all players
+// a gametic cannot be run until ticcmds are received for it
+// from all players.
//
-ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
-int nettics[MAXPLAYERS];
+ticcmd_set_t ticdata[BACKUPTICS];
+ticcmd_t *netcmds;
int maketic;
+int recvtic;
// Used for original sync code.
-int lastnettic;
-int skiptics = 0;
+static int skiptics = 0;
// Reduce the bandwidth needed by sampling game input less and transmitting
// less. If ticdup is 2, sample half normal, 3 = one third normal, etc.
@@ -85,11 +93,7 @@ fixed_t offsetms;
// Use new client syncronisation code
-boolean net_cl_new_sync = true;
-
-// Connected but not participating in the game (observer)
-
-boolean drone = false;
+boolean new_sync = true;
// 35 fps clock adjusted by offsetms milliseconds
@@ -99,7 +103,7 @@ static int GetAdjustedTime(void)
time_ms = I_GetTimeMS();
- if (net_cl_new_sync)
+ if (new_sync)
{
// Use the adjustments from net_client.c only if we are
// using the new sync mode.
@@ -177,7 +181,7 @@ void NetUpdate (void)
continue;
}
- if (net_cl_new_sync)
+ if (new_sync)
{
// If playing single player, do not allow tics to buffer
// up very far
@@ -200,20 +204,95 @@ void NetUpdate (void)
G_BuildTiccmd(&cmd);
#ifdef FEATURE_MULTIPLAYER
-
- if (netgame && !demoplayback)
+
+ if (net_client_connected)
{
NET_CL_SendTiccmd(&cmd, maketic);
}
#endif
- netcmds[consoleplayer][maketic % BACKUPTICS] = cmd;
+ ticdata[maketic % BACKUPTICS].cmds[consoleplayer] = cmd;
+ ticdata[maketic % BACKUPTICS].ingame[consoleplayer] = true;
++maketic;
- nettics[consoleplayer] = maketic;
}
}
+// Called when a player leaves the game
+
+static void D_PlayerQuitGame(player_t *player)
+{
+ static char exitmsg[80];
+ unsigned int player_num;
+
+ player_num = player - players;
+
+ // Do this the same way as Vanilla Doom does, to allow dehacked
+ // replacements of this message
+
+ strncpy(exitmsg, DEH_String("Player 1 left the game"), sizeof(exitmsg));
+ exitmsg[sizeof(exitmsg) - 1] = '\0';
+
+ exitmsg[7] += player_num;
+
+ playeringame[player_num] = false;
+ players[consoleplayer].message = exitmsg;
+
+ // TODO: check if it is sensible to do this:
+
+ if (demorecording)
+ {
+ G_CheckDemoStatus ();
+ }
+}
+
+static void D_Disconnected(void)
+{
+ // In drone mode, the game cannot continue once disconnected.
+
+ if (drone)
+ {
+ I_Error("Disconnected from server in drone mode.");
+ }
+
+ // disconnected from server
+
+ printf("Disconnected from server.\n");
+}
+
+//
+// Invoked by the network engine when a complete set of ticcmds is
+// available.
+//
+
+void D_ReceiveTic(ticcmd_t *ticcmds, boolean *players_mask)
+{
+ int i;
+
+ // Disconnected from server?
+
+ if (ticcmds == NULL && players_mask == NULL)
+ {
+ D_Disconnected();
+ return;
+ }
+
+ for (i = 0; i < MAXPLAYERS; ++i)
+ {
+ if (!drone && i == consoleplayer)
+ {
+ // This is us. Don't overwrite it.
+ }
+ else
+ {
+ ticdata[recvtic % BACKUPTICS].cmds[i] = ticcmds[i];
+ ticdata[recvtic % BACKUPTICS].ingame[i] = players_mask[i];
+ }
+ }
+
+ ++recvtic;
+}
+
//
// Start game loop
//
@@ -225,169 +304,340 @@ void D_StartGameLoop(void)
lasttime = GetAdjustedTime() / ticdup;
}
+// Load game settings from the specified structure and
+// set global variables.
-//
-// D_CheckNetGame
-// Works out player numbers among the net participants
-//
-extern int viewangleoffset;
+static void LoadGameSettings(net_gamesettings_t *settings)
+{
+ unsigned int i;
+
+ deathmatch = settings->deathmatch;
+ ticdup = settings->ticdup;
+ extratics = settings->extratics;
+ startepisode = settings->episode;
+ startmap = settings->map;
+ startskill = settings->skill;
+ startloadgame = settings->loadgame;
+ lowres_turn = settings->lowres_turn;
+ nomonsters = settings->nomonsters;
+ fastparm = settings->fast_monsters;
+ respawnparm = settings->respawn_monsters;
+ timelimit = settings->timelimit;
+
+ if (lowres_turn)
+ {
+ printf("NOTE: Turning resolution is reduced; this is probably "
+ "because there is a client recording a Vanilla demo.\n");
+ }
-void D_CheckNetGame (void)
+ new_sync = settings->new_sync;
+
+ if (new_sync == false)
+ {
+ printf("Syncing netgames like Vanilla Doom.\n");
+ }
+
+ if (!drone)
+ {
+ consoleplayer = settings->consoleplayer;
+ }
+ else
+ {
+ consoleplayer = 0;
+ }
+
+ for (i=0; i<MAXPLAYERS; ++i)
+ {
+ playeringame[i] = i < settings->num_players;
+ }
+}
+
+// Save the game settings from global variables to the specified
+// game settings structure.
+
+static void SaveGameSettings(net_gamesettings_t *settings,
+ net_connect_data_t *connect_data)
{
int i;
- int num_players;
- // Call D_QuitNetGame on exit
+ // Fill in game settings structure with appropriate parameters
+ // for the new game
+
+ settings->deathmatch = deathmatch;
+ settings->episode = startepisode;
+ settings->map = startmap;
+ settings->skill = startskill;
+ settings->loadgame = startloadgame;
+ settings->gameversion = gameversion;
+ settings->nomonsters = nomonsters;
+ settings->fast_monsters = fastparm;
+ settings->respawn_monsters = respawnparm;
+ settings->timelimit = timelimit;
+
+ settings->lowres_turn = M_CheckParm("-record") > 0
+ && M_CheckParm("-longtics") == 0;
+
+ //!
+ // @category net
+ //
+ // Use original game sync code.
+ //
+
+ if (M_CheckParm("-oldsync") > 0)
+ settings->new_sync = 0;
+ else
+ settings->new_sync = 1;
+
+ //!
+ // @category net
+ // @arg <n>
+ //
+ // Send n extra tics in every packet as insurance against dropped
+ // packets.
+ //
+
+ i = M_CheckParmWithArgs("-extratics", 1);
+
+ if (i > 0)
+ settings->extratics = atoi(myargv[i+1]);
+ else
+ settings->extratics = 1;
- I_AtExit(D_QuitNetGame, true);
+ //!
+ // @category net
+ // @arg <n>
+ //
+ // Reduce the resolution of the game by a factor of n, reducing
+ // the amount of network bandwidth needed.
+ //
+
+ i = M_CheckParmWithArgs("-dup", 1);
+
+ if (i > 0)
+ settings->ticdup = atoi(myargv[i+1]);
+ else
+ settings->ticdup = 1;
+
+ //
+ // Connect data
+ //
+
+ // Game type fields:
+
+ connect_data->gamemode = gamemode;
+ connect_data->gamemission = gamemission;
+ // Drone mode?
+
+ connect_data->drone = M_CheckParm("-drone") > 0;
+
+ // Are we recording a demo? Possibly set lowres turn mode
+
+ connect_data->lowres_turn = settings->lowres_turn;
+}
+
+void D_InitSinglePlayerGame(net_gamesettings_t *settings)
+{
// default values for single player
- consoleplayer = 0;
+ settings->consoleplayer = 0;
+ settings->num_players = 1;
+
netgame = false;
- ticdup = 1;
- extratics = 1;
- lowres_turn = false;
- offsetms = 0;
-
- for (i=0; i<MAXPLAYERS; i++)
+
+ //!
+ // @category net
+ //
+ // Start the game playing as though in a netgame with a single
+ // player. This can also be used to play back single player netgame
+ // demos.
+ //
+
+ if (M_CheckParm("-solo-net") > 0)
{
- playeringame[i] = false;
- nettics[i] = 0;
+ netgame = true;
}
+}
+
+boolean D_InitNetGame(net_connect_data_t *connect_data,
+ net_gamesettings_t *settings)
+{
+ net_addr_t *addr = NULL;
+ int i;
- playeringame[0] = true;
#ifdef FEATURE_MULTIPLAYER
+ //!
+ // @category net
+ //
+ // Start a multiplayer server, listening for connections.
+ //
+
+ if (M_CheckParm("-server") > 0)
{
- net_addr_t *addr = NULL;
+ NET_SV_Init();
+ NET_SV_AddModule(&net_loop_server_module);
+ NET_SV_AddModule(&net_sdl_module);
+ NET_SV_RegisterWithMaster();
- //!
+ net_loop_client_module.InitClient();
+ addr = net_loop_client_module.ResolveAddress(NULL);
+ }
+ else
+ {
+ //!
// @category net
//
- // Start a multiplayer server, listening for connections.
+ // Automatically search the local LAN for a multiplayer
+ // server and join it.
//
- if (M_CheckParm("-server") > 0)
+ i = M_CheckParm("-autojoin");
+
+ if (i > 0)
{
- NET_SV_Init();
- NET_SV_AddModule(&net_loop_server_module);
- NET_SV_AddModule(&net_sdl_module);
+ addr = NET_FindLANServer();
- net_loop_client_module.InitClient();
- addr = net_loop_client_module.ResolveAddress(NULL);
+ if (addr == NULL)
+ {
+ I_Error("No server found on local LAN");
+ }
}
- else
- {
- //!
- // @category net
- //
- // Automatically search the local LAN for a multiplayer
- // server and join it.
- //
- i = M_CheckParm("-autojoin");
+ //!
+ // @arg <address>
+ // @category net
+ //
+ // Connect to a multiplayer server running on the given
+ // address.
+ //
+
+ i = M_CheckParmWithArgs("-connect", 1);
- if (i > 0)
- {
- addr = NET_FindLANServer();
+ if (i > 0)
+ {
+ net_sdl_module.InitClient();
+ addr = net_sdl_module.ResolveAddress(myargv[i+1]);
- if (addr == NULL)
- {
- I_Error("No server found on local LAN");
- }
+ if (addr == NULL)
+ {
+ I_Error("Unable to resolve '%s'\n", myargv[i+1]);
}
+ }
+ }
- //!
- // @arg <address>
- // @category net
- //
- // Connect to a multiplayer server running on the given
- // address.
- //
-
- i = M_CheckParm("-connect");
-
- if (i > 0)
- {
- net_sdl_module.InitClient();
- addr = net_sdl_module.ResolveAddress(myargv[i+1]);
+ if (addr != NULL)
+ {
+ if (M_CheckParm("-drone") > 0)
+ {
+ connect_data->drone = true;
+ }
- if (addr == NULL)
- {
- I_Error("Unable to resolve '%s'\n", myargv[i+1]);
- }
- }
+ //!
+ // @category net
+ //
+ // Run as the left screen in three screen mode.
+ //
+
+ if (M_CheckParm("-left") > 0)
+ {
+ viewangleoffset = ANG90;
+ connect_data->drone = true;
}
- if (addr != NULL)
+ //!
+ // @category net
+ //
+ // Run as the right screen in three screen mode.
+ //
+
+ if (M_CheckParm("-right") > 0)
{
- if (M_CheckParm("-drone") > 0)
- {
- drone = true;
- }
+ viewangleoffset = ANG270;
+ connect_data->drone = true;
+ }
- //!
- // @category net
- //
- // Run as the left screen in three screen mode.
- //
+ if (!NET_CL_Connect(addr, connect_data))
+ {
+ I_Error("D_CheckNetGame: Failed to connect to %s\n",
+ NET_AddrToString(addr));
+ }
- if (M_CheckParm("-left") > 0)
- {
- viewangleoffset = ANG90;
- drone = true;
- }
+ printf("D_CheckNetGame: Connected to %s\n", NET_AddrToString(addr));
- //!
- // @category net
- //
- // Run as the right screen in three screen mode.
- //
+ // Wait for game start message received from server.
- if (M_CheckParm("-right") > 0)
- {
- viewangleoffset = ANG270;
- drone = true;
- }
+ NET_WaitForStart(settings);
- if (!NET_CL_Connect(addr))
- {
- I_Error("D_CheckNetGame: Failed to connect to %s\n",
- NET_AddrToString(addr));
- }
+ // Read the game settings that were received.
- printf("D_CheckNetGame: Connected to %s\n", NET_AddrToString(addr));
+ NET_CL_GetSettings(settings);
- NET_WaitForStart();
- }
+ return true;
}
#endif
- num_players = 0;
+ return false;
+}
+
+//
+// D_CheckNetGame
+// Works out player numbers among the net participants
+//
+extern int viewangleoffset;
+
+void D_CheckNetGame (void)
+{
+ net_connect_data_t connect_data;
+ net_gamesettings_t settings;
- for (i=0; i<MAXPLAYERS; ++i)
+ offsetms = 0;
+ recvtic = 0;
+
+ // Call D_QuitNetGame on exit
+
+ I_AtExit(D_QuitNetGame, true);
+
+ SaveGameSettings(&settings, &connect_data);
+
+ if (D_InitNetGame(&connect_data, &settings))
{
- if (playeringame[i])
- ++num_players;
+ netgame = true;
+ autostart = true;
}
+ else
+ {
+ D_InitSinglePlayerGame(&settings);
+ }
+
+ LoadGameSettings(&settings);
DEH_printf("startskill %i deathmatch: %i startmap: %i startepisode: %i\n",
startskill, deathmatch, startmap, startepisode);
DEH_printf("player %i of %i (%i nodes)\n",
- consoleplayer+1, num_players, num_players);
+ consoleplayer+1, settings.num_players, settings.num_players);
// Show players here; the server might have specified a time limit
- if (timelimit > 0)
+ if (timelimit > 0 && deathmatch)
{
- DEH_printf("Levels will end after %d minute", timelimit);
- if (timelimit > 1)
- printf("s");
- printf(".\n");
+ // Gross hack to work like Vanilla:
+
+ if (timelimit == 20 && M_CheckParm("-avg"))
+ {
+ DEH_printf("Austin Virtual Gaming: Levels will end "
+ "after 20 minutes\n");
+ }
+ else
+ {
+ DEH_printf("Levels will end after %d minute", timelimit);
+ if (timelimit > 1)
+ printf("s");
+ printf(".\n");
+ }
}
}
@@ -399,9 +649,6 @@ void D_CheckNetGame (void)
//
void D_QuitNetGame (void)
{
- if (debugfile)
- fclose (debugfile);
-
#ifdef FEATURE_MULTIPLAYER
NET_SV_Shutdown();
@@ -411,62 +658,172 @@ void D_QuitNetGame (void)
}
-// Returns true if there are currently any players in the game.
+static int GetLowTic(void)
+{
+ int lowtic;
-static boolean PlayersInGame(void)
+ lowtic = maketic;
+
+#ifdef FEATURE_MULTIPLAYER
+ if (net_client_connected)
+ {
+ if (drone || recvtic < lowtic)
+ {
+ lowtic = recvtic;
+ }
+ }
+#endif
+
+ return lowtic;
+}
+
+int frametics[4];
+int frameon;
+int frameskip[4];
+int oldnettics;
+
+static void OldNetSync(void)
{
- int i;
+ unsigned int i;
+ unsigned int keyplayer = -1;
- for (i=0; i<MAXPLAYERS; ++i)
+ frameon++;
+
+ // ideally maketic should be 1 - 3 tics above lowtic
+ // if we are consistantly slower, speed up time
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
{
+ // TODO: playeringame should not be used here.
+
if (playeringame[i])
{
- return true;
+ keyplayer = i;
+ break;
}
}
- return false;
+ if (keyplayer < 0)
+ {
+ // If there are no players, we can never advance anyway
+
+ return;
+ }
+
+ if (consoleplayer == keyplayer)
+ {
+ // the key player does not adapt
+ }
+ else
+ {
+ if (maketic <= recvtic)
+ {
+ lasttime--;
+ // printf ("-");
+ }
+
+ frameskip[frameon & 3] = oldnettics > recvtic;
+ oldnettics = maketic;
+
+ if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
+ {
+ skiptics = 1;
+ // printf ("+");
+ }
+ }
}
-static int GetLowTic(void)
+// Returns true if there are players in the game:
+
+static boolean PlayersInGame(void)
{
- int lowtic;
+ boolean result = false;
+ unsigned int i;
+
+ // If we are connected to a server, check if there are any players
+ // in the game.
-#ifdef FEATURE_MULTIPLAYER
if (net_client_connected)
{
- int i;
-
- lowtic = INT_MAX;
-
- for (i=0; i<MAXPLAYERS; ++i)
+ for (i = 0; i < MAXPLAYERS; ++i)
{
- if (playeringame[i])
- {
- if (nettics[i] < lowtic)
- lowtic = nettics[i];
- }
+ result = result || playeringame[i];
}
}
- else
-#endif
+
+ // Whether single or multi-player, unless we are running as a drone,
+ // we are in the game.
+
+ if (!drone)
{
- lowtic = maketic;
+ result = true;
}
- return lowtic;
+ return result;
+}
+
+// When using ticdup, certain values must be cleared out when running
+// the duplicate ticcmds.
+
+static void TicdupSquash(ticcmd_set_t *set)
+{
+ ticcmd_t *cmd;
+ unsigned int i;
+
+ for (i = 0; i < MAXPLAYERS ; ++i)
+ {
+ cmd = &set->cmds[i];
+ cmd->chatchar = 0;
+ if (cmd->buttons & BT_SPECIAL)
+ cmd->buttons = 0;
+ }
+}
+
+static void D_RunTic(ticcmd_set_t *set)
+{
+ extern boolean advancedemo;
+ unsigned int i;
+
+ // Check for player quits.
+
+ for (i = 0; i < MAXPLAYERS; ++i)
+ {
+ if (playeringame[i] && !set->ingame[i])
+ {
+ D_PlayerQuitGame(&players[i]);
+ }
+ }
+
+ netcmds = set->cmds;
+
+ // check that there are players in the game. if not, we cannot
+ // run a tic.
+
+ if (advancedemo)
+ D_DoAdvanceDemo ();
+
+ G_Ticker ();
+}
+
+// When running in single player mode, clear all the ingame[] array
+// except the consoleplayer.
+
+static void SinglePlayerClear(ticcmd_set_t *set)
+{
+ unsigned int i;
+
+ for (i = 0; i < MAXPLAYERS; ++i)
+ {
+ if (i != consoleplayer)
+ {
+ set->ingame[i] = false;
+ }
+ }
}
//
// TryRunTics
//
-int oldnettics;
-int frametics[4];
-int frameon;
-int frameskip[4];
-int oldnettics;
-
-extern boolean advancedemo;
void TryRunTics (void)
{
@@ -492,7 +849,7 @@ void TryRunTics (void)
// decide how many tics to run
- if (net_cl_new_sync)
+ if (new_sync)
{
counts = availabletics;
}
@@ -509,52 +866,9 @@ void TryRunTics (void)
if (counts < 1)
counts = 1;
- frameon++;
-
- if (!demoplayback)
+ if (net_client_connected)
{
- int keyplayer = -1;
-
- // ideally maketic should be 1 - 3 tics above lowtic
- // if we are consistantly slower, speed up time
-
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (playeringame[i])
- {
- keyplayer = i;
- break;
- }
- }
-
- if (keyplayer < 0)
- {
- // If there are no players, we can never advance anyway
-
- return;
- }
-
- if (consoleplayer == keyplayer)
- {
- // the key player does not adapt
- }
- else
- {
- if (maketic <= nettics[keyplayer])
- {
- lasttime--;
- // printf ("-");
- }
-
- frameskip[frameon & 3] = (oldnettics > nettics[keyplayer]);
- oldnettics = maketic;
-
- if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
- {
- skiptics = 1;
- // printf ("+");
- }
- }
+ OldNetSync();
}
}
@@ -586,41 +900,33 @@ void TryRunTics (void)
// run the count * ticdup dics
while (counts--)
{
+ ticcmd_set_t *set;
+
+ if (!PlayersInGame())
+ {
+ return;
+ }
+
+ set = &ticdata[(gametic / ticdup) % BACKUPTICS];
+
+ if (!net_client_connected)
+ {
+ SinglePlayerClear(set);
+ }
+
for (i=0 ; i<ticdup ; i++)
{
- // check that there are players in the game. if not, we cannot
- // run a tic.
-
- if (!PlayersInGame())
- {
- return;
- }
-
- if (gametic/ticdup > lowtic)
- I_Error ("gametic>lowtic");
- if (advancedemo)
- D_DoAdvanceDemo ();
+ if (gametic/ticdup > lowtic)
+ I_Error ("gametic>lowtic");
- G_Ticker ();
+ D_RunTic(set);
gametic++;
// modify command for duplicated tics
- if (i != ticdup-1)
- {
- ticcmd_t *cmd;
- int buf;
- int j;
-
- buf = (gametic/ticdup)%BACKUPTICS;
- for (j=0 ; j<MAXPLAYERS ; j++)
- {
- cmd = &netcmds[j][buf];
- cmd->chatchar = 0;
- if (cmd->buttons & BT_SPECIAL)
- cmd->buttons = 0;
- }
- }
+
+ TicdupSquash(set);
}
+
NetUpdate (); // check for new console commands
}
}
diff --git a/src/doom/d_net.h b/src/doom/d_net.h
index f801d216..a3c1a43c 100644
--- a/src/doom/d_net.h
+++ b/src/doom/d_net.h
@@ -45,7 +45,6 @@ void TryRunTics (void);
// Called at start of game loop to initialize timers
void D_StartGameLoop(void);
-extern boolean drone;
extern boolean net_cl_new_sync;
#endif
diff --git a/src/doom/doomstat.h b/src/doom/doomstat.h
index 40147833..237234d8 100644
--- a/src/doom/doomstat.h
+++ b/src/doom/doomstat.h
@@ -255,7 +255,6 @@ extern int maxammo[NUMAMMO];
// File handling stuff.
extern char * savegamedir;
extern char basedefault[1024];
-extern FILE* debugfile;
// if true, load all graphics at level load
extern boolean precache;
@@ -289,7 +288,7 @@ extern int rndindex;
extern int maketic;
extern int nettics[MAXPLAYERS];
-extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
+extern ticcmd_t *netcmds;
extern int ticdup;
diff --git a/src/doom/dstrings.h b/src/doom/dstrings.h
index bdc6b2ce..d47fc1af 100644
--- a/src/doom/dstrings.h
+++ b/src/doom/dstrings.h
@@ -38,15 +38,6 @@
#define SAVEGAMENAME "doomsav"
-//
-// File locations,
-// relative to current position.
-// Path names are OS-sensitive.
-//
-#define DEVMAPS "devmaps"
-#define DEVDATA "devdata"
-
-
// QuitDOOM messages
// 8 per each game type
#define NUM_QUITMESSAGES 8
diff --git a/src/doom/g_game.c b/src/doom/g_game.c
index ad7155a0..5662d3f2 100644
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -138,7 +138,7 @@ int gametic;
int levelstarttic; // gametic at level start
int totalkills, totalitems, totalsecret; // for intermission
-char demoname[32];
+char *demoname;
boolean demorecording;
boolean longtics; // cph's doom 1.91 longtics hack
boolean lowres_turn; // low resolution turning for longtics
@@ -986,9 +986,9 @@ void G_Ticker (void)
if (playeringame[i])
{
cmd = &players[i].cmd;
-
- memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
-
+
+ memcpy(cmd, &netcmds[i], sizeof(ticcmd_t));
+
if (demoplayback)
G_ReadDemoTiccmd (cmd);
if (demorecording)
@@ -1978,14 +1978,14 @@ void G_WriteDemoTiccmd (ticcmd_t* cmd)
//
// G_RecordDemo
//
-void G_RecordDemo (char* name)
+void G_RecordDemo (char *name)
{
int i;
int maxsize;
usergame = false;
- strcpy (demoname, name);
- strcat (demoname, ".lmp");
+ demoname = Z_Malloc(strlen(name) + 5, PU_STATIC, NULL);
+ sprintf(demoname, "%s.lmp", name);
maxsize = 0x20000;
//!
@@ -1996,8 +1996,8 @@ void G_RecordDemo (char* name)
// Specify the demo buffer size (KiB)
//
- i = M_CheckParm ("-maxdemo");
- if (i && i<myargc-1)
+ i = M_CheckParmWithArgs("-maxdemo", 1);
+ if (i)
maxsize = atoi(myargv[i+1])*1024;
demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL);
demoend = demobuffer + maxsize;
@@ -2145,16 +2145,11 @@ void G_DoPlayDemo (void)
for (i=0 ; i<MAXPLAYERS ; i++)
playeringame[i] = *demo_p++;
- //!
- // @category demo
- //
- // Play back a demo recorded in a netgame with a single player.
- //
-
- if (playeringame[1] || M_CheckParm("-netdemo") > 0)
- {
- netgame = true;
- netdemo = true;
+ if (playeringame[1] || M_CheckParm("-solo-net") > 0
+ || M_CheckParm("-netdemo") > 0)
+ {
+ netgame = true;
+ netdemo = true;
}
// don't spend a lot of time in loadlevel
diff --git a/src/doom/m_menu.c b/src/doom/m_menu.c
index a6f7bbfb..478e7f66 100644
--- a/src/doom/m_menu.c
+++ b/src/doom/m_menu.c
@@ -762,6 +762,8 @@ void M_DrawReadThis1(void)
switch (gameversion)
{
case exe_doom_1_9:
+ case exe_hacx:
+
if (gamemode == commercial)
{
// Doom 2
@@ -1440,23 +1442,23 @@ boolean M_Responder (event_t* ev)
if (ev->type == ev_joystick && joywait < I_GetTime())
{
- if (ev->data3 == -1)
+ if (ev->data3 < 0)
{
key = key_menu_up;
joywait = I_GetTime() + 5;
}
- else if (ev->data3 == 1)
+ else if (ev->data3 > 0)
{
key = key_menu_down;
joywait = I_GetTime() + 5;
}
- if (ev->data2 == -1)
+ if (ev->data2 < 0)
{
key = key_menu_left;
joywait = I_GetTime() + 2;
}
- else if (ev->data2 == 1)
+ else if (ev->data2 > 0)
{
key = key_menu_right;
joywait = I_GetTime() + 2;
diff --git a/src/doom/p_map.c b/src/doom/p_map.c
index 925e4398..78102bdf 100644
--- a/src/doom/p_map.c
+++ b/src/doom/p_map.c
@@ -1426,7 +1426,7 @@ static void SpechitOverrun(line_t *ld)
// Use the specified magic value when emulating spechit overruns.
//
- p = M_CheckParm("-spechit");
+ p = M_CheckParmWithArgs("-spechit", 1);
if (p > 0)
{
diff --git a/src/doom/p_setup.c b/src/doom/p_setup.c
index 7d9d4318..3fc95cab 100644
--- a/src/doom/p_setup.c
+++ b/src/doom/p_setup.c
@@ -755,17 +755,7 @@ P_SetupLevel
// Make sure all sounds are stopped before Z_FreeTags.
S_Start ();
-
-#if 0 // UNUSED
- if (debugfile)
- {
- Z_FreeTags (PU_LEVEL, INT_MAX);
- Z_FileDumpHeap (debugfile);
- }
- else
-#endif
- Z_FreeTags (PU_LEVEL, PU_PURGELEVEL-1);
-
+ Z_FreeTags (PU_LEVEL, PU_PURGELEVEL-1);
// UNUSED W_Profile ();
P_InitThinkers ();
diff --git a/src/doom/p_spec.c b/src/doom/p_spec.c
index 37beb850..90d0bb7c 100644
--- a/src/doom/p_spec.c
+++ b/src/doom/p_spec.c
@@ -1213,9 +1213,9 @@ static void DonutOverrun(fixed_t *s3_floorheight, short *s3_floorpic,
// system. The default (if this option is not specified) is to
// emulate the behavior when running under Windows 98.
- p = M_CheckParm("-donut");
+ p = M_CheckParmWithArgs("-donut", 2);
- if (p > 0 && p < myargc - 2)
+ if (p > 0)
{
// Dump of needed memory: (fixed_t)0000:0000 and (short)0000:0008
//
@@ -1389,10 +1389,9 @@ void P_SpawnSpecials (void)
if (W_CheckNumForName(DEH_String("texture2")) >= 0)
episode = 2;
-
// See if -TIMER was specified.
- if (timelimit > 0)
+ if (timelimit > 0 && deathmatch)
{
levelTimer = true;
levelTimeCount = timelimit * 60 * TICRATE;
@@ -1401,7 +1400,7 @@ void P_SpawnSpecials (void)
{
levelTimer = false;
}
-
+
// Init special SECTORs.
sector = sectors;
for (i=0 ; i<numsectors ; i++, sector++)
diff --git a/src/doom/r_data.c b/src/doom/r_data.c
index b999e916..505f1ff7 100644
--- a/src/doom/r_data.c
+++ b/src/doom/r_data.c
@@ -413,6 +413,7 @@ R_GetColumn
static void GenerateTextureHashTable(void)
{
+ texture_t **rover;
int i;
int key;
@@ -429,12 +430,25 @@ static void GenerateTextureHashTable(void)
textures[i]->index = i;
- // Hook into hash table
+ // Vanilla Doom does a linear search of the texures array
+ // and stops at the first entry it finds. If there are two
+ // entries with the same name, the first one in the array
+ // wins. The new entry must therefore be added at the end
+ // of the hash chain, so that earlier entries win.
key = W_LumpNameHash(textures[i]->name) % numtextures;
- textures[i]->next = textures_hashtable[key];
- textures_hashtable[key] = textures[i];
+ rover = &textures_hashtable[key];
+
+ while (*rover != NULL)
+ {
+ rover = &(*rover)->next;
+ }
+
+ // Hook into hash table
+
+ textures[i]->next = NULL;
+ *rover = textures[i];
}
}