diff --git a/src/doom/d_main.c b/src/doom/d_main.c index 736a1fee1f..8cfa332a50 100644 --- a/src/doom/d_main.c +++ b/src/doom/d_main.c @@ -108,6 +108,7 @@ boolean nomonsters; // checkparm of -nomonsters boolean respawnparm; // checkparm of -respawn boolean fastparm; // checkparm of -fast boolean coop_spawns = false; // [crispy] checkparm of -coop_spawns +int mp_things_spawn_type; // [crispy] checkparm of -mpspawntype @@ -1577,6 +1578,21 @@ void D_DoomMain (void) if (M_CheckParm ("-dm3")) deathmatch = 3; + //! + // @arg + // @category net + // [crispy] + // Types of multiplayer things to be spawned in a netgame + // + + p = M_CheckParmWithArgs("-mpspawntype", 1); + mp_things_spawn_type = atoi(myargv[p+1]); + + if (mp_things_spawn_type > MP_THINGS_SPAWN_TYPES_NUM || mp_things_spawn_type < 0) + { + mp_things_spawn_type = 0; + } + if (devparm) DEH_printf(D_DEVSTR); diff --git a/src/doom/d_net.c b/src/doom/d_net.c index 4da8004aa3..8cba767554 100644 --- a/src/doom/d_net.c +++ b/src/doom/d_net.c @@ -119,6 +119,7 @@ static void LoadGameSettings(net_gamesettings_t *settings) respawnparm = settings->respawn_monsters; timelimit = settings->timelimit; consoleplayer = settings->consoleplayer; + mp_things_spawn_type = settings->mp_things_spawn_type; // [crispy] if (lowres_turn) { @@ -150,6 +151,7 @@ static void SaveGameSettings(net_gamesettings_t *settings) settings->fast_monsters = fastparm; settings->respawn_monsters = respawnparm; settings->timelimit = timelimit; + settings->mp_things_spawn_type = mp_things_spawn_type; // [crispy] settings->lowres_turn = (M_ParmExists("-record") && !M_ParmExists("-longtics")) diff --git a/src/doom/doomstat.h b/src/doom/doomstat.h index 262e6c4e59..80089ec264 100644 --- a/src/doom/doomstat.h +++ b/src/doom/doomstat.h @@ -48,7 +48,7 @@ extern boolean nomonsters; // checkparm of -nomonsters extern boolean respawnparm; // checkparm of -respawn extern boolean fastparm; // checkparm of -fast extern boolean coop_spawns; // [crispy] checkparm of -coop_spawns - +extern int mp_things_spawn_type; // [crispy] checkparm of -mpspawntype extern boolean devparm; // DEBUG: launched with -devparm @@ -103,7 +103,7 @@ extern boolean respawnmonsters; // Netgame? Only true if >1 player. extern boolean netgame; -// 0=Cooperative; 1=Deathmatch; 2=Altdeath +// 0=Cooperative; 1=Deathmatch; 2=Altdeath; 3=dm3; extern int deathmatch; // ------------------------- diff --git a/src/doom/p_mobj.c b/src/doom/p_mobj.c index e3348d3398..74a61b0b11 100644 --- a/src/doom/p_mobj.c +++ b/src/doom/p_mobj.c @@ -41,6 +41,27 @@ void G_PlayerReborn (int player); void P_SpawnMapThing (mapthing_t* mthing); +// [crispy] mobjtype weapons +const mobjtype_t mobjtype_weapons[] = { + MT_MISC25, + MT_CHAINGUN, + MT_MISC26, + MT_MISC27, + MT_MISC28, + MT_SHOTGUN, + MT_SUPERSHOTGUN, +}; + +#define MOBJTYPE_WEAPONS_COUNT (sizeof(mobjtype_weapons) / sizeof(mobjtype_t)) + +boolean is_weapon(mobjtype_t value) { + for (int i = 0; i < MOBJTYPE_WEAPONS_COUNT; ++i) { + if (value == mobjtype_weapons[i]) { + return true; + } + } + return false; +} // // P_SetMobjState @@ -1006,7 +1027,13 @@ void P_SpawnMapThing (mapthing_t* mthing) // check for appropriate skill level if (!coop_spawns && !netgame && (mthing->options & 16) ) return; - + + // [crispy] Don't spawn mp-only things in the netgame + if (netgame && (mthing->options & 16) && mp_things_spawn_type == MP_THINGS_SPAWN_NONE) + { + return; + } + if (gameskill == sk_baby) bit = 1; else if (gameskill == sk_nightmare) @@ -1057,6 +1084,20 @@ void P_SpawnMapThing (mapthing_t* mthing) return; } + if (netgame && (mthing->options & 16)) + { + // [crispy] Don't spawn any mp-only things except monsters in the netgame + if (mp_things_spawn_type == MP_THINGS_SPAWN_ONLY_MONSTERS && !(i == MT_SKULL || (mobjinfo[i].flags & MF_COUNTKILL))) + { + return; + } + // [crispy] Don't spawn mp-only weapons in the netgame + if (mp_things_spawn_type == MP_THINGS_SPAWN_ALL_BUT_WEAPONS && is_weapon(i)) + { + return; + } + } + // spawn it x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; diff --git a/src/net_defs.h b/src/net_defs.h index ab852c08ee..47fa5249df 100644 --- a/src/net_defs.h +++ b/src/net_defs.h @@ -169,6 +169,16 @@ typedef enum NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH_ALL, } net_master_packet_type_t; +typedef enum // [crispy] +{ + MP_THINGS_SPAWN_ALL, + MP_THINGS_SPAWN_ALL_BUT_WEAPONS, + MP_THINGS_SPAWN_ONLY_MONSTERS, + MP_THINGS_SPAWN_NONE, + + MP_THINGS_SPAWN_TYPES_NUM, +} net_mp_things_spawn_t; + // Settings specified when the client connects to the server. typedef struct @@ -210,7 +220,8 @@ typedef struct int num_players; int consoleplayer; - + int mp_things_spawn_type; // [crispy] + // Hexen player classes: int player_classes[NET_MAXPLAYERS]; diff --git a/src/net_structrw.c b/src/net_structrw.c index 2dbd2740a1..878990249f 100644 --- a/src/net_structrw.c +++ b/src/net_structrw.c @@ -81,6 +81,7 @@ void NET_WriteSettings(net_packet_t *packet, net_gamesettings_t *settings) NET_WriteInt8(packet, settings->random); NET_WriteInt8(packet, settings->num_players); NET_WriteInt8(packet, settings->consoleplayer); + NET_WriteInt8(packet, settings->mp_things_spawn_type); // [crispy] for (i = 0; i < settings->num_players; ++i) { @@ -109,7 +110,8 @@ boolean NET_ReadSettings(net_packet_t *packet, net_gamesettings_t *settings) && NET_ReadSInt8(packet, (signed int *) &settings->loadgame) && NET_ReadInt8(packet, (unsigned int *) &settings->random) && NET_ReadInt8(packet, (unsigned int *) &settings->num_players) - && NET_ReadSInt8(packet, (signed int *) &settings->consoleplayer); + && NET_ReadSInt8(packet, (signed int *) &settings->consoleplayer) + && NET_ReadSInt8(packet, (signed int *) &settings->mp_things_spawn_type); // [crispy] if (!success) { diff --git a/src/setup/multiplayer.c b/src/setup/multiplayer.c index 24517519db..d8af870e43 100644 --- a/src/setup/multiplayer.c +++ b/src/setup/multiplayer.c @@ -133,6 +133,7 @@ static int deathmatch = 0; static int strife_altdeath = 0; static int fast = 0; static int respawn = 0; +static int mp_things_spawn_type = 0; // [crispy] static int udpport = 2342; static int timer = 0; static int privateserver = 0; @@ -282,6 +283,11 @@ static void StartGame(int multiplayer) { AddCmdLineParameter(exec, "-privateserver"); } + + if (mp_things_spawn_type) // [crispy] + { + AddCmdLineParameter(exec, "-mpspawntype %i", mp_things_spawn_type); + } } AddWADs(exec); @@ -708,6 +714,25 @@ static txt_dropdown_list_t *GameTypeDropdown(void) } } +static void MultiplayerFlags(void) // [crispy] +{ + txt_window_t *window; + + // Build the window + window = TXT_NewWindow("Multiplayer Flags"); + TXT_SetColumnWidths(window, 40); + TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_TOP, TXT_SCREEN_W / 2, 3); + + TXT_AddWidgets(window, + TXT_NewSeparator("Multiplayer Things Spawn Type"), + TXT_NewRadioButton("All", &mp_things_spawn_type, MP_THINGS_SPAWN_ALL), + TXT_NewRadioButton("All except weapons", &mp_things_spawn_type, MP_THINGS_SPAWN_ALL_BUT_WEAPONS), + TXT_NewRadioButton("Only monsters", &mp_things_spawn_type, MP_THINGS_SPAWN_ONLY_MONSTERS), + TXT_NewRadioButton("None", &mp_things_spawn_type, MP_THINGS_SPAWN_NONE), + NULL + ); +} + // "Start game" menu. This is used for the start server window // and the single player warp menu. The parameters specify // the window title and whether to display multiplayer options. @@ -769,6 +794,15 @@ static void StartGameMenu(const char *window_title, int multiplayer) TXT_NewLabel("minutes"), NULL), NULL); + if (gamemission == doom) // [crispy] Multiplayer Flags + { + TXT_AddWidgets(window, + TXT_NewLabel("Flags"), + TXT_NewButton2("Set", + (TxtWidgetSignalFunc) MultiplayerFlags, NULL), + NULL + ); + } } TXT_AddWidgets(window,