From 63b25559b4ffd7ea12f8a8f4d91d1262803b396a Mon Sep 17 00:00:00 2001
From: vortex <vortex@d7cf8633-e32d-0410-b094-e92efae38249>
Date: Sun, 21 Aug 2011 14:55:40 +0000
Subject: [PATCH] 2 new cvars: sv_gameplayfix_unstickentities and
 sv_gameplayfix_unstickplayers to enable/disable unsticking checks, added a
 couple of VF_ parms for csqc setview to control fog (so CSQC viewports can
 have different fog settings). Rearranged fog update (moved all update code
 from R_UpdateVariables to R_UpdateFog which is called for each viewport
 render), so can have different fog settings for several viewports. Added back
 cvar r_transparent_sortmindist.

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11289 d7cf8633-e32d-0410-b094-e92efae38249
::stable-branch::merge=d35a3da5c044ae514578d133eced5a9e8ee17bb0
---
 cl_screen.c |   9 ++--
 clvm_cmds.c |  65 ++++++++++++++++++++++++++
 csprogs.h   |  11 +++++
 gl_rmain.c  | 129 +++++++++++++++++++++++++++-------------------------
 meshqueue.c |   9 ++--
 server.h    |   2 +
 sv_main.c   |   4 ++
 sv_phys.c   |   7 ++-
 svvm_cmds.c |  10 ++--
 9 files changed, 170 insertions(+), 76 deletions(-)

diff --git a/cl_screen.c b/cl_screen.c
index 049e011d..26ddc00a 100644
--- a/cl_screen.c
+++ b/cl_screen.c
@@ -1612,17 +1612,16 @@ static void SCR_DrawTouchscreenOverlay(void)
 	}
 }
 
-extern void R_UpdateFogColor(void);
+extern void R_UpdateFog(void);
 void R_ClearScreen(qboolean fogcolor)
 {
 	float clearcolor[4];
 	// clear to black
 	Vector4Clear(clearcolor);
-	if (fogcolor)
+	if (fogcolor && r_fog_clear.integer)
 	{
-		R_UpdateFogColor();
-		if (r_fog_clear.integer)
-			VectorCopy(r_refdef.fogcolor, clearcolor);
+		R_UpdateFog();
+		VectorCopy(r_refdef.fogcolor, clearcolor);
 	}
 	// clear depth is 1.0
 	// LordHavoc: we use a stencil centered around 128 instead of 0,
diff --git a/clvm_cmds.c b/clvm_cmds.c
index d9b8c77d..fd4207c6 100644
--- a/clvm_cmds.c
+++ b/clvm_cmds.c
@@ -889,6 +889,38 @@ void VM_CL_R_SetView (void)
 		case VF_CLEARSCREEN:
 			PRVM_G_FLOAT(OFS_RETURN) = r_refdef.view.isoverlay;
 			break;
+		case VF_FOG_DENSITY:
+			PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_density;
+			break;
+		case VF_FOG_COLOR:
+			PRVM_G_VECTOR(OFS_RETURN)[0] = r_refdef.fog_red;
+			PRVM_G_VECTOR(OFS_RETURN)[1] = r_refdef.fog_green;
+			PRVM_G_VECTOR(OFS_RETURN)[2] = r_refdef.fog_blue;
+			break;
+		case VF_FOG_COLOR_R:
+			PRVM_G_VECTOR(OFS_RETURN)[0] = r_refdef.fog_red;
+			break;
+		case VF_FOG_COLOR_G:
+			PRVM_G_VECTOR(OFS_RETURN)[1] = r_refdef.fog_green;
+			break;
+		case VF_FOG_COLOR_B:
+			PRVM_G_VECTOR(OFS_RETURN)[2] = r_refdef.fog_blue;
+			break;
+		case VF_FOG_ALPHA:
+			PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_alpha;
+			break;
+		case VF_FOG_START:
+			PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_start;
+			break;
+		case VF_FOG_END:
+			PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_end;
+			break;
+		case VF_FOG_HEIGHT:
+			PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_height;
+			break;
+		case VF_FOG_FADEDEPTH:
+			PRVM_G_FLOAT(OFS_RETURN) = r_refdef.fog_fadedepth;
+			break;
 		default:
 			PRVM_G_FLOAT(OFS_RETURN) = 0;
 			VM_Warning("VM_CL_R_GetView : unknown parm %i\n", c);
@@ -1004,6 +1036,38 @@ void VM_CL_R_SetView (void)
 	case VF_CLEARSCREEN:
 		r_refdef.view.isoverlay = !k;
 		break;
+	case VF_FOG_DENSITY:
+		r_refdef.fog_density = k;
+		break;
+	case VF_FOG_COLOR:
+		r_refdef.fog_red = f[0];
+		r_refdef.fog_green = f[1];
+		r_refdef.fog_blue = f[2];
+		break;
+	case VF_FOG_COLOR_R:
+		r_refdef.fog_red = k;
+		break;
+	case VF_FOG_COLOR_G:
+		r_refdef.fog_green = k;
+		break;
+	case VF_FOG_COLOR_B:
+		r_refdef.fog_blue = k;
+		break;
+	case VF_FOG_ALPHA:
+		r_refdef.fog_alpha = k;
+		break;
+	case VF_FOG_START:
+		r_refdef.fog_start = k;
+		break;
+	case VF_FOG_END:
+		r_refdef.fog_end = k;
+		break;
+	case VF_FOG_HEIGHT:
+		r_refdef.fog_height = k;
+		break;
+	case VF_FOG_FADEDEPTH:
+		r_refdef.fog_fadedepth = k;
+		break;
 	default:
 		PRVM_G_FLOAT(OFS_RETURN) = 0;
 		VM_Warning("VM_CL_R_SetView : unknown parm %i\n", c);
@@ -3034,6 +3098,7 @@ void VM_CL_R_RenderScene (void)
 	// we need to update any RENDER_VIEWMODEL entities at this point because
 	// csqc supplies its own view matrix
 	CL_UpdateViewEntities();
+
 	// now draw stuff!
 	R_RenderView();
 
diff --git a/csprogs.h b/csprogs.h
index bb0a3fb8..c82974b2 100644
--- a/csprogs.h
+++ b/csprogs.h
@@ -41,6 +41,17 @@
 #define VF_PERSPECTIVE		200 //(float)
 #define VF_CLEARSCREEN		201 //(float)
 
+#define VF_FOG_DENSITY		202 //(float)
+#define VF_FOG_COLOR		203 //(vector)
+#define VF_FOG_COLOR_R		204 //(float)
+#define VF_FOG_COLOR_G		205 //(float)
+#define VF_FOG_COLOR_B		206 //(float)
+#define VF_FOG_ALPHA		207 //(float)
+#define VF_FOG_START		208 //(float)
+#define VF_FOG_END   		209 //(float)
+#define VF_FOG_HEIGHT		210 //(float)
+#define VF_FOG_FADEDEPTH	211 //(float)
+
 #define RF_VIEWMODEL		1	// The entity is never drawn in mirrors. In engines with realtime lighting, it casts no shadows.
 #define RF_EXTERNALMODEL	2	// The entity is appears in mirrors but not in the normal view. It does still cast shadows in engines with realtime lighting.
 #define RF_DEPTHHACK		4	// The entity appears closer to the view than normal, either by scaling it wierdly or by just using a depthrange. This will usually be found in conjunction with RF_VIEWMODEL
diff --git a/gl_rmain.c b/gl_rmain.c
index 427039f8..7e1609fe 100644
--- a/gl_rmain.c
+++ b/gl_rmain.c
@@ -127,6 +127,7 @@ cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rat
 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
+cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
 
@@ -4285,6 +4286,7 @@ void GL_Main_Init(void)
 	Cvar_RegisterVariable(&r_fog_clear);
 	Cvar_RegisterVariable(&r_drawfog);
 	Cvar_RegisterVariable(&r_transparentdepthmasking);
+	Cvar_RegisterVariable(&r_transparent_sortmindist);
 	Cvar_RegisterVariable(&r_transparent_sortmaxdist);
 	Cvar_RegisterVariable(&r_transparent_sortarraysize);
 	Cvar_RegisterVariable(&r_texture_dds_load);
@@ -6578,67 +6580,9 @@ static void R_BlendView(void)
 
 matrix4x4_t r_waterscrollmatrix;
 
-void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
+void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
 {
-	if (r_refdef.fog_density)
-	{
-		r_refdef.fogcolor[0] = r_refdef.fog_red;
-		r_refdef.fogcolor[1] = r_refdef.fog_green;
-		r_refdef.fogcolor[2] = r_refdef.fog_blue;
-
-		Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
-		r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
-		r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
-		r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
-
-		{
-			vec3_t fogvec;
-			VectorCopy(r_refdef.fogcolor, fogvec);
-			//   color.rgb *= ContrastBoost * SceneBrightness;
-			VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
-			r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
-			r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
-			r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
-		}
-	}
-}
-
-void R_UpdateVariables(void)
-{
-	R_Textures_Frame();
-
-	r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
-
-	r_refdef.farclip = r_farclip_base.value;
-	if (r_refdef.scene.worldmodel)
-		r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
-	r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
-
-	if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
-		Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
-	r_refdef.polygonfactor = 0;
-	r_refdef.polygonoffset = 0;
-	r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
-	r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
-
-	r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
-	r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
-	r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
-	r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
-	r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
-	if (FAKELIGHT_ENABLED)
-	{
-		r_refdef.lightmapintensity *= r_fakelight_intensity.value;
-	}
-	if (r_showsurfaces.integer)
-	{
-		r_refdef.scene.rtworld = false;
-		r_refdef.scene.rtworldshadows = false;
-		r_refdef.scene.rtdlight = false;
-		r_refdef.scene.rtdlightshadows = false;
-		r_refdef.lightmapintensity = 0;
-	}
-
+	// Nehahra fog
 	if (gamemode == GAME_NEHAHRA)
 	{
 		if (gl_fogenable.integer)
@@ -6669,12 +6613,11 @@ void R_UpdateVariables(void)
 		}
 	}
 
+	// fog parms
 	r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
 	r_refdef.fog_start = max(0, r_refdef.fog_start);
 	r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
 
-	// R_UpdateFogColor(); // why? R_RenderScene does it anyway
-
 	if (r_refdef.fog_density && r_drawfog.integer)
 	{
 		r_refdef.fogenabled = true;
@@ -6700,6 +6643,66 @@ void R_UpdateVariables(void)
 	else
 		r_refdef.fogenabled = false;
 
+	// fog color
+	if (r_refdef.fog_density)
+	{
+		r_refdef.fogcolor[0] = r_refdef.fog_red;
+		r_refdef.fogcolor[1] = r_refdef.fog_green;
+		r_refdef.fogcolor[2] = r_refdef.fog_blue;
+
+		Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
+		r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
+		r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
+		r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
+
+		{
+			vec3_t fogvec;
+			VectorCopy(r_refdef.fogcolor, fogvec);
+			//   color.rgb *= ContrastBoost * SceneBrightness;
+			VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
+			r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
+			r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
+			r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
+		}
+	}
+}
+
+void R_UpdateVariables(void)
+{
+	R_Textures_Frame();
+
+	r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
+
+	r_refdef.farclip = r_farclip_base.value;
+	if (r_refdef.scene.worldmodel)
+		r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
+	r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
+
+	if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
+		Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
+	r_refdef.polygonfactor = 0;
+	r_refdef.polygonoffset = 0;
+	r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
+	r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
+
+	r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
+	r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
+	r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
+	r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
+	r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
+	if (FAKELIGHT_ENABLED)
+	{
+		r_refdef.lightmapintensity *= r_fakelight_intensity.value;
+	}
+	if (r_showsurfaces.integer)
+	{
+		r_refdef.scene.rtworld = false;
+		r_refdef.scene.rtworldshadows = false;
+		r_refdef.scene.rtdlight = false;
+		r_refdef.scene.rtdlightshadows = false;
+		r_refdef.lightmapintensity = 0;
+	}
+
 	switch(vid.renderpath)
 	{
 	case RENDERPATH_GL20:
@@ -6980,7 +6983,7 @@ void R_RenderScene(void)
 
 	r_refdef.stats.renders++;
 
-	R_UpdateFogColor();
+	R_UpdateFog();
 
 	// don't let sound skip if going slow
 	if (r_refdef.scene.extraupdate)
diff --git a/meshqueue.c b/meshqueue.c
index d21ba627..34334e6d 100644
--- a/meshqueue.c
+++ b/meshqueue.c
@@ -17,6 +17,7 @@ int trans_sortarraysize;
 meshqueue_t **trans_hash = NULL;
 meshqueue_t ***trans_hashpointer = NULL;
 extern cvar_t r_transparent_sortarraysize;
+extern cvar_t r_transparent_sortmindist;
 extern cvar_t r_transparent_sortmaxdist;
 
 float mqt_viewplanedist;
@@ -73,8 +74,10 @@ void R_MeshQueue_RenderTransparent(void)
 	// check for bad cvars
 	if (r_transparent_sortarraysize.integer < 1 || r_transparent_sortarraysize.integer > 32768)
 		Cvar_SetValueQuick(&r_transparent_sortarraysize, bound(1, r_transparent_sortarraysize.integer, 32768));
-	if (r_transparent_sortmaxdist.integer < 1 || r_transparent_sortmaxdist.integer > 32768)
-		Cvar_SetValueQuick(&r_transparent_sortmaxdist, bound(1, r_transparent_sortmaxdist.integer, 32768));
+	if (r_transparent_sortmindist.integer < 1 || r_transparent_sortmindist.integer >= r_transparent_sortmaxdist.integer)
+		Cvar_SetValueQuick(&r_transparent_sortmindist, 0);
+	if (r_transparent_sortmaxdist.integer < r_transparent_sortmindist.integer || r_transparent_sortmaxdist.integer > 32768)
+		Cvar_SetValueQuick(&r_transparent_sortmaxdist, bound(r_transparent_sortmindist.integer, r_transparent_sortmaxdist.integer, 32768));
 
 	// update hash array
 	if (trans_sortarraysize != r_transparent_sortarraysize.integer)
@@ -96,7 +99,7 @@ void R_MeshQueue_RenderTransparent(void)
 	maxhashindex = trans_sortarraysize - 1;
 	for (i = 0, mqt = mqt_array; i < mqt_count; i++, mqt++)
 	{
-		hashindex = bound(0, (int)(min(mqt->dist, r_transparent_sortmaxdist.integer) * distscale), maxhashindex);
+		hashindex = bound(0, (int)(bound(0, mqt->dist - r_transparent_sortmindist.integer, r_transparent_sortmaxdist.integer) * distscale), maxhashindex);
 		// link to tail of hash chain (to preserve render order)
 		mqt->next = NULL;
 		*trans_hashpointer[hashindex] = mqt;
diff --git a/server.h b/server.h
index ed552a14..538a6220 100644
--- a/server.h
+++ b/server.h
@@ -451,6 +451,8 @@ extern cvar_t sv_gameplayfix_swiminbmodels;
 extern cvar_t sv_gameplayfix_upwardvelocityclearsongroundflag;
 extern cvar_t sv_gameplayfix_downtracesupportsongroundflag;
 extern cvar_t sv_gameplayfix_q1bsptracelinereportstexture;
+extern cvar_t sv_gameplayfix_unstickplayers;
+extern cvar_t sv_gameplayfix_unstickentities;
 extern cvar_t sv_gravity;
 extern cvar_t sv_idealpitchscale;
 extern cvar_t sv_jumpstep;
diff --git a/sv_main.c b/sv_main.c
index 87187b51..aa7ce320 100644
--- a/sv_main.c
+++ b/sv_main.c
@@ -121,6 +121,8 @@ cvar_t sv_gameplayfix_swiminbmodels = {0, "sv_gameplayfix_swiminbmodels", "1", "
 cvar_t sv_gameplayfix_upwardvelocityclearsongroundflag = {0, "sv_gameplayfix_upwardvelocityclearsongroundflag", "1", "prevents monsters, items, and most other objects from being stuck to the floor when pushed around by damage, and other situations in mods"};
 cvar_t sv_gameplayfix_downtracesupportsongroundflag = {0, "sv_gameplayfix_downtracesupportsongroundflag", "1", "prevents very short moves from clearing onground (which may make the player stick to the floor at high netfps)"};
 cvar_t sv_gameplayfix_q1bsptracelinereportstexture = {0, "sv_gameplayfix_q1bsptracelinereportstexture", "1", "enables mods to get accurate trace_texture results on q1bsp by using a surface-hitting traceline implementation rather than the standard solidbsp method, q3bsp always reports texture accurately"};
+cvar_t sv_gameplayfix_unstickplayers = {0, "sv_gameplayfix_unstickplayers", "1", "big hack to try and fix the rare case of MOVETYPE_WALK entities getting stuck in the world clipping hull."};
+cvar_t sv_gameplayfix_unstickentities = {0, "sv_gameplayfix_unstickentities", "1", "hack to check if entities are crossing world collision hull and try to move them to the right position"};
 cvar_t sv_gravity = {CVAR_NOTIFY, "sv_gravity","800", "how fast you fall (512 = roughly earth gravity)"};
 cvar_t sv_idealpitchscale = {0, "sv_idealpitchscale","0.8", "how much to look up/down slopes and stairs when not using freelook"};
 cvar_t sv_jumpstep = {CVAR_NOTIFY, "sv_jumpstep", "0", "whether you can step up while jumping (sv_gameplayfix_stepwhilejumping must also be 1)"};
@@ -525,6 +527,8 @@ void SV_Init (void)
 	Cvar_RegisterVariable (&sv_gameplayfix_upwardvelocityclearsongroundflag);
 	Cvar_RegisterVariable (&sv_gameplayfix_downtracesupportsongroundflag);
 	Cvar_RegisterVariable (&sv_gameplayfix_q1bsptracelinereportstexture);
+	Cvar_RegisterVariable (&sv_gameplayfix_unstickplayers);
+	Cvar_RegisterVariable (&sv_gameplayfix_unstickentities);
 	Cvar_RegisterVariable (&sv_gravity);
 	Cvar_RegisterVariable (&sv_idealpitchscale);
 	Cvar_RegisterVariable (&sv_jumpstep);
diff --git a/sv_phys.c b/sv_phys.c
index 7b9d705a..629727c6 100644
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -2264,7 +2264,8 @@ void SV_WalkMove (prvm_edict_t *ent)
 	if (sv.frametime <= 0)
 		return;
 
-	SV_CheckStuck (ent);
+	if (sv_gameplayfix_unstickplayers.integer)
+		SV_CheckStuck (ent);
 
 	applygravity = !SV_CheckWater (ent) && PRVM_serveredictfloat(ent, movetype) == MOVETYPE_WALK && ! ((int)PRVM_serveredictfloat(ent, flags) & FL_WATERJUMP);
 
@@ -2544,6 +2545,7 @@ SV_Physics_Toss
 Toss, bounce, and fly movement.  When onground, do nothing.
 =============
 */
+
 void SV_Physics_Toss (prvm_edict_t *ent)
 {
 	trace_t trace;
@@ -2604,7 +2606,8 @@ void SV_Physics_Toss (prvm_edict_t *ent)
 		if (trace.bmodelstartsolid)
 		{
 			// try to unstick the entity
-			SV_UnstickEntity(ent);
+			if (sv_gameplayfix_unstickentities.integer)
+				SV_UnstickEntity(ent);
 			if(!SV_PushEntity (&trace, ent, move, false, true))
 				return; // teleported
 			if (ent->priv.server->free)
diff --git a/svvm_cmds.c b/svvm_cmds.c
index 617d1e33..f5d3293b 100644
--- a/svvm_cmds.c
+++ b/svvm_cmds.c
@@ -1101,6 +1101,7 @@ VM_SV_droptofloor
 void() droptofloor
 ===============
 */
+
 static void VM_SV_droptofloor (void)
 {
 	prvm_edict_t		*ent;
@@ -1128,7 +1129,8 @@ static void VM_SV_droptofloor (void)
 	end[2] -= 256;
 
 	if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer)
-		SV_UnstickEntity(ent);
+		if (sv_gameplayfix_unstickentities.integer)
+			SV_UnstickEntity(ent);
 
 	trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent));
 	if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)
@@ -1141,7 +1143,8 @@ static void VM_SV_droptofloor (void)
 		if (trace.startsolid)
 		{
 			Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
-			SV_UnstickEntity(ent);
+			if (sv_gameplayfix_unstickentities.integer)
+				SV_UnstickEntity(ent);
 			SV_LinkEdict(ent);
 			PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
 			PRVM_serveredictedict(ent, groundentity) = 0;
@@ -1151,7 +1154,8 @@ static void VM_SV_droptofloor (void)
 		{
 			Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
 			VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
-			SV_UnstickEntity(ent);
+			if (sv_gameplayfix_unstickentities.integer)
+				SV_UnstickEntity(ent);
 			SV_LinkEdict(ent);
 			PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND;
 			PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
-- 
2.39.5