diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c
index 47538983c..05b99455a 100644
--- a/engine/client/cl_tent.c
+++ b/engine/client/cl_tent.c
@@ -23,8 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "particles.h"
 entity_state_t *CL_FindPacketEntity(int num);
 
-#define R_AddDecals(a)	//disabled for now
-
 int
 	pt_gunshot=P_INVALID,
 	ptdp_gunshotquad=P_INVALID,
@@ -225,10 +223,11 @@ sfx_t			*cl_sfx_ric2;
 sfx_t			*cl_sfx_ric3;
 sfx_t			*cl_sfx_r_exp3;
 
-cvar_t	cl_expsprite = CVARF("cl_expsprite", "0", CVAR_ARCHIVE);
+cvar_t	cl_expsprite = CVARFD("cl_expsprite", "0", CVAR_ARCHIVE, "Display a central sprite in explosion effects. QuakeWorld typically does so, NQ mods should not.");
 cvar_t  r_explosionlight = CVARFC("r_explosionlight", "1", CVAR_ARCHIVE, Cvar_Limiter_ZeroToOne_Callback);
 cvar_t	cl_truelightning = CVARF("cl_truelightning", "0",	CVAR_SEMICHEAT);
 cvar_t  cl_beam_trace = CVAR("cl_beam_trace", "0");
+cvar_t	cl_legacystains = CVARD("cl_legacystains", "1", "WARNING: this cvar will default to 0 and later removed at some point");	//FIXME: do as the description says!
 
 typedef struct {
 	sfx_t **sfx;
@@ -344,6 +343,7 @@ void CL_InitTEnts (void)
 	Cvar_Register (&cl_truelightning, "Temporary entity control");
 	Cvar_Register (&cl_beam_trace, "Temporary entity control");
 	Cvar_Register (&r_explosionlight, "Temporary entity control");
+	Cvar_Register (&cl_legacystains, "Temporary entity control");
 }
 
 void CL_ShutdownTEnts (void)
@@ -764,8 +764,7 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end)	//fixme: use TE_ n
 	if (etype >= 0)
 	{
 		P_RunParticleEffectState (impact, normal, 1, etype, &(b->emitstate));
-		R_AddDecals(end);
-		R_AddStain(end, -10, -10, -10, 20);
+		if (cl_legacystains.ival) R_AddStain(end, -10, -10, -10, 20);
 	}
 }
 void CL_ParseBeam (int tent)
@@ -846,7 +845,7 @@ void CL_ParseStream (int type)
 		b->model = 	Mod_ForName("models/stice.mdl", true);
 		b->flags |= 2;
 		b->particleeffect = P_FindParticleType("te_stream_icechunks");
-		R_AddStain(end, -10, -10, 0, 20);
+		if (cl_legacystains.ival) R_AddStain(end, -10, -10, 0, 20);
 		break;
 	case TEH2_STREAM_SUNSTAFF1:
 		b->model = Mod_ForName("models/stsunsf1.mdl", true);
@@ -865,7 +864,7 @@ void CL_ParseStream (int type)
 	case TEH2_STREAM_SUNSTAFF2:
 		b->model = 	Mod_ForName("models/stsunsf1.mdl", true);
 		b->particleeffect = P_FindParticleType("te_stream_sunstaff2");
-		R_AddStain(end, -10, -10, -10, 20);
+		if (cl_legacystains.ival) R_AddStain(end, -10, -10, -10, 20);
 		break;
 	case TEH2_STREAM_COLORBEAM:
 		b->model = Mod_ForName("models/stclrbm.mdl", true);
@@ -919,6 +918,21 @@ void CL_ParseTEnt (void)
 #endif
 
 
+	if (nqprot)
+	{
+		//easiest way to handle these
+		switch(type)
+		{
+		case TENQ_EXPLOSION2:
+			type = TEQW_EXPLOSION2;
+			break;
+		case TENQ_BEAM:
+			type = TEQW_BEAM;
+			break;
+		default:
+			break;
+		}
+	}
 	switch (type)
 	{
 	case TE_WIZSPIKE:			// spike hitting wall
@@ -926,7 +940,7 @@ void CL_ParseTEnt (void)
 		pos[1] = MSG_ReadCoord ();
 		pos[2] = MSG_ReadCoord ();
 
-		R_AddStain(pos, -10, 0, -10, 20);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, 0, -10, 20);
 
 		if (P_RunParticleEffectType(pos, NULL, 1, pt_wizspike))
 			P_RunParticleEffect (pos, vec3_origin, 20, 30);
@@ -939,7 +953,7 @@ void CL_ParseTEnt (void)
 		pos[1] = MSG_ReadCoord ();
 		pos[2] = MSG_ReadCoord ();
 
-		R_AddStain(pos, -10, -10, -10, 20);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -10, -10, 20);
 
 		if (P_RunParticleEffectType(pos, NULL, 1, pt_knightspike))
 			P_RunParticleEffect (pos, vec3_origin, 226, 20);
@@ -952,8 +966,7 @@ void CL_ParseTEnt (void)
 		pos[1] = MSG_ReadCoord ();
 		pos[2] = MSG_ReadCoord ();
 
-		R_AddStain(pos, -10, -10, -10, 20);
-		R_AddDecals(pos);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -10, -10, 20);
 
 		if (P_RunParticleEffectType(pos, NULL, 1, ptdp_spikequad))
 			if (P_RunParticleEffectType(pos, NULL, 1, pt_spike))
@@ -978,8 +991,7 @@ void CL_ParseTEnt (void)
 		pos[1] = MSG_ReadCoord ();
 		pos[2] = MSG_ReadCoord ();
 
-		R_AddStain(pos, -10, -10, -10, 20);
-		R_AddDecals(pos);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -10, -10, 20);
 
 		if (P_RunParticleEffectType(pos, NULL, 1, pt_spike))
 			if (P_RunParticleEffectType(pos, NULL, 10, pt_gunshot))
@@ -1003,8 +1015,7 @@ void CL_ParseTEnt (void)
 		pos[1] = MSG_ReadCoord ();
 		pos[2] = MSG_ReadCoord ();
 
-		R_AddStain(pos, -10, -10, -10, 20);
-		R_AddDecals(pos);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -10, -10, 20);
 
 		if (P_RunParticleEffectType(pos, NULL, 1, ptdp_superspikequad))
 			if (P_RunParticleEffectType(pos, NULL, 1, pt_superspike))
@@ -1030,8 +1041,7 @@ void CL_ParseTEnt (void)
 		pos[1] = MSG_ReadCoord ();
 		pos[2] = MSG_ReadCoord ();
 
-		R_AddStain(pos, -10, -10, -10, 20);
-		R_AddDecals(pos);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -10, -10, 20);
 
 		if (P_RunParticleEffectType(pos, NULL, 1, pt_superspike))
 			if (P_RunParticleEffectType(pos, NULL, 2, pt_spike))
@@ -1060,8 +1070,7 @@ void CL_ParseTEnt (void)
 		pos[1] = MSG_ReadCoord ();
 		pos[2] = MSG_ReadCoord ();
 
-		R_AddStain(pos, -10, -10, -10, 20);
-		R_AddDecals(pos);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -10, -10, 20);
 
 		if (P_RunParticleEffectType(pos, NULL, 1, ptfte_bullet))
 			if (P_RunParticleEffectType(pos, NULL, 10, pt_gunshot))
@@ -1085,8 +1094,7 @@ void CL_ParseTEnt (void)
 		pos[1] = MSG_ReadCoord ();
 		pos[2] = MSG_ReadCoord ();
 
-		R_AddStain(pos, -10, -10, -10, 20);
-		R_AddDecals(pos);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -10, -10, 20);
 
 		if (P_RunParticleEffectType(pos, NULL, 1, ptfte_superbullet))
 			if (P_RunParticleEffectType(pos, NULL, 2, ptfte_bullet))
@@ -1117,7 +1125,7 @@ void CL_ParseTEnt (void)
 			if (P_RunParticleEffectType(pos, NULL, 1, pt_explosion))
 				P_RunParticleEffect(pos, NULL, 107, 1024); // should be 97-111
 
-		R_AddStain(pos, -1, -1, -1, 100);
+		if (cl_legacystains.ival) R_AddStain(pos, -1, -1, -1, 100);
 
 	// light
 		if (r_explosionlight.value)
@@ -1157,7 +1165,7 @@ void CL_ParseTEnt (void)
 		if (P_RunParticleEffectType(pos, NULL, 1, pt_explosion))
 			P_RunParticleEffect(pos, NULL, 107, 1024); // should be 97-111
 
-		R_AddStain(pos, -1, -1, -1, 100);
+		if (cl_legacystains.ival) R_AddStain(pos, -1, -1, -1, 100);
 
 	// light
 		if (r_explosionlight.value)
@@ -1190,6 +1198,29 @@ void CL_ParseTEnt (void)
 		}
 		break;
 
+	case TEQW_EXPLOSION2:
+		{
+			int colorStart;
+			int colorLength;
+			pos[0] = MSG_ReadCoord ();
+			pos[1] = MSG_ReadCoord ();
+			pos[2] = MSG_ReadCoord ();
+			colorStart = MSG_ReadByte ();
+			colorLength = MSG_ReadByte ();
+			if (P_RunParticleEffectType(pos, NULL, 1, pt_explosion))
+				P_RunParticleEffect(pos, NULL, (colorStart + colorLength/2), 512);
+			if (r_explosionlight.value)
+			{
+				dl = CL_AllocDlight (0);
+				VectorCopy (pos, dl->origin);
+				dl->radius = 350;
+				dl->die = cl.time + 0.5;
+				dl->decay = 300;
+			}
+			S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0, 0);
+		}
+		break;
+
 	case TEDP_EXPLOSIONRGB:
 		pos[0] = MSG_ReadCoord ();
 		pos[1] = MSG_ReadCoord ();
@@ -1197,7 +1228,7 @@ void CL_ParseTEnt (void)
 		if (P_RunParticleEffectType(pos, NULL, 1, pt_explosion))
 			P_RunParticleEffect(pos, NULL, 107, 1024); // should be 97-111
 
-		R_AddStain(pos, -1, -1, -1, 100);
+		if (cl_legacystains.ival) R_AddStain(pos, -1, -1, -1, 100);
 
 
 	// light
@@ -1228,7 +1259,7 @@ void CL_ParseTEnt (void)
 			if (P_RunParticleEffectType(pos, NULL, 1, pt_explosion))
 				P_RunParticleEffect(pos, NULL, 107, 1024); // should be 97-111
 
-		R_AddStain(pos, -1, -1, -1, 100);
+		if (cl_legacystains.ival) R_AddStain(pos, -1, -1, -1, 100);
 
 	// light
 		if (r_explosionlight.value)
@@ -1287,7 +1318,7 @@ void CL_ParseTEnt (void)
 		pos[1] = MSG_ReadCoord ();
 		pos[2] = MSG_ReadCoord ();
 
-		R_AddStain(pos, -10, -10, -10, 20);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -10, -10, 20);
 
 		if (P_RunParticleEffectType(pos, NULL, 1, ptdp_gunshotquad))
 			if (P_RunParticleEffectType(pos, NULL, 1, pt_gunshot))
@@ -1303,7 +1334,7 @@ void CL_ParseTEnt (void)
 		pos[1] = MSG_ReadCoord ();
 		pos[2] = MSG_ReadCoord ();
 
-		R_AddStain(pos, -10, -10, -10, 20);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -10, -10, 20);
 
 		if (P_RunParticleEffectType(pos, NULL, cnt, pt_gunshot))
 			P_RunParticleEffect (pos, vec3_origin, 0, 20*cnt);
@@ -1316,7 +1347,7 @@ void CL_ParseTEnt (void)
 		pos[1] = MSG_ReadCoord ();
 		pos[2] = MSG_ReadCoord ();
 
-		R_AddStain(pos, 0, -10, -10, 40);
+		if (cl_legacystains.ival) R_AddStain(pos, 0, -10, -10, 40);
 
 		if (P_RunParticleEffectType(pos, NULL, cnt, ptqw_blood))
 			if (P_RunParticleEffectType(pos, NULL, cnt, ptdp_blood))
@@ -1329,7 +1360,7 @@ void CL_ParseTEnt (void)
 		pos[1] = MSG_ReadCoord ();
 		pos[2] = MSG_ReadCoord ();
 
-		R_AddStain(pos, 1, -10, -10, 20);
+		if (cl_legacystains.ival) R_AddStain(pos, 1, -10, -10, 20);
 
 		if (P_RunParticleEffectType(pos, NULL, 1, ptqw_lightningblood))
 			P_RunParticleEffect (pos, vec3_origin, 225, 50);
@@ -1485,7 +1516,7 @@ void CL_ParseTEnt (void)
 		dl->color[2] = 1.0;
 
 		// stain (Hopefully this is close to how DP does it)
-		R_AddStain(pos, -10, -10, -10, 30);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -10, -10, 30);
 
 		if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_plasmaburn"), 0, NULL))
 			P_ParticleTrailIndex(pos, pos2, 15, 0, NULL);
@@ -2200,7 +2231,7 @@ void CLQ2_ParseTEnt (void)
 		if (P_RunParticleEffectType(pos, dir, 1, ptq2_blood))
 			if (P_RunParticleEffectType(pos, dir, 1, ptqw_blood))
 				P_RunParticleEffect(pos, dir, 0xe8, 60);
-		R_AddStain(pos, 0, -10, -10, 40);
+		if (cl_legacystains.ival) R_AddStain(pos, 0, -10, -10, 40);
 		break;
 
 	case Q2TE_GUNSHOT:			// bullet hitting wall
@@ -2213,7 +2244,7 @@ void CLQ2_ParseTEnt (void)
 		else
 			P_RunParticleEffect (pos, dir, 0xe0, 6);
 
-		R_AddStain(pos, -10, -10, -10, 20);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -10, -10, 20);
 
 		if (type != Q2TE_SPARKS)
 		{
@@ -2248,7 +2279,7 @@ void CLQ2_ParseTEnt (void)
 		MSG_ReadDir (dir);
 		P_RunParticleEffect (pos, dir, 0, 20);
 		CL_SmokeAndFlash(pos);
-		R_AddStain(pos, -10, -10, -10, 20);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -10, -10, 20);
 		break;
 
 	case Q2TE_SPLASH:			// bullet hitting water
@@ -2308,7 +2339,7 @@ void CLQ2_ParseTEnt (void)
 		if (P_RunParticleEffectType(pos, dir, 1, ptq2_blasterparticles))
 			P_RunParticleEffect (pos, dir, 0xe0, 40);
 
-		R_AddStain(pos, 0, -5, -10, 20);
+		if (cl_legacystains.ival) R_AddStain(pos, 0, -5, -10, 20);
 
 		ex = CL_AllocExplosion ();
 		VectorCopy (pos, ex->origin);
@@ -2368,7 +2399,7 @@ void CLQ2_ParseTEnt (void)
 		if (P_RunParticleEffectType(pos, NULL, 1, pt_explosion))
 			P_RunParticleEffect(pos, NULL, 0xe0, 256);
 
-		R_AddStain(pos, -1, -1, -1, 100);
+		if (cl_legacystains.ival) R_AddStain(pos, -1, -1, -1, 100);
 
 	// light
 		if (r_explosionlight.value)
@@ -2463,7 +2494,7 @@ void CLQ2_ParseTEnt (void)
 			if (P_RunParticleEffectType(pos, NULL, 1, pt_explosion))
 				P_RunParticleEffect(pos, NULL, 0xe0, 256);
 
-			R_AddStain(pos, -1, -1, -1, 100);
+			if (cl_legacystains.ival) R_AddStain(pos, -1, -1, -1, 100);
 		}
 
 	// light
@@ -2639,7 +2670,7 @@ void CLQ2_ParseTEnt (void)
 			if (P_RunParticleEffectType(pos, dir, 1, ptq2_blasterparticles))
 				P_RunParticleEffect (pos, dir, 0xd0, 40);
 
-		R_AddStain(pos, -10, 0, -10, 20);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, 0, -10, 20);
 
 		ex = CL_AllocExplosion ();
 		VectorCopy (pos, ex->origin);
@@ -2689,7 +2720,7 @@ void CLQ2_ParseTEnt (void)
 			if (P_RunParticleEffectType(pos, dir, 1, ptq2_blasterparticles))
 				P_RunParticleEffect (pos, dir, 0x6f, 40);
 
-		R_AddStain(pos, -10, -2, 0, 20);
+		if (cl_legacystains.ival) R_AddStain(pos, -10, -2, 0, 20);
 
 		ex = CL_AllocExplosion ();
 		VectorCopy (pos, ex->origin);
diff --git a/engine/client/m_items.c b/engine/client/m_items.c
index 9599c49f3..7910befbc 100644
--- a/engine/client/m_items.c
+++ b/engine/client/m_items.c
@@ -1863,7 +1863,7 @@ void M_Menu_Main_f (void)
 	int mgt;
 
 #ifdef CSQC_DAT
-	if (CSQC_ConsoleCommand(va("%s %s", Cmd_Argv(0), Cmd_Args)))
+	if (CSQC_ConsoleCommand(va("%s %s", Cmd_Argv(0), Cmd_Args())))
 		return;
 #endif
 
diff --git a/engine/client/p_script.c b/engine/client/p_script.c
index a503b25fe..b9ec71b5b 100644
--- a/engine/client/p_script.c
+++ b/engine/client/p_script.c
@@ -1419,6 +1419,15 @@ static void P_ParticleEffect_f(void)
 		}
 		else if (!strcmp(var, "lighttime"))
 			ptype->dl_time = atof(value);
+		else if (!strcmp(var, "lightcubemap"))
+			ptype->dl_cubemapnum = atoi(value);
+		else if (!strcmp(var, "spawnstain"))
+		{
+			ptype->stain_radius = atof(value);
+			ptype->stain_rgb[0] = atof(Cmd_Argv(2));
+			ptype->stain_rgb[1] = atof(Cmd_Argv(3));
+			ptype->stain_rgb[2] = atof(Cmd_Argv(4));
+		}
 		else
 			Con_DPrintf("%s is not a recognised particle type field (in %s)\n", var, ptype->name);
 	}
@@ -1555,13 +1564,15 @@ qboolean PScript_Query(int typenum, int body, char *outstr, int outstrlen)
 		if (ptype->dl_radius)
 		{
 			Q_strncatz(outstr, va("lightradius %g\n", ptype->dl_radius), outstrlen);
-			Q_strncatz(outstr, va("lightradiusfade %g \n", ptype->dl_decay[3]), outstrlen);
+			Q_strncatz(outstr, va("lightradiusfade %g\n", ptype->dl_decay[3]), outstrlen);
 			Q_strncatz(outstr, va("lightrgb %g %g %g\n", ptype->dl_rgb[0], ptype->dl_rgb[1], ptype->dl_rgb[2]), outstrlen);
 			Q_strncatz(outstr, va("lightrgbfade %g %g %g\n", ptype->dl_decay[0], ptype->dl_decay[1], ptype->dl_decay[2]), outstrlen);
 			Q_strncatz(outstr, va("lighttime %g\n", ptype->dl_time), outstrlen);
 			Q_strncatz(outstr, va("lightshadows %g\n", (ptype->flags & PT_NODLSHADOW)?0.0f:1.0f), outstrlen);
 			Q_strncatz(outstr, va("lightcubemap %i\n", ptype->dl_cubemapnum), outstrlen);
 		}
+		if (ptype->stain_radius)
+			Q_strncatz(outstr, va("spawnstain %g %g %g %g\n", ptype->stain_radius, ptype->stain_rgb[0], ptype->stain_rgb[1], ptype->stain_rgb[2]), outstrlen);
 
 		return true;
 
diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c
index f66042bee..2245e7bc3 100644
--- a/engine/client/pr_csqc.c
+++ b/engine/client/pr_csqc.c
@@ -5490,8 +5490,10 @@ qboolean CSQC_KeyPress(int key, int unicode, qboolean down, int devid)
 
 	if (!csqcprogs || !csqcg.input_event)
 		return false;
+#ifdef TEXTEDITOR
 	if (editormodal)
 		return false;
+#endif
 
 	pr_globals = PR_globals(csqcprogs, PR_CURRENT);
 	G_FLOAT(OFS_PARM0) = down?CSIE_KEYDOWN:CSIE_KEYUP;
@@ -5573,8 +5575,10 @@ qboolean CSQC_ConsoleCommand(char *cmd)
 	void *pr_globals;
 	if (!csqcprogs || !csqcg.console_command)
 		return false;
+#ifdef TEXTEDITOR
 	if (editormodal)
 		return false;
+#endif
 
 	pr_globals = PR_globals(csqcprogs, PR_CURRENT);
 	(((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, cmd));
diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c
index 8c57d33b3..bcce5571d 100644
--- a/engine/common/pr_bgcmd.c
+++ b/engine/common/pr_bgcmd.c
@@ -2768,7 +2768,6 @@ void QCBUILTIN PF_uri_unescape  (pubprogfuncs_t *prinst, struct globalvars_s *pr
 #ifdef WEBCLIENT
 static void PR_uri_get_callback(struct dl_download *dl)
 {
-	extern pubprogfuncs_t *menuprogs;
 	world_t *w = dl->user_ctx;
 	pubprogfuncs_t *prinst = w->progs;
 	float id = dl->user_num;
diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c
index 2f4e77a9d..ccd8f2ad8 100644
--- a/engine/server/sv_main.c
+++ b/engine/server/sv_main.c
@@ -537,6 +537,10 @@ void SV_DropClient (client_t *drop)
 					ED_Clear(svprogfuncs, drop->edict);
 			}
 
+			if (svprogfuncs && drop->edict)
+				drop->edict->v->frags = 0;
+			drop->edict = NULL;
+
 			if (drop->spawninfo)
 				Z_Free(drop->spawninfo);
 			drop->spawninfo = NULL;
@@ -564,7 +568,7 @@ void SV_DropClient (client_t *drop)
 		Z_Free(drop->centerprintstring);
 	drop->centerprintstring = NULL;
 
-	if (!drop->redirect)
+	if (!drop->redirect && drop->state > cs_zombie)
 	{
 		if (drop->spectator)
 			Con_Printf ("Spectator %s removed\n",drop->name);
@@ -607,8 +611,6 @@ void SV_DropClient (client_t *drop)
 	drop->kills = 0;
 	drop->deaths = 0;
 #endif
-	if (svprogfuncs && drop->edict)
-		drop->edict->v->frags = 0;
 	drop->namebuf[0] = 0;
 	drop->name = drop->namebuf;
 	memset (drop->userinfo, 0, sizeof(drop->userinfo));
@@ -2290,7 +2292,7 @@ client_t *SVC_DirectConnect(void)
 		{
 			if (!newcl)
 			{
-				if (!strcmp(cl->name, name) || !*cl->name)	//named, or first come first serve.
+				if (!strcmp(cl->name, name) || !*cl->name || sv.allocated_client_slots <= 1)	//named, or first come first serve.
 				{
 					newcl = cl;
 					temp.istobeloaded = cl->istobeloaded;