diff --git a/src/d_main.cpp b/src/d_main.cpp index 08ff77a5d..aa758cde3 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -567,6 +567,23 @@ CVAR (Flag, sv_alwaysspawnmulti, dmflags2, DF2_ALWAYS_SPAWN_MULTI); CVAR (Flag, sv_novertspread, dmflags2, DF2_NOVERTSPREAD); CVAR (Flag, sv_noextraammo, dmflags2, DF2_NO_EXTRA_AMMO); +//========================================================================== +// +// CVAR dmflags3 +// +//========================================================================== + +CUSTOM_CVAR(Int, dmflags3, 0, CVAR_SERVERINFO | CVAR_NOINITCALL) +{ + if ((self & DF3_NO_PLAYER_CLIP) && (!multiplayer || deathmatch)) + { + self = self & ~DF3_NO_PLAYER_CLIP; + Printf("No player clipping is only available in coop\n"); + } +} + +CVAR(Flag, sv_noplayerclip, dmflags3, DF3_NO_PLAYER_CLIP); + //========================================================================== // // CVAR compatflags diff --git a/src/doomdef.h b/src/doomdef.h index 6982fed06..641e4597a 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -176,6 +176,12 @@ enum : unsigned DF2_NO_EXTRA_AMMO = 1u << 31, // Don't add extra ammo when picking up weapons (like in original Doom) }; +// [Nash] dmflags3 in 2023 let's gooooo +enum : unsigned +{ + DF3_NO_PLAYER_CLIP = 1 << 0, // Players can walk through and shoot through each other +}; + // [RH] Compatibility flags. enum : unsigned int { diff --git a/src/doomstat.h b/src/doomstat.h index c95d0cdca..cc991a4fe 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -233,6 +233,7 @@ EXTERN_CVAR (Int, infighting) EXTERN_CVAR (Int, dmflags); EXTERN_CVAR (Int, dmflags2); // [BC] +EXTERN_CVAR (Int, dmflags3); // [Nash] EXTERN_CVAR (Int, compatflags); EXTERN_CVAR (Int, compatflags2); diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index a9852bd6b..81f78eeb5 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -492,6 +492,9 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi if (tmf.thing->flags6 & MF6_THRUSPECIES && tmf.thing->GetSpecies() == th->GetSpecies()) continue; + if ((multiplayer && !deathmatch) && (dmflags3 & DF3_NO_PLAYER_CLIP) && (tmf.thing->player && th->player)) + continue; + // [RH] Z-Check // But not if not MF2_PASSMOBJ or MF3_DONTOVERLAP are set! // Otherwise those things would get stuck inside each other. @@ -1371,6 +1374,9 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch if ((tm.thing->flags6 & MF6_THRUSPECIES) && (tm.thing->GetSpecies() == thing->GetSpecies())) return true; + if ((multiplayer && !deathmatch) && (dmflags3 & DF3_NO_PLAYER_CLIP) && (thing->player && tm.thing->player)) + return true; + tm.thing->BlockingMobj = thing; topz = thing->Top(); @@ -1552,6 +1558,9 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch && (tm.thing->target->GetSpecies() == thing->GetSpecies())) return true; + if ((multiplayer && !deathmatch) && (dmflags3 & DF3_NO_PLAYER_CLIP) && (tm.thing->target->player && thing->player)) + return true; + // Check for rippers passing through corpses if ((thing->flags & MF_CORPSE) && (tm.thing->flags2 & MF2_RIP) && !(thing->flags & MF_SHOOTABLE)) { @@ -2063,6 +2072,10 @@ int P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj) { continue; } + if ((multiplayer && !deathmatch) && (dmflags3 & DF3_NO_PLAYER_CLIP) && (thing->player && actor->player)) + { + continue; + } if (!(thing->flags & MF_SOLID)) { // Can't hit thing continue; @@ -4456,12 +4469,14 @@ static ETraceStatus CheckForActor(FTraceResults &res, void *userdata) // 3. MTHRUSPECIES on puff and the shooter has same species as the hit actor // 4. THRUSPECIES on puff and the puff has same species as the hit actor // 5. THRUGHOST on puff and the GHOST flag on the hit actor + // 6. Skip through players in coop if sv_noplayerclip is enabled if ((data->ThruActors) || (!(data->Spectral) && res.Actor->flags4 & MF4_SPECTRAL) || (data->MThruSpecies && res.Actor->GetSpecies() == data->Caller->GetSpecies()) || (data->ThruSpecies && res.Actor->GetSpecies() == data->PuffSpecies) || - (data->hitGhosts && res.Actor->flags3 & MF3_GHOST)) + (data->hitGhosts && res.Actor->flags3 & MF3_GHOST) || + ((multiplayer && !deathmatch) && (dmflags3 & DF3_NO_PLAYER_CLIP) && (res.Actor->player && data->Caller->player))) { return TRACE_Skip; } @@ -5195,12 +5210,14 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata) // 2. MTHRUSPECIES on puff and the shooter has same species as the hit actor // 3. THRUSPECIES on puff and the puff has same species as the hit actor // 4. THRUGHOST on puff and the GHOST flag on the hit actor + // 5. Skip through players in coop if sv_noplayerclip is enabled if ((data->ThruActors) || (data->UseThruBits && (data->ThruBits & res.Actor->ThruBits)) || (data->MThruSpecies && res.Actor->GetSpecies() == data->Caller->GetSpecies()) || (data->ThruSpecies && res.Actor->GetSpecies() == data->PuffSpecies) || - (data->ThruGhosts && res.Actor->flags3 & MF3_GHOST)) + (data->ThruGhosts && res.Actor->flags3 & MF3_GHOST) || + ((multiplayer && !deathmatch) && (dmflags3 & DF3_NO_PLAYER_CLIP) && (res.Actor->player && data->Caller->player))) { return TRACE_Skip; } @@ -6014,6 +6031,9 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom if (thing->flags3 & MF3_NORADIUSDMG && !(bombspot->flags4 & MF4_FORCERADIUSDMG)) continue; + if ((multiplayer && !deathmatch) && (dmflags3 & DF3_NO_PLAYER_CLIP) && (thing->player && bombsource->player)) + continue; + if (!(flags & RADF_HURTSOURCE) && (thing == bombsource || thing == bombspot)) { // don't damage the source of the explosion continue; @@ -6427,6 +6447,9 @@ int P_PushUp(AActor *thing, FChangePosition *cpos) if (!P_CanCollideWith(thing, intersect)) continue; + if ((multiplayer && !deathmatch) && (dmflags3 & DF3_NO_PLAYER_CLIP) && (thing->player && intersect->player)) + continue; + if (!(intersect->flags2 & MF2_PASSMOBJ) || (!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) || (intersect->flags4 & MF4_ACTLIKEBRIDGE) @@ -6491,6 +6514,9 @@ int P_PushDown(AActor *thing, FChangePosition *cpos) if (!P_CanCollideWith(thing, intersect)) continue; + if ((multiplayer && !deathmatch) && (dmflags3 & DF3_NO_PLAYER_CLIP) && (thing->player && intersect->player)) + continue; + if (!(intersect->flags2 & MF2_PASSMOBJ) || (!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) || (intersect->flags4 & MF4_ACTLIKEBRIDGE) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index b05ee889b..6f3560fb6 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1702,6 +1702,7 @@ OptionMenu CoopOptions protected Option "$GMPLYMNU_KEEPAMMO", "sv_cooploseammo", "NoYes" Option "$GMPLYMNU_LOSEHALFAMMO", "sv_coophalveammo", "YesNo" Option "$GMPLYMNU_SPAWNWHEREDIED", "sv_samespawnspot", "YesNo" + Option "$GMPLYMNU_NOPLAYERCLIP", "sv_noplayerclip", "YesNo" Class "GameplayMenu" } diff --git a/wadsrc/static/zscript/actors/doom/weaponbfg.zs b/wadsrc/static/zscript/actors/doom/weaponbfg.zs index 583688f8d..8e436ed46 100644 --- a/wadsrc/static/zscript/actors/doom/weaponbfg.zs +++ b/wadsrc/static/zscript/actors/doom/weaponbfg.zs @@ -230,7 +230,8 @@ extend class Actor if (spray != null) { if ((spray.bMThruSpecies && target.GetSpecies() == t.linetarget.GetSpecies()) || - (!(flags & BFGF_HURTSOURCE) && target == t.linetarget)) // [XA] Don't hit oneself unless we say so. + (!(flags & BFGF_HURTSOURCE) && target == t.linetarget) || // [XA] Don't hit oneself unless we say so. + (multiplayer && !deathmatch) && sv_noplayerclip && (target.player && t.linetarget.player)) { spray.Destroy(); // [MC] Remove it because technically, the spray isn't trying to "hit" them. continue; diff --git a/wadsrc/static/zscript/ui/menu/doommenus.zs b/wadsrc/static/zscript/ui/menu/doommenus.zs index 969437a8b..9affca2bc 100644 --- a/wadsrc/static/zscript/ui/menu/doommenus.zs +++ b/wadsrc/static/zscript/ui/menu/doommenus.zs @@ -4,7 +4,7 @@ class GameplayMenu : OptionMenu { Super.Drawer(); - String s = String.Format("dmflags = %d dmflags2 = %d", dmflags, dmflags2); + String s = String.Format("dmflags = %d dmflags2 = %d dmflags3 = %d", dmflags, dmflags2, dmflags3); screen.DrawText (OptionFont(), OptionMenuSettings.mFontColorValue, (screen.GetWidth() - OptionWidth (s) * CleanXfac_1) / 2, 35 * CleanXfac_1, s, DTA_CleanNoMove_1, true);