r4247 - in branches/nexuiz-2.0: . data data/particles data/qcsrc/client data/qcsrc/common data/qcsrc/menu data/qcsrc/server data/scripts misc/gtkradiant misc/gtkradiant/singlepatches

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Fri Aug 29 14:32:01 EDT 2008


Author: div0
Date: 2008-08-29 14:32:01 -0400 (Fri, 29 Aug 2008)
New Revision: 4247

Added:
   branches/nexuiz-2.0/misc/gtkradiant/singlepatches/gtkradiant-targetname.diff
Modified:
   branches/nexuiz-2.0/.patchsets
   branches/nexuiz-2.0/data/defaultNexuiz.cfg
   branches/nexuiz-2.0/data/particles/laserbeam.tga
   branches/nexuiz-2.0/data/qcsrc/client/Main.qc
   branches/nexuiz-2.0/data/qcsrc/client/View.qc
   branches/nexuiz-2.0/data/qcsrc/client/csqc_builtins.qc
   branches/nexuiz-2.0/data/qcsrc/client/csqc_constants.qc
   branches/nexuiz-2.0/data/qcsrc/client/laser.qc
   branches/nexuiz-2.0/data/qcsrc/client/main.qh
   branches/nexuiz-2.0/data/qcsrc/common/campaign_setup.qc
   branches/nexuiz-2.0/data/qcsrc/common/constants.qh
   branches/nexuiz-2.0/data/qcsrc/common/gamecommand.qc
   branches/nexuiz-2.0/data/qcsrc/common/util.qc
   branches/nexuiz-2.0/data/qcsrc/menu/config.qh
   branches/nexuiz-2.0/data/qcsrc/menu/menu.qh
   branches/nexuiz-2.0/data/qcsrc/server/campaign.qc
   branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
   branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
   branches/nexuiz-2.0/data/qcsrc/server/defs.qh
   branches/nexuiz-2.0/data/qcsrc/server/domination.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
   branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc
   branches/nexuiz-2.0/data/qcsrc/server/keyhunt.qc
   branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
   branches/nexuiz-2.0/data/qcsrc/server/runematch.qc
   branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc
   branches/nexuiz-2.0/data/qcsrc/server/t_quake.qc
   branches/nexuiz-2.0/data/qcsrc/server/t_teleporters.qc
   branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc
   branches/nexuiz-2.0/data/qcsrc/server/vote.qc
   branches/nexuiz-2.0/data/scripts/entities.def
   branches/nexuiz-2.0/misc/gtkradiant/gtkradiant-nexuiz-patchset.diff
Log:
r4223 | div0 | 2008-08-28 15:41:54 +0200 (Thu, 28 Aug 2008) | 2 lines
new cvar: cl_zoomsensitivity
r4224 | div0 | 2008-08-28 15:43:26 +0200 (Thu, 28 Aug 2008) | 2 lines
update zoomsensitivity
r4225 | esteel | 2008-08-28 20:27:09 +0200 (Thu, 28 Aug 2008) | 2 lines
it seems a bit over the top to error out just because we can't open the file in db_save, just dprint and return
r4226 | div0 | 2008-08-29 08:07:32 +0200 (Fri, 29 Aug 2008) | 2 lines
add field .nottargeted to override targetname checks (for misc_follow on anything)
r4227 | div0 | 2008-08-29 08:13:22 +0200 (Fri, 29 Aug 2008) | 2 lines
make doors/plats not change their position in the spawn function (but defer that). Helps with attaching misc_follow.
r4228 | div0 | 2008-08-29 09:42:51 +0200 (Fri, 29 Aug 2008) | 2 lines
trigger_multivibrator
r4229 | div0 | 2008-08-29 09:55:39 +0200 (Fri, 29 Aug 2008) | 2 lines
new laser beam graphics
r4230 | div0 | 2008-08-29 10:27:36 +0200 (Fri, 29 Aug 2008) | 2 lines
fix laser interpolation
r4231 | div0 | 2008-08-29 10:43:04 +0200 (Fri, 29 Aug 2008) | 2 lines
more fixes to the laser
r4232 | div0 | 2008-08-29 11:15:58 +0200 (Fri, 29 Aug 2008) | 3 lines
func_plat: wait -1 makes it seamless
laser: color fix
r4233 | div0 | 2008-08-29 11:25:46 +0200 (Fri, 29 Aug 2008) | 2 lines
make interpolation support slowmo
r4234 | div0 | 2008-08-29 14:55:20 +0200 (Fri, 29 Aug 2008) | 2 lines
hook: when something gets in the way, cut the hook off. Helps a bit with moving around.
r4235 | div0 | 2008-08-29 16:06:08 +0200 (Fri, 29 Aug 2008) | 2 lines
more patches: targetname/killtarget handling fixes
r4236 | div0 | 2008-08-29 18:16:25 +0200 (Fri, 29 Aug 2008) | 5 lines
fteqcc should implement DWIM:
when it was a before
and I change it to a && b || c
then it should know I mean a && (b || c)! (j/k)
r4237 | div0 | 2008-08-29 18:43:20 +0200 (Fri, 29 Aug 2008) | 2 lines
record zoom in demos (TODO: also send zoom state when fov is below a threshold?)
r4238 | div0 | 2008-08-29 18:58:10 +0200 (Fri, 29 Aug 2008) | 2 lines
also detect zoom scripts, and write zoom status to the server (for speccing) and demo (assuming any fov < 50 is zoomed)
r4239 | div0 | 2008-08-29 19:06:30 +0200 (Fri, 29 Aug 2008) | 2 lines
slightly better +zoom handling; still misses DP's magic to support two keys at once
r4240 | div0 | 2008-08-29 19:10:00 +0200 (Fri, 29 Aug 2008) | 2 lines
fov 80 is new threshold
r4241 | div0 | 2008-08-29 19:10:59 +0200 (Fri, 29 Aug 2008) | 2 lines
thresh must be 60 (fov slider in menu)
r4242 | div0 | 2008-08-29 19:11:52 +0200 (Fri, 29 Aug 2008) | 2 lines
better save than sorry. 59.5
r4243 | div0 | 2008-08-29 19:31:34 +0200 (Fri, 29 Aug 2008) | 2 lines
laser: also support detectors
r4244 | div0 | 2008-08-29 20:13:58 +0200 (Fri, 29 Aug 2008) | 2 lines
fix the "wrong gametype on startup" bug
r4245 | div0 | 2008-08-29 20:19:01 +0200 (Fri, 29 Aug 2008) | 2 lines
get rid of some old unused code
r4246 | div0 | 2008-08-29 20:20:05 +0200 (Fri, 29 Aug 2008) | 2 lines
more remains

Modified: branches/nexuiz-2.0/.patchsets
===================================================================
--- branches/nexuiz-2.0/.patchsets	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/.patchsets	2008-08-29 18:32:01 UTC (rev 4247)
@@ -1,2 +1,2 @@
 master = svn://svn.icculus.org/nexuiz/trunk
-revisions_applied = 1-4221
+revisions_applied = 1-4246

Modified: branches/nexuiz-2.0/data/defaultNexuiz.cfg
===================================================================
--- branches/nexuiz-2.0/data/defaultNexuiz.cfg	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/defaultNexuiz.cfg	2008-08-29 18:32:01 UTC (rev 4247)
@@ -80,6 +80,7 @@
 fov 90
 seta cl_zoomfactor 5  // how much +zoom will zoom (1-16)
 seta cl_zoomspeed 3.5 // how fast it will zoom (0.5-16), negative values mean instant zoom
+seta cl_zoomsensitivity 0 // how zoom changes sensitivity (0 = weakest, 1 = strongest)
 freelook 1
 sensitivity 6
 v_gamma 1.125000
@@ -375,7 +376,8 @@
 set g_changeteam_fragtransfer		0	// % of frags you get to keep when you change teams (rounded down)
 
 // dm
-set g_dm 1 // actually, this is a dummy cvar just to make the menu happy
+set g_dm 1
+set gamecfg 1 // deathmatch
 
 // ctf
 set g_ctf				0

Modified: branches/nexuiz-2.0/data/particles/laserbeam.tga
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/qcsrc/client/Main.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/Main.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/client/Main.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -217,9 +217,20 @@
 	strCmd = argv(0);
 
 	if(strCmd == "+button4") { // zoom
+		// return false, because the message shall be sent to the server anyway (for demos/speccing)
+		if(ignore_plus_zoom)
+		{
+			--ignore_plus_zoom;
+			return false;
+		}
 		button_zoom = 1;
 		return true;
 	} else if(strCmd == "-button4") { // zoom
+		if(ignore_minus_zoom)
+		{
+			--ignore_minus_zoom;
+			return false;
+		}
 		button_zoom = 0;
 		return true;
 	} else if(strCmd == "+button3") { // secondary
@@ -738,6 +749,11 @@
 	spectatee_status = newspectatee_status;
 }
 
+void Net_ReadZoomNotify()
+{
+	spectatorbutton_zoom = ReadByte();
+}
+
 void Net_ReadSpawn()
 {
 	zoomin_effect = 1;
@@ -790,10 +806,14 @@
 			Net_GrapplingHook();
 			bHandled = true;
 			break;
-		case TE_CSQC_SPAWN: // TE_BEAM
+		case TE_CSQC_SPAWN:
 			Net_ReadSpawn();
 			bHandled = true;
 			break;
+		case TE_CSQC_ZOOMNOTIFY:
+			Net_ReadZoomNotify();
+			bHandled = true;
+			break;
 		default:
 			// No special logic for this temporary entity; return 0 so the engine can handle it
 			bHandled = false;

Modified: branches/nexuiz-2.0/data/qcsrc/client/View.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/View.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/client/View.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -14,10 +14,11 @@
 	return v_y * 0.01745329251994329576;
 }
 
-vector GetCurrentFov()
+vector GetCurrentFov(float fov)
 {
-	float zoomspeed, zoomfactor, zoomdir;
+	float zoomsensitivity, zoomspeed, zoomfactor, zoomdir;
 
+	zoomsensitivity = cvar("cl_zoomsensitivity");
 	zoomfactor = cvar("cl_zoomfactor");
 	if(zoomfactor < 1 || zoomfactor > 16)
 		zoomfactor = 2.5;
@@ -29,6 +30,14 @@
 	zoomdir = button_zoom;
 	if(activeweapon == 7 && !minstagib)
 		zoomdir += button_attack2;
+	if(spectatee_status > 0 || isdemo())
+	{
+		if(spectatorbutton_zoom)
+			zoomdir = 0 + !zoomdir;
+			// do not even THINK about removing this 0
+			// _I_ know what I am doing
+			// fteqcc does not
+	}
 
 	if(zoomdir)
 		zoomin_effect = 0;
@@ -55,8 +64,13 @@
 		}
 	}
 
+	if(zoomsensitivity < 1)
+		setsensitivityscale(pow(current_viewzoom, 1 - zoomsensitivity));
+	else
+		setsensitivityscale(1);
+
 	float frustumx, frustumy, fovx, fovy;
-	frustumy = tan(cvar("fov") * 0.00872664625997164788) * 0.75 * current_viewzoom;
+	frustumy = tan(fov * 0.00872664625997164788) * 0.75 * current_viewzoom;
 	frustumx = frustumy * cvar("vid_width") / cvar("vid_height") / cvar("vid_pixelheight");
 	fovx = atan2(frustumx, 1) / 0.00872664625997164788;
 	fovy = atan2(frustumy, 1) / 0.00872664625997164788;
@@ -70,9 +84,11 @@
 void CSQC_ctf_hud(void);
 void PostInit(void);
 float Sbar_WouldDrawScoreboard ();
+float zoomscript_caught;
 void CSQC_UpdateView(void)
 {
 	entity e;
+	float fov;
 
 	drawframetime = time - drawtime;
 	drawtime = time;
@@ -82,6 +98,26 @@
 	// might even be better to add the gametype to TE_CSQC_INIT...?
 	if(!postinit)
 		PostInit();
+
+	fov = cvar("fov");
+	if(button_zoom || fov <= 59.5)
+	{
+		if(!zoomscript_caught)
+		{
+			localcmd("+button4\n");
+			zoomscript_caught = 1;
+			ignore_plus_zoom += 1;
+		}
+	}
+	else
+	{
+		if(zoomscript_caught)
+		{
+			localcmd("-button4\n");
+			zoomscript_caught = 0;
+			ignore_minus_zoom += 1;
+		}
+	}
 	
 	sbar_alpha_fg = cvar("sbar_alpha_fg" );
 	sbar_hudselector = cvar("sbar_hudselector");
@@ -100,7 +136,7 @@
 	// Draw the World (and sky)
 	R_SetView(VF_DRAWWORLD, 1);
 
-	R_SetView(VF_FOV, GetCurrentFov());
+	R_SetView(VF_FOV, GetCurrentFov(fov));
 	
 	// Draw the Crosshair
 	R_SetView(VF_DRAWCROSSHAIR, !Sbar_WouldDrawScoreboard());

Modified: branches/nexuiz-2.0/data/qcsrc/client/csqc_builtins.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/csqc_builtins.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/client/csqc_builtins.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -39,7 +39,7 @@
 void (string s, ...)							localcmd = #46;
 entity (entity e)							nextent = #47;
 
-vector (vector v)							vectoangles = #51;
+vector (vector v, ...)							vectoangles = #51;
 
 void (string var, string val)						cvar_set = #72;
 
@@ -115,7 +115,7 @@
 void (string s, ...)							cprint = #338;
 void (string s, ...)							print = #339;
 
-void (float scale)							setsensitivityscale = #347;
+void (float scale)							setsensitivityscale = #346;
 
 
 void (float framenum)							RetrieveMovementFrame = #345;

Modified: branches/nexuiz-2.0/data/qcsrc/client/csqc_constants.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/csqc_constants.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/client/csqc_constants.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -58,7 +58,7 @@
 const float		STAT_MONSTERS					= 14;
 const float		STAT_ITEMS						= 15;
 const float		STAT_VIEWHEIGHT					= 16;
-
+const float		STAT_MOVEVARS_TIMESCALE         = 241;
 const float		STAT_FRAGLIMIT					= 235;
 const float		STAT_TIMELIMIT					= 236;
 

Modified: branches/nexuiz-2.0/data/qcsrc/client/laser.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/laser.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/client/laser.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -1,18 +1,23 @@
 // FIXME make this generic code, to be used for other entities too?
 .vector iorigin1, iorigin2;
 .vector ivelocity1, ivelocity2;
-.vector iangles1, iangles2;
+.vector iforward1, iforward2;
+.vector iright1, iright2;
 .float itime1, itime2;
 void InterpolateOrigin_Note()
 {
 	float dt;
 
+	makevectors(self.angles);
+
 	self.iorigin1 = self.iorigin2;
-	self.iangles1 = self.iangles2;
+	self.iforward1 = self.iforward2;
+	self.iright1 = self.iright2;
 	self.ivelocity1 = self.ivelocity2;
 
 	self.iorigin2 = self.origin;
-	self.iangles2 = self.angles;
+	self.iforward2 = v_forward;
+	self.iright2 = v_right;
 	self.ivelocity2 = self.velocity;
 
 	dt = time - self.itime1;
@@ -20,19 +25,21 @@
 	if(vlen(self.iorigin2 - self.iorigin1) > 1000)
 	{
 		self.iorigin1 = self.iorigin2;
-		self.iangles1 = self.iangles2;
+		self.iforward1 = self.iforward2;
+		self.iright1 = self.iright2;
 		self.ivelocity1 = self.ivelocity2;
 	}
 	else if(vlen(self.ivelocity2 - self.ivelocity1) > 1000)
 	{
-		self.iangles1 = self.iangles2;
+		self.iforward1 = self.iforward2;
+		self.iright1 = self.iright2;
 		self.ivelocity1 = self.ivelocity2;
 	}
 
 	if(dt < 0.2)
 	{
 		self.itime1 = time;
-		self.itime2 = time + getstatf(STAT_SYS_TICRATE);
+		self.itime2 = time + getstatf(STAT_SYS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
 	}
 	else
 	{
@@ -42,19 +49,24 @@
 }
 void InterpolateOrigin_Do()
 {
+	vector forward, right;
 	if(self.itime1 && self.itime2 && self.itime1 != self.itime2)
 	{
 		float f;
 		f = bound(0, (time - self.itime1) / (self.itime2 - self.itime1), 1);
 		self.origin = (1 - f) * self.iorigin1 + f * self.iorigin2;
-		self.angles = (1 - f) * self.iangles1 + f * self.iangles2;
+		forward = (1 - f) * self.iforward1 + f * self.iforward2;
+		right = (1 - f) * self.iright1 + f * self.iright2;
+		self.angles = vectoangles(forward, right);
+		self.angles_x = -self.angles_x;
 		self.velocity = (1 - f) * self.ivelocity1 + f * self.ivelocity2;
 	}
 }
 void InterpolateOrigin_Undo()
 {
 	self.origin = self.iorigin2;
-	self.angles = self.iangles2;
+	self.angles = vectoangles(self.iforward2, self.iright2);
+	self.angles_x = -self.angles_x;
 	self.velocity = self.ivelocity2;
 }
 
@@ -88,7 +100,7 @@
 	}
 	else
 	{
-		Draw_CylindricLine(self.origin, trace_endpos, 2, "particles/laserbeam", 0, time * 3, self.colormod, 1, DRAWFLAG_ADDITIVE); // TODO make a texture to make the laser look smoother
+		Draw_CylindricLine(self.origin, trace_endpos, 2, "particles/laserbeam", 0, time * 3, self.colormod, 0.5, DRAWFLAG_ADDITIVE); // TODO make a texture to make the laser look smoother
 	}
 	pointparticles(self.cnt, trace_endpos, trace_plane_normal, 256 * drawframetime);
 }

Modified: branches/nexuiz-2.0/data/qcsrc/client/main.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/main.qh	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/client/main.qh	2008-08-29 18:32:01 UTC (rev 4247)
@@ -115,8 +115,11 @@
 vector view_origin, view_angles, view_forward, view_right, view_up;
 
 float button_zoom;
+float spectatorbutton_zoom;
 float button_attack2;
 float activeweapon;
 float minstagib;
 float current_viewzoom;
 float zoomin_effect;
+float ignore_plus_zoom;
+float ignore_minus_zoom;

Modified: branches/nexuiz-2.0/data/qcsrc/common/campaign_setup.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/campaign_setup.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/common/campaign_setup.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -1,8 +1,5 @@
 void CampaignSetup(float n)
 {
-#ifndef MAPINFO
-	localcmd("exec game_reset.cfg\n");
-#endif
 	localcmd("exec mutator_reset.cfg\n");
 	localcmd("set g_campaign 1\n");
 	localcmd("set _campaign_name \"");
@@ -13,15 +10,6 @@
 		localcmd("\n");
 	localcmd(campaign_mutators[n]);
 		localcmd("\n");
-#ifdef MAPINFO
 	MapInfo_SwitchGameType(MapInfo_Type_FromString(campaign_gametype[n]));
-	//print(">>", cvar_string("g_tdm"), "<<\n");
 	MapInfo_LoadMap(campaign_mapname[n]);
-#else
-	localcmd("exec maps/"); // can't use strcat here in current fteqcc
-		localcmd(campaign_gametype[n]);
-		localcmd("_");
-		localcmd(campaign_mapname[n]);
-		localcmd(".mapcfg\n");
-#endif
 }

Modified: branches/nexuiz-2.0/data/qcsrc/common/constants.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/constants.qh	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/common/constants.qh	2008-08-29 18:32:01 UTC (rev 4247)
@@ -13,7 +13,8 @@
 // Revision 12: smaller scores updates (SERVER: requires new engine)
 // Revision 13: pointparticles
 // Revision 14: laser
-#define CSQC_REVISION 14
+// Revision 15: zoom
+#define CSQC_REVISION 15
 
 // probably put these in common/
 // so server/ and client/ can be synced better
@@ -198,6 +199,7 @@
 const float TE_CSQC_FORCESCOREBOARD = 110;
 const float TE_CSQC_SPECTATING = 111;
 const float TE_CSQC_SPAWN = 112;
+const float TE_CSQC_ZOOMNOTIFY = 113;
 
 const float STAT_KH_KEYS = 32;
 const float STAT_CTF_STATE = 33;

Modified: branches/nexuiz-2.0/data/qcsrc/common/gamecommand.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/gamecommand.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/common/gamecommand.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -86,7 +86,6 @@
 	{
 		if(argv(1) == "add" && argc == 3)
 		{
-#ifdef MAPINFO
 			f = fopen(strcat("maps/", argv(2), ".bsp"), FILE_READ);
 			if(f != -1)
 				fclose(f);
@@ -98,50 +97,26 @@
 				cvar_set("g_maplist", argv(2));
 			else
 				cvar_set("g_maplist", strcat(argv(2), " ", cvar_string("g_maplist")));
-#else
-			f = fopen(strcat("maps/", argv(2), ".mapcfg"), FILE_READ);
-			if(f != -1)
-				fclose(f);
-			else {
-				print("maplist: ERROR: ", argv(2), " does not exist!\n");
-				return TRUE;
-			}
-			cvar_set("g_maplist", strcat("'", argv(2), "'", cvar_string("g_maplist")));
-#endif
 			return TRUE;
 		}
 		else if(argv(1) == "remove" && argc == 3)
 		{
 			s = argv(2);
-#ifdef MAPINFO
 			n = tokenizebyseparator(cvar_string("g_maplist"), " ");
-#else
-			n = tokenize(cvar_string("g_maplist"));
-#endif
 			s2 = "";
 			for(i = 0; i < n; ++i)
 				if(argv(i) != s)
 				{
-#ifdef MAPINFO
 					s2 = strcat(s2, " ", argv(i));
-#else
-					s2 = strcat(s2, "'", argv(i), "'");
-#endif
 				}
-#ifdef MAPINFO
 			s2 = substring(s2, 1, strlen(s2) - 1);
-#endif
 			cvar_set("g_maplist", s2);
 			return TRUE;
 		}
 		else if(argv(1) == "shuffle" && argc == 2)
 		{
 			s = cvar_string("g_maplist");
-#ifdef MAPINFO
 			for(i = 1; i < (n = tokenizebyseparator(s, " ")); ++i)
-#else
-			for(i = 1; i < (n = tokenize(s)); ++i)
-#endif
 			{
 				// swap i-th item at a random position from 0 to i
 				// proof for even distribution:
@@ -158,13 +133,8 @@
 
 				s2 = "";
 				for(j = 0; j < n; ++j)
-#ifdef MAPINFO
 					s2 = strcat(s2, " ", argv((j == i) ? f : (j == f) ? i : j));
 				s = substring(s2, 1, strlen(s2) - 1);
-#else
-					s2 = strcat(s2, "'", argv((j == i) ? f : (j == f) ? i : j), "'");
-				s = s2;
-#endif
 			}
 			cvar_set("g_maplist", s);
 			return TRUE;

Modified: branches/nexuiz-2.0/data/qcsrc/common/util.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/util.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/common/util.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -277,8 +277,11 @@
 {
 	float fh, i, n;
 	fh = fopen(pFilename, FILE_WRITE);
-	if(fh < 0)
-		error(strcat("Can't write DB to ", pFilename));
+	if(fh < 0) 
+	{
+		dprint(strcat("Can't write DB to ", pFilename));
+		return;
+	}
 	n = buf_getsize(db);
 	fputs(fh, strcat(ftos(DB_BUCKETS), "\n"));
 	for(i = 0; i < n; ++i)

Modified: branches/nexuiz-2.0/data/qcsrc/menu/config.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/config.qh	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/menu/config.qh	2008-08-29 18:32:01 UTC (rev 4247)
@@ -1,4 +1,3 @@
 // build config file
 #define MENUQC // so common/*.qc can check for menu QC or game QC
-// #define MAPINFO // maybe later, when it is the default in server QC
 

Modified: branches/nexuiz-2.0/data/qcsrc/menu/menu.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/menu.qh	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/menu/menu.qh	2008-08-29 18:32:01 UTC (rev 4247)
@@ -2,8 +2,6 @@
 
 #define NULL (null_entity)
 
-#define MAPINFO
-
 // constants
 
 const string string_null;

Modified: branches/nexuiz-2.0/data/qcsrc/server/campaign.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/campaign.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/campaign.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -50,14 +50,9 @@
 	string thismapname, wantedmapname;
 	thismapname = GetMapname();
 	wantedmapname = campaign_gametype[0];
-#ifdef MAPINFO
-	// TODO check game type
 	if(MapInfo_CurrentGametype() != MapInfo_Type_FromString(wantedmapname))
 		return CampaignBailout("wrong game type!");
 	wantedmapname = campaign_mapname[0];
-#else
-	wantedmapname = strcat(wantedmapname, "_", campaign_mapname[0]);
-#endif
 	if(wantedmapname != thismapname)
 		return CampaignBailout(strcat("wrong map: ", wantedmapname, " != ", thismapname));
 	cvar_set("fraglimit", ftos(campaign_fraglimit[0]));

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -1655,6 +1655,21 @@
 		self.event_damage(self, self, 1, DEATH_ROT, self.origin, '0 0 0');
 }
 
+.float zoomstate;
+float zoomstate_set;
+void SetZoomState(float z)
+{
+	if(z != self.zoomstate)
+	{
+		msg_entity = self;
+		WriteByte(MSG_ONE, SVC_TEMPENTITY);
+		WriteByte(MSG_ONE, TE_CSQC_ZOOMNOTIFY);
+		WriteByte(MSG_ONE, z);
+		self.zoomstate = z;
+	}
+	zoomstate_set = 1;
+}
+
 /*
 ======================
 spectate mode routines
@@ -1679,6 +1694,7 @@
 	self.fixangle = TRUE;
 	setorigin(self, spectatee.origin);
 	setsize(self, spectatee.mins, spectatee.maxs);
+	SetZoomState(spectatee.zoomstate);
 }
 
 float SpectateUpdate() {
@@ -1928,6 +1944,8 @@
 	if(blockSpectators)
 		checkSpectatorBlock();
 	
+	zoomstate_set = 0;
+
 	if(self.netname_previous != self.netname)
 	{
 		if(cvar("sv_eventlog"))
@@ -2144,6 +2162,9 @@
 		SpectatorThink();
 	}
 
+	if(!zoomstate_set)
+		SetZoomState(self.BUTTON_ZOOM || (self.BUTTON_ATCK2 && !g_minstagib && self.weapon == WEP_NEX));
+
 	float oldspectatee_status;
 	oldspectatee_status = self.spectatee_status;
 	if(self.classname == "spectator")

Modified: branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -299,7 +299,6 @@
 			}
 		}
 		sprint(self, "\n");
-#ifdef MAPINFO
 	} else if(argv(0) == "lsmaps") {
 		sprint(self, "^7Maps available: ");
 		for(i = 0; i < MapInfo_count; ++i)
@@ -311,7 +310,6 @@
 			sprint(self, strcat(col, MapInfo_BSPName_ByID(i), " "));
 		}
 		sprint(self, "\n");
-#endif
 	} else if(argv(0) == "voice") {
 		VoiceMessage(argv(1));
 	} else if(argv(0) == "say") {

Modified: branches/nexuiz-2.0/data/qcsrc/server/defs.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/defs.qh	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/defs.qh	2008-08-29 18:32:01 UTC (rev 4247)
@@ -1,4 +1,3 @@
-#define MAPINFO
 float require_spawnfunc_prefix; // if this float exists, only functions with spawnfunc_ name prefix qualify as spawn functions
 
 #define BUTTON_ATCK   button0
@@ -338,8 +337,6 @@
 float default_player_alpha;
 float default_weapon_alpha;
 
-.float has_zoomed;
-
 .float() customizeentityforclient;
 .float cvar_cl_handicap;
 .float cvar_cl_zoomfactor;
@@ -491,3 +488,4 @@
 
 string clientstuff;
 .float stat_sys_ticrate;
+.float phase;

Modified: branches/nexuiz-2.0/data/qcsrc/server/domination.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/domination.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/domination.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -40,7 +40,7 @@
 	local float old_delay, old_team, real_team;
 
 	// now that the delay has expired, switch to the latest team to lay claim to this point
-	head = self.aiment;
+	head = self.owner;
 
 	real_team = self.cnt;
 	self.cnt = -1;
@@ -170,7 +170,7 @@
 	self.team = self.goalentity.team; // this stores the PREVIOUS team!
 
 	self.cnt = other.team;
-	self.aiment = head; // team to switch to after the delay
+	self.owner = head; // team to switch to after the delay
 	self.dmg_inflictor = other;
 
 	// self.state = 1;

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -60,6 +60,12 @@
 	ent.aiment_classname = strzone(e.classname);
 	ent.aiment_deadflag = e.deadflag;
 }
+void UnsetMovetypeFollow(entity ent)
+{
+	ent.movetype = MOVETYPE_FLY;
+	ent.solid = SOLID_BBOX;
+	ent.aiment = world;
+}
 float LostMovetypeFollow(entity ent)
 {
 	if(ent.aiment)
@@ -109,6 +115,23 @@
 	makevectors(self.owner.v_angle);
 	org = self.owner.origin + self.owner.view_ofs + v_forward * 8 - v_right * 8 + v_up * -12;
 
+	tracebox(org, self.mins, self.maxs, self.origin, MOVE_NOMONSTERS, self.owner);
+	// do not hit players with this, as they tend to get in the way just too often
+	if(trace_fraction < 1 && (!self.aiment || trace_ent != self.aiment))
+	{
+		// 1. detach the hook
+		if(self.aiment)
+			UnsetMovetypeFollow(self);
+
+		// 2. cut it off
+		self.origin = trace_endpos;
+
+		// 3. reattach the hook
+		if(trace_ent)
+			if(trace_ent.movetype != MOVETYPE_NONE)
+				SetMovetypeFollow(self, trace_ent);
+	}
+
 	if(self.rope_length < 0)
 		self.rope_length = vlen(org - self.origin);
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -257,6 +257,7 @@
 		if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
 		{
 			self.touch = multi_touch;
+			setorigin (self, self.origin);	// make sure it links into the world
 		}
 	}
 };
@@ -474,7 +475,7 @@
 {
 	if(self.noise)
 		precache_sound (self.noise);
-	if(self.targetname)
+	IFTARGETED
 		self.use = target_speaker_use;
 	else
 		ambientsound (self.origin, self.noise, VOL_BASE, ATTN_STATIC);
@@ -567,7 +568,7 @@
 	self.model = "net_entity";
 	if(!self.cnt)
 		self.cnt = particleeffectnum(self.mdl);
-	if(self.targetname != "")
+	IFTARGETED
 	{
 		self.use = pointparticles_use;
 		if(self.spawnflags & 1)
@@ -729,6 +730,14 @@
 			}
 		}
 	}
+	else
+	{
+		if(self.angles != self.mangle)
+		{
+			self.mangle = self.angles;
+			self.SendFlags |= 2;
+		}
+	}
 	if(self.origin != self.oldorigin)
 	{
 		self.SendFlags |= 1;
@@ -738,12 +747,15 @@
 
 void misc_laser_init()
 {
-	self.enemy = find(world, targetname, self.target);
+	if(self.target != "")
+		self.enemy = find(world, targetname, self.target);
 }
 
+.entity pusher;
 void misc_laser_think()
 {
 	vector o;
+	entity oldself;
 
 	self.nextthink = time;
 
@@ -752,9 +764,17 @@
 
 	misc_laser_aim();
 
-	o = self.enemy.origin;
-	if not(self.spawnflags & 2)
-		o = self.origin + normalize(o - self.origin) * 32768;
+	if(self.enemy)
+	{
+		o = self.enemy.origin;
+		if not(self.spawnflags & 2)
+			o = self.origin + normalize(o - self.origin) * 32768;
+	}
+	else
+	{
+		makevectors(self.mangle);
+		o = self.origin + v_forward * 32768;
+	}
 
 	if(self.dmg)
 	{
@@ -763,6 +783,38 @@
 		else
 			FireRailgunBullet(self.origin, o, self.dmg * frametime, 0, DEATH_HURTTRIGGER);
 	}
+
+	if(self.enemy.target != "") // DETECTOR laser
+	{
+		traceline(self.origin, o, MOVE_NORMAL, self);
+		if(trace_ent.classname == "player")
+		{
+			self.pusher = trace_ent;
+			if(!self.count)
+			{
+				self.count = 1;
+
+				oldself = self;
+				self = self.enemy;
+				activator = self.pusher;
+				SUB_UseTargets();
+				self = oldself;
+			}
+		}
+		else
+		{
+			if(self.count)
+			{
+				self.count = 0;
+
+				oldself = self;
+				self = self.enemy;
+				activator = self.pusher;
+				SUB_UseTargets();
+				self = oldself;
+			}
+		}
+	}
 }
 
 float laser_SendEntity(entity to, float fl)
@@ -853,8 +905,9 @@
 	self.SendFlags = 15;
 	self.modelindex = 1;
 	self.model = "net_entity";
+	self.mangle = self.angles;
 
-	if(self.targetname != "")
+	IFTARGETED
 	{
 		self.use = laser_use;
 		if(self.spawnflags & 1)
@@ -1098,6 +1151,75 @@
 	self.state = 0;
 }
 
+void multivibrator_send()
+{
+	float newstate;
+	float cyclestart;
+
+	cyclestart = floor((time + self.phase) / (self.wait + self.respawntime)) * (self.wait + self.respawntime) - self.phase;
+
+	newstate = (time < cyclestart + self.wait);
+
+	if(self.state != newstate)
+		SUB_UseTargets();
+	self.state = newstate;
+
+	if(self.state)
+		self.nextthink = cyclestart + self.wait + 0.01;
+	else
+		self.nextthink = cyclestart + self.wait + self.respawntime + 0.01;
+}
+
+void multivibrator_toggle()
+{
+	if(self.nextthink == 0)
+	{
+		multivibrator_send();
+	}
+	else
+	{
+		if(self.state)
+		{
+			SUB_UseTargets();
+			self.state = 0;
+		}
+		self.nextthink = 0;
+	}
+}
+
+/*QUAKED trigger_multivibrator (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON
+"Multivibrator" trigger gate... repeatedly sends trigger events. When triggered, turns on or off.
+-------- KEYS --------
+target: trigger all entities with this targetname when it goes off
+targetname: name that identifies this entity so it can be triggered; when off, it always uses the OFF state
+phase: offset of the timing
+wait: "on" cycle time (default: 1)
+respawntime: "off" cycle time (default: same as wait)
+-------- SPAWNFLAGS --------
+START_ON: assume it is already turned on (when targeted)
+*/
+void spawnfunc_trigger_multivibrator()
+{
+	if(!self.wait)
+		self.wait = 1;
+	if(!self.respawntime)
+		self.respawntime = self.wait;
+
+	self.state = 0;
+	self.use = multivibrator_toggle;
+	self.think = multivibrator_send;
+	self.nextthink = time;
+
+	IFTARGETED
+	{
+		if(!(self.spawnflags & 1))
+			self.nextthink = 0; // wait for a trigger event
+	}
+	else
+		self.nextthink = time;
+}
+
+
 void follow_init()
 {
 	entity src, dst;

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -140,19 +140,12 @@
 		cvar_set("_sv_init", "0");
 		if(cvar("g_maplist_shuffle"))
 			ShuffleMaplist();
-#ifdef MAPINFO
 		tokenizebyseparator(cvar_string("g_maplist"), " ");
-#else
-		tokenize(cvar_string("g_maplist"));
-		if(argv(0) != GetMapname())
-#endif
 		{
 			cvar_set("nextmap", argv(0));
 
-#ifdef MAPINFO
 			MapInfo_Enumerate();
 			MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), 0);
-#endif
 
 			if(!DoNextMapOverride())
 				GotoNextMap();
@@ -272,11 +265,7 @@
 	{
 		s = strcat(cvar_string("sv_eventlog_files_counter"), ".");
 		s = strcat(s, ftos(random()));
-#ifdef MAPINFO
 		GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s), FALSE);
-#else
-		GameLogEcho(strcat(":gamestart:", GetMapname(), ":", s), FALSE);
-#endif
 		s = ":gameinfo:mutators:LIST";
 		if(cvar("g_grappling_hook"))
 			s = strcat(s, ":grappling_hook");
@@ -319,10 +308,8 @@
 	sys_ticrate = cvar("sys_ticrate");
 	orig_slowmo = cvar("slowmo");
 
-#ifdef MAPINFO
 	MapInfo_Enumerate();
 	MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), 1);
-#endif
 
 	//if tourney is used map starts in warmup mode. if this mode shall stay unlimited, reset timelimit, but save the original one
 	if(g_tourney && cvar("g_tourney_warmup_unlimited_time")) {
@@ -395,29 +382,10 @@
 	return GametypeNameFromType(game);
 }
 
-float IsSameGametype(string mapcfgname)
-{
-#ifdef MAPINFO
-	return TRUE; // can't change game type by map name here
-#else
-	string gt;
-	gt = GetGametype();
-	if(substring(mapcfgname, 0, strlen(gt) + 1) == strcat(gt, "_"))
-		return TRUE;
-	return FALSE;
-#endif
-}
-
 string getmapname_stored;
 string GetMapname()
 {
-#ifdef MAPINFO
 	return mapname;
-#else
-	if(getmapname_stored == "")
-		getmapname_stored = strzone(strcat(GetGametype(), "_", mapname));
-	return getmapname_stored;
-#endif
 }
 
 float Map_Count, Map_Current;
@@ -491,11 +459,7 @@
 
 string Map_Filename(float position)
 {
-#ifdef MAPINFO
 	return strcat("maps/", argv(position), ".bsp");
-#else
-	return strcat("maps/", argv(position), ".mapcfg");
-#endif
 }
 
 string strwords(string s, float w)
@@ -537,11 +501,7 @@
 			return 0;
 	}
 	filename = Map_Filename(position);
-#ifdef MAPINFO
 	if(MapInfo_CheckMap(map_next))
-#else
-	if(TryFile(filename))
-#endif
 	{
 		if(pass == 2)
 			return 1;
@@ -573,31 +533,17 @@
 
 void GameResetCfg()
 {
-#ifdef MAPINFO
 	// settings persist, except...
 	if(cvar("g_campaign"))
 		localcmd("\nexec mutator_reset.cfg\n");
 	localcmd("\nsettemp_restore\n");
-#else
-	// if an exit cfg is defined by exiting map, exec it.
-	string exit_cfg;
-	exit_cfg = cvar_string("exit_cfg");
-	if(exit_cfg != "")
-		localcmd(strcat("exec \"", exit_cfg, "\"\n"));
-
-	localcmd("exec game_reset.cfg\n");
-#endif
 };
 
 void Map_Goto()
 {
 	Map_MarkAsRecent(getmapname_stored);
 	GameResetCfg();
-#ifdef MAPINFO
 	MapInfo_LoadMap(getmapname_stored);
-#else
-	localcmd(strcat("exec \"maps/", getmapname_stored ,".mapcfg\"\n"));
-#endif
 }
 
 // return codes of map selectors:
@@ -663,26 +609,14 @@
 
 		// insert the current map there
 		newlist = "";
-#ifdef MAPINFO
 		for(j = 1; j < insertpos; ++j)                 // i == 1: no loop, will be inserted as first; however, i == 1 has been excluded above
 			newlist = strcat(newlist, " ", argv(j));
 		newlist = strcat(newlist, " ", argv(0));       // now insert the just selected map
 		for(j = insertpos; j < Map_Count; ++j)         // i == Map_Count: no loop, has just been inserted as last
 			newlist = strcat(newlist, " ", argv(j));
 		newlist = substring(newlist, 1, strlen(newlist) - 1);
-#else
-		for(j = 1; j < insertpos; ++j)                 // i == 1: no loop, will be inserted as first; however, i == 1 has been excluded above
-			newlist = strcat(newlist, "'", argv(j), "'");
-		newlist = strcat(newlist, "'", argv(0), "'");  // now insert the just selected map
-		for(j = insertpos; j < Map_Count; ++j)         // i == Map_Count: no loop, has just been inserted as last
-			newlist = strcat(newlist, "'", argv(j), "'");
-#endif
 		cvar_set("g_maplist", newlist);
-#ifdef MAPINFO
 		Map_Count = tokenizebyseparator(cvar_string("g_maplist"), " ");
-#else
-		Map_Count = tokenize(newlist);
-#endif
 
 		// NOTE: the selected map has just been inserted at (insertpos-1)th position
 		Map_Current = insertpos - 1; // this is not really valid, but this way the fallback has a chance of working
@@ -696,22 +630,13 @@
 {
 	string temp;
 	temp = cvar_string("g_maplist");
-#ifdef MAPINFO
-	Map_Count = tokenizebyseparator(cvar_string("g_maplist"), " ");
-#else
-	Map_Count = tokenize(temp);
-#endif
+	Map_Count = tokenizebyseparator(temp, " ");
 	if(Map_Count == 0)
 	{
 		bprint( "Maplist is empty!  Resetting it to default map list.\n" );
-#ifdef MAPINFO
 		cvar_set("g_maplist", temp = MapInfo_ListAllowedMaps());
 		localcmd("\nmenu_cmd sync\n");
 		Map_Count = tokenizebyseparator(temp, " ");
-#else
-		cvar_set("g_maplist", temp = cvar_string("g_maplist_defaultlist"));
-		Map_Count = tokenize(temp);
-#endif
 	}
 	if(Map_Count == 0)
 		error("empty maplist, cannot select a new map");
@@ -788,11 +713,7 @@
 		return TRUE;
 	}
 	if(cvar_string("nextmap") != "")
-#ifdef MAPINFO
 		if(MapInfo_CheckMap(cvar_string("nextmap")))
-#else
-		if(TryFile(strcat("maps/", cvar_string("nextmap"), ".mapcfg")))
-#endif
 		{
 			Map_Goto_SetStr(cvar_string("nextmap"));
 			Map_Goto();
@@ -831,12 +752,8 @@
 			if(allowReset)
 			{
 				bprint( "Maplist contains no single playable map!  Resetting it to default map list.\n" );
-#ifdef MAPINFO
 				cvar_set("g_maplist", MapInfo_ListAllowedMaps());
 				localcmd("\nmenu_cmd sync\n");
-#else
-				cvar_set("g_maplist", cvar_string("g_maplist_defaultlist"));
-#endif
 			}
 			else
 			{
@@ -966,11 +883,7 @@
 		s = ":scores:";
 	else
 		s = ":status:";
-#ifdef MAPINFO
 	s = strcat(s, GetGametype(), "_", GetMapname(), ":", ftos(rint(time)));
-#else
-	s = strcat(s, GetMapname(), ":", ftos(rint(time)));
-#endif
 
 	if(to_console)
 		ServerConsoleEcho(s, FALSE);
@@ -1441,11 +1354,7 @@
 	float i;
 
 	result = cvar_string("g_maplist");
-#ifdef MAPINFO
 	litems = tokenizebyseparator(result, " ");
-#else
-	litems = tokenize(result);
-#endif
 
 	for(start = 0; start < litems - 1; ++start)
 	{
@@ -1455,7 +1364,6 @@
 		selected = ceil(random() * (litems - start) + start) - 1;
 
 		// shift this item to the place start
-#ifdef MAPINFO
 		for(i = 0; i < start; ++i)
 			result = strcat(result, " ", argv(i));
 		result = strcat(result, " ", argv(selected));
@@ -1465,17 +1373,7 @@
 		result = substring(result, 1, strlen(result) - 1);
 
 		litems = tokenizebyseparator(result, " ");
-#else
-		for(i = 0; i < start; ++i)
-			result = strcat(result, "'", argv(i), "'");
-		result = strcat(result, "'", argv(selected), "'");
-		for(i = start; i < litems; ++i)
-			if(i != selected)
-				result = strcat(result, "'", argv(i), "'");
 
-		litems = tokenize(result);
-#endif
-
 		//dprint(result, "\n");
 	}
 
@@ -1789,26 +1687,15 @@
 		return "Suggestions are not accepted on this server.";
 	if(mapvote_initialized)
 		return "Can't suggest - voting is already in progress!";
-#ifdef MAPINFO
 	m = MapInfo_FixName(m);
 	if(!m)
 		return "The map you suggested is not available on this server.";
-#else
-	if(!cvar("g_maplist_votable_suggestions_change_gametype"))
-		if(!IsSameGametype(m))
-			return "This server does not allow changing the game type by map suggestions.";
-#endif
 	if(!cvar("g_maplist_votable_override_mostrecent"))
 		if(Map_IsRecent(m))
 			return "This server does not allow for recent maps to be played again. Please be patient for some rounds.";
 
-#ifdef MAPINFO
 	if(!MapInfo_CheckMap(m))
 		return "The map you suggested does not support the current game mode.";
-#else
-	if(!TryFile(strcat("maps/", m, ".mapcfg")))
-		return "The map you suggested is not available on this server.";
-#endif
 	for(i = 0; i < mapvote_suggestion_ptr; ++i)
 		if(mapvote_suggestions[i] == m)
 			return "This map was already suggested.";
@@ -1872,12 +1759,8 @@
 	if(mapvote_count == 0)
 	{
 		bprint( "Maplist contains no single playable map!  Resetting it to default map list.\n" );
-#ifdef MAPINFO
 		cvar_set("g_maplist", MapInfo_ListAllowedMaps());
 		localcmd("\nmenu_cmd sync\n");
-#else
-		cvar_set("g_maplist", cvar_string("g_maplist_defaultlist"));
-#endif
 		for(i = 0; i < 100 && mapvote_count < nmax; ++i)
 			MapVote_AddVotable(GetNextMap(), FALSE);
 	}
@@ -2250,10 +2133,8 @@
 	if(mapvote_run)
 		return;
 
-#ifdef MAPINFO
 	MapInfo_Enumerate();
 	if(MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), 1))
-#endif
 		mapvote_run = TRUE;
 }
 void MapVote_Think()
@@ -2288,11 +2169,7 @@
 
 string GotoMap(string m)
 {
-#ifdef MAPINFO
 	if(!MapInfo_CheckMap(m))
-#else
-	if(!TryFile(strcat("maps/", m, ".mapcfg")))
-#endif
 		return "The map you chose is not available on this server.";
 	cvar_set("nextmap", m);
 	cvar_set("timelimit", "-1");
@@ -2387,11 +2264,9 @@
 		ServerProgsDB = db_load("server.db");
 
 	// Mapinfo
-#ifdef MAPINFO
 	MapInfo_Shutdown();
 	MapInfo_Enumerate();
 	MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), 1);
-#endif
 }
 
 void SV_Shutdown()

Modified: branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -77,7 +77,6 @@
 		return;
 	}
 
-#ifdef MAPINFO
 	if(argv(0) == "gametype") if(argc == 2)
 	{
 		float t, tsave;
@@ -104,7 +103,6 @@
 			bprint("Game type switch to ", s, " failed: this type does not exist!\n");
 		return;
 	}
-#endif
 
 	if(argv(0) == "adminmsg") if(argc == 3)
 	{

Modified: branches/nexuiz-2.0/data/qcsrc/server/keyhunt.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/keyhunt.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/keyhunt.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -245,7 +245,6 @@
 	setattachment(key, world, "");
 	key.angles_y += key.owner.angles_y;
 #endif
-	key.aiment = world;
 	key.flags = FL_ITEM;
 	key.solid = SOLID_TRIGGER;
 	key.movetype = MOVETYPE_TOSS;

Modified: branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -1196,6 +1196,7 @@
 #define INITPRIO_GAMETYPE_FALLBACK  1
 #define INITPRIO_FINDTARGET        10
 #define INITPRIO_SETLOCATION       90
+#define INITPRIO_LINKDOORS         91
 #define INITPRIO_LAST              99
 
 .void(void) initialize_entity;
@@ -1260,3 +1261,6 @@
 	}
 	initialize_entity_first = world;
 }
+
+.float nottargeted;
+#define IFTARGETED if(!self.nottargeted && self.targetname != "")

Modified: branches/nexuiz-2.0/data/qcsrc/server/runematch.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/runematch.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/runematch.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -199,7 +199,6 @@
 	setattachment(self, world, "");
 
 	self.movetype = MOVETYPE_FOLLOW;
-	self.aiment = other;
 	self.view_ofs = other.origin;
 
 	setorigin(self, '0 0 0');

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -140,6 +140,11 @@
 	plat_go_down();
 };
 
+void plat_init_movedown()
+{
+	setorigin (self, self.pos2);
+	self.state = 2;
+}
 
 .string sound1, sound2;
 
@@ -208,118 +213,20 @@
 
 	plat_spawn_inside_trigger ();	// the "start moving" trigger
 
-	if (self.targetname)
+	IFTARGETED
 	{
 		self.state = 4;
 		self.use = plat_use;
 	}
 	else
-	{
-		setorigin (self, self.pos2);
-		self.state = 2;
-	}
+		InitializeEntity(self, plat_init_movedown, INITPRIO_SETLOCATION);
 };
 
 
-/*
 void() train_next;
-void() func_train_find;
-
-void train_blocked()
-{
-	if (time < self.attack_finished_single)
-		return;
-	self.attack_finished_single = time + 0.5;
-};
-void train_use()
-{
-	if (self.think != func_train_find)
-		return;
-	train_next();
-};
-
 void train_wait()
 {
-	if (self.wait)
-	{
-		self.nextthink = self.ltime + self.wait;
-		sound (self, CHAN_TRIGGER, self.noise, VOL_BASE, ATTN_NORM);
-	}
-	else
-		self.nextthink = self.ltime + 0.1;
-
 	self.think = train_next;
-};
-
-void train_next()
-{
-	local entity targ;
-
-	targ = find (world, targetname, self.target);
-	self.target = targ.target;
-	if (!self.target)
-		objerror ("train_next: no next target");
-	if (targ.wait)
-		self.wait = targ.wait;
-	else
-		self.wait = 0;
-	sound (self, CHAN_TRIGGER, self.noise1, VOL_BASE, ATTN_NORM);
-	SUB_CalcMove (targ.origin - self.mins, self.speed, train_wait);
-};
-
-void func_train_find()
-{
-	local entity targ;
-
-	targ = find (world, targetname, self.target);
-	self.target = targ.target;
-	setorigin (self, targ.origin - self.mins);
-	if (!self.targetname)
-	{	// not triggered, so start immediately
-		self.nextthink = self.ltime + 0.1;
-		self.think = train_next;
-	}
-};
-
-
-void spawnfunc_func_train()
-{
-	if (!self.speed)
-		self.speed = 100;
-	if (!self.target)
-		objerror ("func_train without a target");
-
-	if (self.sounds == 0)
-	{
-		self.noise = ("misc/null.wav");
-		precache_sound ("misc/null.wav");
-		self.noise1 = ("misc/null.wav");
-		precache_sound ("misc/null.wav");
-	}
-
-	if (self.sounds == 1)
-	{
-		self.noise = ("plats/train2.wav");
-		precache_sound ("plats/train2.wav");
-		self.noise1 = ("plats/train1.wav");
-		precache_sound ("plats/train1.wav");
-	}
-
-	self.blocked = train_blocked;
-	self.use = train_use;
-	self.classname = "train";
-
-	InitMovingBrushTrigger();
-	self.effects |= EF_LOWPRECISION;
-	self.nextthink = self.ltime + 0.1;
-	self.think = func_train_find;
-};
-*/
-
-void() train_next;
-void train_wait()
-{
-	self.think = train_next;
 	self.nextthink = self.ltime + self.wait;
 };
 
@@ -333,10 +240,20 @@
 	self.wait = targ.wait;
 	if (!self.wait)
 		self.wait = 0.1;
-	if (targ.speed)
-		SUB_CalcMove(targ.origin - self.mins, targ.speed, train_wait);
+	if(self.wait < 0)
+	{
+		if (targ.speed)
+			SUB_CalcMove(targ.origin - self.mins, targ.speed, train_next);
+		else
+			SUB_CalcMove(targ.origin - self.mins, self.speed, train_next);
+	}
 	else
-		SUB_CalcMove(targ.origin - self.mins, self.speed, train_wait);
+	{
+		if (targ.speed)
+			SUB_CalcMove(targ.origin - self.mins, targ.speed, train_wait);
+		else
+			SUB_CalcMove(targ.origin - self.mins, self.speed, train_wait);
+	}
 };
 
 void func_train_find()
@@ -436,7 +353,6 @@
 };
 
 .float height;
-.float phase;
 void func_bobbing_controller_think()
 {
 	local vector v;
@@ -978,7 +894,7 @@
 
 		if (self.health)
 			starte.health = self.health;
-		if (self.targetname)
+		IFTARGETED
 			starte.targetname = self.targetname;
 		if (self.message != "")
 			starte.message = self.message;
@@ -995,7 +911,7 @@
 
 			if (self.health)
 				return;
-			if (self.targetname)
+			IFTARGETED
 				return;
 			if (self.items)
 				return;
@@ -1056,6 +972,13 @@
 
 */
 
+void door_init_startopen()
+{
+	setorigin (self, self.pos2);
+	self.pos2 = self.pos1;
+	self.pos1 = self.origin;
+}
+
 void spawnfunc_func_door()
 {
 	//if (!self.deathtype) // map makers can override this
@@ -1070,11 +993,6 @@
 	self.blocked = door_blocked;
 	self.use = door_use;
 
-    if(self.targetname == "") {
-        self.spawnflags = 0;
-        self.dmg = 0;
-    }
-
     if(self.spawnflags & 8)
         self.dmg = 10000;
 
@@ -1106,11 +1024,7 @@
 // DOOR_START_OPEN is to allow an entity to be lighted in the closed position
 // but spawn in the open position
 	if (self.spawnflags & DOOR_START_OPEN)
-	{
-		setorigin (self, self.pos2);
-		self.pos2 = self.pos1;
-		self.pos1 = self.origin;
-	}
+		InitializeEntity(self, door_init_startopen, INITPRIO_SETLOCATION);
 
 	self.state = STATE_BOTTOM;
 
@@ -1127,7 +1041,7 @@
 
 // LinkDoors can't be done until all of the doors have been spawned, so
 // the sizes can be detected properly.
-	InitializeEntity(self, LinkDoors, INITPRIO_FINDTARGET);
+	InitializeEntity(self, LinkDoors, INITPRIO_LINKDOORS);
 };
 
 /*
@@ -1258,12 +1172,12 @@
 
 void fd_secret_done()
 {
-	if (!self.targetname || self.spawnflags&SECRET_YES_SHOOT)
+	if (self.spawnflags&SECRET_YES_SHOOT)
 	{
 		self.health = 10000;
 		self.takedamage = DAMAGE_YES;
 		//self.th_pain = fd_secret_use;
-        }
+	}
 	if (self.noise3 != "")
 		sound(self, CHAN_TRIGGER, self.noise3, VOL_BASE, ATTN_NORM);
 };
@@ -1337,7 +1251,10 @@
 	self.blocked = secret_blocked;
 	self.speed = 50;
 	self.use = fd_secret_use;
-	if ( !self.targetname || self.spawnflags&SECRET_YES_SHOOT)
+	IFTARGETED
+		self.spawnflags |= SECRET_YES_SHOOT;
+
+	if(self.spawnflags&SECRET_YES_SHOOT)
 	{
 		self.health = 10000;
 		self.takedamage = DAMAGE_YES;

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_quake.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_quake.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_quake.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -52,5 +52,6 @@
 	trace_dphittexturename = "";
 	require_spawnfunc_prefix = 1;
 	self.movetypesteplandevent = SUB_Null;
+	self.viewzoom = 0;
 }
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_teleporters.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_teleporters.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_teleporters.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -92,7 +92,10 @@
 	//setorigin (self, self.origin + '0 0 27');	// To fix a mappers' habit as old as Quake
 	setorigin (self, self.origin);
 
-	if (!self.targetname)
+	IFTARGETED
+	{
+	}
+	else
 		objerror ("Teleport destination without a targetname");
 }
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -161,7 +161,7 @@
 
 void InitGameplayMode()
 {
-	float fraglimit_override, timelimit_override, capturelimit_override;
+	float fraglimit_override, timelimit_override;
 
 	VoteReset();
 	
@@ -172,14 +172,12 @@
 	ReadGameCvars();
 	WriteGameCvars();
 
-#ifdef MAPINFO
 	MapInfo_LoadMapSettings(mapname);
 	clientstuff = strzone(MapInfo_Map_clientstuff);
 	MapInfo_ClearTemps();
 
 	// in case mapinfo switched the type
 	ReadGameCvars();
-#endif
 
 	// set both here, gamemode can override it later
 	timelimit_override = cvar("timelimit_override");
@@ -352,7 +350,6 @@
 void PrintWelcomeMessage(entity pl)
 {
 	string s, mutator, modifications;
-	float p;
 
 	/*if(self.welcomemessage_time > time)
 		return;

Modified: branches/nexuiz-2.0/data/qcsrc/server/vote.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/vote.qc	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/qcsrc/server/vote.qc	2008-08-29 18:32:01 UTC (rev 4247)
@@ -348,40 +348,23 @@
 
 string ValidateMap(string m, entity e)
 {
-#ifdef MAPINFO
 	m = MapInfo_FixName(m);
 	if(!m)
 	{
 		print_to(e, "This map is not available on this server.");
 		return string_null;
 	}
-#else
-	if(!cvar("sv_vote_change_gametype"))
-		if(!IsSameGametype(m))
-		{
-			print_to(e, "This server does not allow changing the game type by map votes.");
-			return string_null;
-		}
-#endif
 	if(!cvar("sv_vote_override_mostrecent"))
 		if(Map_IsRecent(m))
 		{
 			print_to(e, "This server does not allow for recent maps to be played again. Please be patient for some rounds.");
 			return string_null;
 		}
-#ifdef MAPINFO
 	if(!MapInfo_CheckMap(m))
 	{
 		print_to(e, strcat("^1Invalid mapname, \"^3", m, "^1\" does not support the current game mode."));
 		return string_null;
 	}
-#else
-	if(!TryFile(strcat("maps/", m, ".mapcfg")))
-	{
-		print_to(e, strcat("^1Invalid mapname, \"^3", m, "^1\" does not exist on this server."));
-		return string_null;
-	}
-#endif
 
 	return m;
 }

Modified: branches/nexuiz-2.0/data/scripts/entities.def
===================================================================
--- branches/nexuiz-2.0/data/scripts/entities.def	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/data/scripts/entities.def	2008-08-29 18:32:01 UTC (rev 4247)
@@ -499,7 +499,7 @@
 /*QUAKED misc_laser (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON FINITE
 Laser beam emitter
 -------- KEYS --------
-target: target_position the laser targets (may be another entity, the laser will then target its origin. Use origin brushes, that is!)
+target: target_position the laser targets (may be another entity, preferably target_position, possibly controlled by misc_follow)
 mdl: name of particle effect for the beam end point (see effectinfo.txt; default is misc_laser_beam_end)
 colormod: color of the laser beam (default: red, that is, 1 0 0)
 dmg: damage inflicted by the beam per second, or -1 for an instant-death ray
@@ -509,7 +509,8 @@
 START_ON: when targeted, the laser will start switched on
 FINITE: the laser does not extend over its target like light would do, but stops there (takes more bandwidth)
 -------- NOTES --------
-Use trigger_monoflop if you want the laser to turn off for a while, then turn back on
+Use trigger_monoflop if you want the laser to turn off for a while, then turn back on.
+When the laser's target has itself target set, its targets are triggered when someone enters or leaves the laser.
 */
 
 /*QUAKED misc_model (1 .5 .25) (-16 -16 -16) (16 16 16) - SOLID - EXTRUDE_NORMALS EXTRUDE_TERRAIN
@@ -605,7 +606,7 @@
 target: point to next path_corner in the path.
 targetname: the train following the path or the previous path_corner in the path points to this.
 speed: speed of func_train while moving to this path corner. If unset, the value from the func_train will be used.
-wait: number of seconds func_train will pause on this path corner before moving to next path corner (default: 0.1; to not wait, set this to something like 0.001)
+wait: number of seconds func_train will pause on this path corner before moving to next path corner (default: 0.1; to not wait, set this to -1
 */
 
 /*QUAKED runematch_spawn_point (.3 .3 1) (-16 -16 -16) (16 16 16) 
@@ -641,7 +642,6 @@
 target: The targetname of the target_objective you want to manipulate.
 targetname: Name for other entities to target this entity.
 dmg: The amount of "health"-points you want to subtract from the objective health. Defaults to 101.
--------- SPAWNFLAGS --------
 */
 
 /*QUAKED target_position (0 .5 0) (-8 -8 -8) (8 8 8) 
@@ -951,6 +951,18 @@
 FIXED: do pulses of fixed length (so the "off" delay is NOT extended as usual and new events are just ignored)
 */
 
+/*QUAKED trigger_multivibrator (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON
+"Multivibrator" trigger gate... repeatedly sends trigger events. When triggered, turns on or off.
+-------- KEYS --------
+target: trigger all entities with this targetname when it goes off
+targetname: name that identifies this entity so it can be triggered
+phase: phase of the multivibrator (it is added to the time)
+wait: "on" cycle time (default: 1)
+respawntime: "off" cycle time (default: same as wait)
+-------- SPAWNFLAGS --------
+START_ON: assume it is already turned on (when targeted)
+*/
+
 /*QUAKED misc_follow (.5 .5 .5) (-8 -8 -8) (8 8 8)
 Makes one entity follow another. Will not work with all entities.
 -------- KEYS --------

Modified: branches/nexuiz-2.0/misc/gtkradiant/gtkradiant-nexuiz-patchset.diff
===================================================================
--- branches/nexuiz-2.0/misc/gtkradiant/gtkradiant-nexuiz-patchset.diff	2008-08-29 18:20:05 UTC (rev 4246)
+++ branches/nexuiz-2.0/misc/gtkradiant/gtkradiant-nexuiz-patchset.diff	2008-08-29 18:32:01 UTC (rev 4247)
@@ -111,6 +111,487 @@
  		/* skip unparsed rest of line and continue */
  		_pico_parse_skip_rest( p );
  	}
+Index: radiant/map.cpp
+===================================================================
+--- radiant/map.cpp	(revision 304)
++++ radiant/map.cpp	(working copy)
+@@ -270,6 +270,100 @@
+   ents->RemoveAll();
+ }
+ 
++void Map_DoTargetFix(entity_t *e, const char *target, int num_ents, CPtrArray *ents, GPtrArray *new_ents)
++{
++	int j;
++	int id;
++	char newtarget[128];
++	entity_t *e_target;
++
++	qboolean targetnameFound = FALSE;
++	qboolean targetFound = FALSE;
++	qboolean colliding = FALSE;
++
++	if(!target)
++		return;
++	if(!*target)
++		return;
++
++	target = g_strdup(target);
++
++	// check the current map entities for an actual collision
++	for (e_target = entities.next; e_target != &entities; e_target = e_target->next)
++	{
++		if(
++			!strcmp(target, ValueForKey(e_target, "target"))
++			||
++			!strcmp(target, ValueForKey(e_target, "killtarget"))
++		)
++		{
++			// make sure the collision is not between two imported entities
++			for(j=0; j<(int)new_ents->len; j++)
++			{
++				if(e_target == g_ptr_array_index(new_ents, j))
++				{
++					targetFound = true;
++					goto no_collision_yet_1;
++				}
++			}
++			colliding = TRUE;
++no_collision_yet_1:
++			;
++		}
++		if(
++			!strcmp(target, ValueForKey(e_target, "targetname"))
++		)
++		{
++			// make sure the collision is not between two imported entities
++			for(j=0; j<(int)new_ents->len; j++)
++			{
++				if(e_target == g_ptr_array_index(new_ents, j))
++				{
++					targetnameFound = true;
++					goto no_collision_yet_2;
++				}
++			}
++			colliding = TRUE;
++no_collision_yet_2:
++			;
++		}
++	}
++
++	// find the matching targeted entity(s)
++	if(colliding && targetFound && targetnameFound)
++	{
++		// We got a collision
++		// first look for a non-conflicting target name
++		id = GetUniqueTargetId(1);
++		sprintf(newtarget, "t%i", id);
++
++		for(j=num_ents-1; j>0; j--)
++		{
++			e_target = (entity_t*)ents->GetAt(j);
++			if(e_target != NULL)
++			{
++				const char *targetname = ValueForKey(e_target, "targetname");
++				if( (targetname != NULL) && (strcmp(target, targetname) == 0) ) 
++				{
++					SetKeyValue(e_target, "targetname", newtarget);
++				}
++				targetname = ValueForKey(e_target, "target");
++				if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
++				{
++					SetKeyValue(e_target, "target", newtarget);
++				}
++				targetname = ValueForKey(e_target, "killtarget");
++				if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
++				{
++					SetKeyValue(e_target, "killtarget", newtarget);
++				}
++			}
++		}
++	}
++
++	g_free(target);
++}
++
+ /*!\todo Possibly make the import Undo-friendly by calling Undo_End for new brushes and ents */
+ void Map_ImportEntities(CPtrArray *ents, bool bAddSelected = false)
+ {
+@@ -466,60 +560,27 @@
+     }
+     else
+     {
+-      // fix target/targetname collisions
+-      if ((g_PrefsDlg.m_bDoTargetFix) && (strcmp(ValueForKey(e, "target"), "") != 0))
+-      {
+-        GPtrArray *t_ents = g_ptr_array_new();
+-        entity_t *e_target;
+-        const char *target = ValueForKey(e, "target");
+-        qboolean bCollision=FALSE;
++      // keep a list of ents added to avoid testing collisions against them
++      g_ptr_array_add(new_ents, (gpointer)e);
+ 
+-        // check the current map entities for an actual collision
+-        for (e_target = entities.next; e_target != &entities; e_target = e_target->next)
+-        {
+-          if(!strcmp(target, ValueForKey(e_target, "target")))
+-          {
+-            bCollision = TRUE;
+-            // make sure the collision is not between two imported entities
+-            for(j=0; j<(int)new_ents->len; j++)
+-            {
+-              if(e_target == g_ptr_array_index(new_ents, j))
+-                bCollision = FALSE;
+-            }
+-          }
+-        }
+-
+-        // find the matching targeted entity(s)
+-        if(bCollision)
+-        {
+-          for(j=num_ents-1; j>0; j--)
+-          {
+-            e_target = (entity_t*)ents->GetAt(j);
+-            if(e_target != NULL && e_target != e)
+-            {
+-              const char *targetname = ValueForKey(e_target, "targetname");
+-              if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
+-                g_ptr_array_add(t_ents, (gpointer)e_target);
+-            }
+-          }
+-          if(t_ents->len > 0)
+-          {
+-            // link the first to get a unique target/targetname
+-            Entity_Connect(e, (entity_t*)g_ptr_array_index(t_ents,0));
+-            // set the targetname of the rest of them manually
+-            for(j = 1; j < (int)t_ents->len; j++)
+-              SetKeyValue( (entity_t*)g_ptr_array_index(t_ents, j), "targetname", ValueForKey(e, "target") );
+-          }
+-          g_ptr_array_free(t_ents, FALSE);
+-        }
+-      }
+-
+       // add the entity to the end of the entity list
+       Entity_AddToList(e, &entities);
+       g_qeglobals.d_num_entities++;
+ 
+-      // keep a list of ents added to avoid testing collisions against them
+-      g_ptr_array_add(new_ents, (gpointer)e);
++      // fix target/targetname collisions
++      if (g_PrefsDlg.m_bDoTargetFix)
++	  {
++		  const char *target;
++
++		  target = ValueForKey(e, "target");
++		  Map_DoTargetFix(e, target, num_ents, ents, new_ents);
++
++		  target = ValueForKey(e, "killtarget");
++		  Map_DoTargetFix(e, target, num_ents, ents, new_ents);
++
++		  target = ValueForKey(e, "targetname");
++		  Map_DoTargetFix(e, target, num_ents, ents, new_ents);
++	  }
+     }
+   }
+   g_ptr_array_free(new_ents, FALSE);
+Index: radiant/drag.cpp
+===================================================================
+--- radiant/drag.cpp	(revision 304)
++++ radiant/drag.cpp	(working copy)
+@@ -255,54 +255,6 @@
+ 
+ entity_t *peLink;
+ 
+-void UpdateTarget(vec3_t origin, vec3_t dir)
+-{
+-	trace_t	t;
+-	entity_t *pe;
+-	int i;
+-	char sz[128];
+-
+-	t = Test_Ray (origin, dir, 0);
+-
+-	if (!t.brush)
+-		return;
+-
+-	pe = t.brush->owner;
+-
+-	if (pe == NULL)
+-		return;
+-
+-	// is this the first?
+-	if (peLink != NULL)
+-	{
+-
+-		// Get the target id from out current target
+-		// if there is no id, make one
+-
+-		i = IntForKey(pe, "target");
+-		if (i <= 0)
+-		{
+-			i = GetUniqueTargetId(1);
+-			sprintf(sz, "%d", i);
+-
+-			SetKeyValue(pe, "target", sz);
+-		}
+-
+-		// set the target # into our src
+-
+-		sprintf(sz, "%d", i);
+-		SetKeyValue(peLink, "targetname", sz);
+-
+-		Sys_UpdateWindows(W_ENTITY);
+-
+-	}
+-
+-	// promote the target to the src
+-
+-	peLink = pe;
+-
+-}
+-
+ /*
+ ===========
+ Drag_Begin
+Index: radiant/xywindow.cpp
+===================================================================
+--- radiant/xywindow.cpp	(revision 304)
++++ radiant/xywindow.cpp	(working copy)
+@@ -270,16 +270,17 @@
+ void DrawPathLines (void)
+ {
+   int       i, j, k;
+-  vec3_t    mid, mid1;
++  vec3_t    mid, mid1, v;
+   entity_t *se, *te;
+   brush_t   *sb, *tb;
+   const char    *psz;
+-  vec3_t    dir, s1, s2;
++  vec3_t    dir, s1, s2, dirortho;
+   vec_t len, f;
+   int       arrows;
+   int           num_entities;
+   const char        *ent_target[MAX_MAP_ENTITIES];
+   entity_t  *ent_entity[MAX_MAP_ENTITIES];
++  int lines;
+ 
+   if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
+   {
+@@ -295,6 +296,12 @@
+       ent_entity[num_entities] = te;
+       num_entities++;
+     }
++    ent_target[num_entities] = ValueForKey (te, "killtarget");
++    if (ent_target[num_entities][0])
++    {
++      ent_entity[num_entities] = te;
++      num_entities++;
++    }
+   }
+ 
+   for (se = entities.next ; se != &entities ; se = se->next)
+@@ -308,6 +315,9 @@
+     if (sb == &se->brushes)
+       continue;
+ 
++	for (i=0 ; i<3 ; i++)
++		mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
++
+     for (k=0 ; k<num_entities ; k++)
+     {
+       if (strcmp (ent_target[k], psz))
+@@ -318,14 +328,20 @@
+       if (tb == &te->brushes)
+         continue;
+ 
+-      for (i=0 ; i<3 ; i++)
+-        mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
++	  lines = 0;
++	  if(!strcmp(ValueForKey(te, "target"), psz))
++		  lines += 1;
++	  if(!strcmp(ValueForKey(te, "killtarget"), psz))
++		  lines += 2;
+ 
+       for (i=0 ; i<3 ; i++)
+         mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5;
+ 
+       VectorSubtract (mid1, mid, dir);
+       len = VectorNormalize (dir, dir);
++	  dirortho[0] = -dir[1];
++	  dirortho[1] = dir[0];
++	  dirortho[2] = 0;
+       s1[0] = -dir[1]*8 + dir[0]*8;
+       s2[0] = dir[1]*8 + dir[0]*8;
+       s1[1] = dir[0]*8 + dir[1]*8;
+@@ -334,8 +350,13 @@
+       qglColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
+ 
+       qglBegin(GL_LINES);
+-      qglVertex3fv(mid);
+-      qglVertex3fv(mid1);
++	  for(i = -lines + 1; i < lines; i += 2)
++	  {
++		  VectorMA(mid, i, dirortho, v);
++		  qglVertex3fv(v);
++		  VectorMA(mid1, i, dirortho, v);
++		  qglVertex3fv(v);
++	  }
+ 
+       arrows = (int)(len / 256) + 1;
+ 
+Index: radiant/targetname.cpp
+===================================================================
+--- radiant/targetname.cpp	(revision 304)
++++ radiant/targetname.cpp	(working copy)
+@@ -24,11 +24,11 @@
+ /*!
+ connects two entities creating a unique target/targetname value 
+ */
+-void Entity_Connect(entity_t *e1, entity_t *e2)
++void Entity_Connect(entity_t *e1, entity_t *e2, bool kill)
+ {
+   const char *maptarget;
+   char newtarget[16];
+-  int maxtarget=0;  // highest t# value in the map
++  int id=0;  // highest t# value in the map
+   entity_t *e;      // map entities
+ 
+   if (e1 == e2)
+@@ -39,47 +39,54 @@
+ 		return;
+ 	}
+ 
+-  for (e=entities.next ; e != &entities ; e=e->next)
+-  {
+-    maptarget = ValueForKey (e, "target");
+-    if (maptarget && maptarget[0])
+-    {
+-      int targetnum = atoi(maptarget+1);
+-      if (targetnum > maxtarget)
+-        maxtarget = targetnum;
+-    }
+-  }
+-  sprintf (newtarget, "t%i", maxtarget+1);
++	id = GetUniqueTargetId(1);
++	sprintf (newtarget, "t%i", id);
+   
+ #ifdef _DEBUG
+   Sys_Printf("Connecting entities with new target/targetname: %s\n", newtarget);
+ #endif  
+   
+-	SetKeyValue (e1, "target", newtarget);
++  	if(kill)
++		SetKeyValue (e1, "killtarget", newtarget);
++	else
++		SetKeyValue (e1, "target", newtarget);
+ 	SetKeyValue (e2, "targetname", newtarget);
+ }
+ 
++static int TargetIdForKey(entity_t *pe, const char *key)
++{
++	const char *p = ValueForKey(pe, key);
++	if(!p)
++		return 0;
++	if(!*p)
++		return 0;
++	return atoi(p + 1);
++}
++
+ int GetUniqueTargetId(int iHint)
+ {
+-	int iMin, iMax, i;
++	int iMax, i;
+ 	bool fFound;
+ 	entity_t *pe;
+ 	
+ 	fFound = FALSE;
+ 	pe = entities.next;
+-	iMin = 0; 
+ 	iMax = 0;
+ 	
+ 	for (; pe != NULL && pe != &entities ; pe = pe->next)
+ 	{
+-		i = IntForKey(pe, "target");
+-		if (i)
+-		{
+-			iMin = MIN(i, iMin);
+-			iMax = MAX(i, iMax);
+-			if (i == iHint)
+-				fFound = TRUE;
+-		}
++		i = TargetIdForKey(pe, "target");
++		iMax = MAX(i, iMax);
++		if (i == iHint)
++			fFound = TRUE;
++		i = TargetIdForKey(pe, "targetname");
++		iMax = MAX(i, iMax);
++		if (i == iHint)
++			fFound = TRUE;
++		i = TargetIdForKey(pe, "killtarget");
++		iMax = MAX(i, iMax);
++		if (i == iHint)
++			fFound = TRUE;
+ 	}
+ 
+ 	if (fFound)
+Index: radiant/qe3.cpp
+===================================================================
+--- radiant/qe3.cpp	(revision 304)
++++ radiant/qe3.cpp	(working copy)
+@@ -704,7 +704,7 @@
+ from the first selected to the secon
+ ===============
+ */
+-void ConnectEntities (void)
++void ConnectEntities (bool kill)
+ {
+ 	entity_t	*e1, *e2;
+ 	const char		*target;
+@@ -734,7 +734,7 @@
+ 		return;
+ 	}
+ 
+-  target = ValueForKey (e1, "target");
++  target = ValueForKey (e1, kill ? "killtarget" : "target");
+   if (target && target[0])
+     newtarg = g_strdup(target);
+   else
+@@ -743,12 +743,12 @@
+     if(target && target[0])
+       newtarg = g_strdup(target);
+     else
+-      Entity_Connect(e1, e2);
++      Entity_Connect(e1, e2, kill);
+   }
+ 
+   if(newtarg != NULL)
+   {
+-    SetKeyValue(e1, "target", newtarg);
++    SetKeyValue(e1, kill ? "killtarget" : "target", newtarg);
+     SetKeyValue(e2, "targetname", newtarg);
+     g_free(newtarg);
+   }
+Index: radiant/qe3.h
+===================================================================
+--- radiant/qe3.h	(revision 304)
++++ radiant/qe3.h	(working copy)
+@@ -229,7 +229,7 @@
+ void SelectEdgeByRay (vec3_t org, vec3_t dir);
+ void SelectVertexByRay (vec3_t org, vec3_t dir);
+ 
+-void ConnectEntities (void);
++void ConnectEntities (bool kill = false);
+ 
+ extern	int	update_bits;
+ 
+@@ -878,7 +878,7 @@
+ 
+ // SPoG
+ // targetname.cpp
+-void Entity_Connect(entity_t *e1, entity_t *e2);
++void Entity_Connect(entity_t *e1, entity_t *e2, bool kill = false);
+ int GetUniqueTargetId(int iHint);
+ 
+ // xywindow.cpp
 Index: tools/quake3/q3map2/convert_map.c
 ===================================================================
 --- tools/quake3/q3map2/convert_map.c	(revision 191)
@@ -1827,4 +2308,4 @@
 +++ include/version.default	(working copy)
 @@ -1 +1 @@
 -1.4.0
-+1.4.0-div0-obj
++1.4.0-div0-obj-targetname

Copied: branches/nexuiz-2.0/misc/gtkradiant/singlepatches/gtkradiant-targetname.diff (from rev 4246, trunk/misc/gtkradiant/singlepatches/gtkradiant-targetname.diff)
===================================================================
--- branches/nexuiz-2.0/misc/gtkradiant/singlepatches/gtkradiant-targetname.diff	                        (rev 0)
+++ branches/nexuiz-2.0/misc/gtkradiant/singlepatches/gtkradiant-targetname.diff	2008-08-29 18:32:01 UTC (rev 4247)
@@ -0,0 +1,481 @@
+Index: radiant/map.cpp
+===================================================================
+--- radiant/map.cpp	(revision 304)
++++ radiant/map.cpp	(working copy)
+@@ -270,6 +270,100 @@
+   ents->RemoveAll();
+ }
+ 
++void Map_DoTargetFix(entity_t *e, const char *target, int num_ents, CPtrArray *ents, GPtrArray *new_ents)
++{
++	int j;
++	int id;
++	char newtarget[128];
++	entity_t *e_target;
++
++	qboolean targetnameFound = FALSE;
++	qboolean targetFound = FALSE;
++	qboolean colliding = FALSE;
++
++	if(!target)
++		return;
++	if(!*target)
++		return;
++
++	target = g_strdup(target);
++
++	// check the current map entities for an actual collision
++	for (e_target = entities.next; e_target != &entities; e_target = e_target->next)
++	{
++		if(
++			!strcmp(target, ValueForKey(e_target, "target"))
++			||
++			!strcmp(target, ValueForKey(e_target, "killtarget"))
++		)
++		{
++			// make sure the collision is not between two imported entities
++			for(j=0; j<(int)new_ents->len; j++)
++			{
++				if(e_target == g_ptr_array_index(new_ents, j))
++				{
++					targetFound = true;
++					goto no_collision_yet_1;
++				}
++			}
++			colliding = TRUE;
++no_collision_yet_1:
++			;
++		}
++		if(
++			!strcmp(target, ValueForKey(e_target, "targetname"))
++		)
++		{
++			// make sure the collision is not between two imported entities
++			for(j=0; j<(int)new_ents->len; j++)
++			{
++				if(e_target == g_ptr_array_index(new_ents, j))
++				{
++					targetnameFound = true;
++					goto no_collision_yet_2;
++				}
++			}
++			colliding = TRUE;
++no_collision_yet_2:
++			;
++		}
++	}
++
++	// find the matching targeted entity(s)
++	if(colliding && targetFound && targetnameFound)
++	{
++		// We got a collision
++		// first look for a non-conflicting target name
++		id = GetUniqueTargetId(1);
++		sprintf(newtarget, "t%i", id);
++
++		for(j=num_ents-1; j>0; j--)
++		{
++			e_target = (entity_t*)ents->GetAt(j);
++			if(e_target != NULL)
++			{
++				const char *targetname = ValueForKey(e_target, "targetname");
++				if( (targetname != NULL) && (strcmp(target, targetname) == 0) ) 
++				{
++					SetKeyValue(e_target, "targetname", newtarget);
++				}
++				targetname = ValueForKey(e_target, "target");
++				if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
++				{
++					SetKeyValue(e_target, "target", newtarget);
++				}
++				targetname = ValueForKey(e_target, "killtarget");
++				if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
++				{
++					SetKeyValue(e_target, "killtarget", newtarget);
++				}
++			}
++		}
++	}
++
++	g_free(target);
++}
++
+ /*!\todo Possibly make the import Undo-friendly by calling Undo_End for new brushes and ents */
+ void Map_ImportEntities(CPtrArray *ents, bool bAddSelected = false)
+ {
+@@ -466,60 +560,27 @@
+     }
+     else
+     {
+-      // fix target/targetname collisions
+-      if ((g_PrefsDlg.m_bDoTargetFix) && (strcmp(ValueForKey(e, "target"), "") != 0))
+-      {
+-        GPtrArray *t_ents = g_ptr_array_new();
+-        entity_t *e_target;
+-        const char *target = ValueForKey(e, "target");
+-        qboolean bCollision=FALSE;
++      // keep a list of ents added to avoid testing collisions against them
++      g_ptr_array_add(new_ents, (gpointer)e);
+ 
+-        // check the current map entities for an actual collision
+-        for (e_target = entities.next; e_target != &entities; e_target = e_target->next)
+-        {
+-          if(!strcmp(target, ValueForKey(e_target, "target")))
+-          {
+-            bCollision = TRUE;
+-            // make sure the collision is not between two imported entities
+-            for(j=0; j<(int)new_ents->len; j++)
+-            {
+-              if(e_target == g_ptr_array_index(new_ents, j))
+-                bCollision = FALSE;
+-            }
+-          }
+-        }
+-
+-        // find the matching targeted entity(s)
+-        if(bCollision)
+-        {
+-          for(j=num_ents-1; j>0; j--)
+-          {
+-            e_target = (entity_t*)ents->GetAt(j);
+-            if(e_target != NULL && e_target != e)
+-            {
+-              const char *targetname = ValueForKey(e_target, "targetname");
+-              if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
+-                g_ptr_array_add(t_ents, (gpointer)e_target);
+-            }
+-          }
+-          if(t_ents->len > 0)
+-          {
+-            // link the first to get a unique target/targetname
+-            Entity_Connect(e, (entity_t*)g_ptr_array_index(t_ents,0));
+-            // set the targetname of the rest of them manually
+-            for(j = 1; j < (int)t_ents->len; j++)
+-              SetKeyValue( (entity_t*)g_ptr_array_index(t_ents, j), "targetname", ValueForKey(e, "target") );
+-          }
+-          g_ptr_array_free(t_ents, FALSE);
+-        }
+-      }
+-
+       // add the entity to the end of the entity list
+       Entity_AddToList(e, &entities);
+       g_qeglobals.d_num_entities++;
+ 
+-      // keep a list of ents added to avoid testing collisions against them
+-      g_ptr_array_add(new_ents, (gpointer)e);
++      // fix target/targetname collisions
++      if (g_PrefsDlg.m_bDoTargetFix)
++	  {
++		  const char *target;
++
++		  target = ValueForKey(e, "target");
++		  Map_DoTargetFix(e, target, num_ents, ents, new_ents);
++
++		  target = ValueForKey(e, "killtarget");
++		  Map_DoTargetFix(e, target, num_ents, ents, new_ents);
++
++		  target = ValueForKey(e, "targetname");
++		  Map_DoTargetFix(e, target, num_ents, ents, new_ents);
++	  }
+     }
+   }
+   g_ptr_array_free(new_ents, FALSE);
+Index: radiant/drag.cpp
+===================================================================
+--- radiant/drag.cpp	(revision 304)
++++ radiant/drag.cpp	(working copy)
+@@ -255,54 +255,6 @@
+ 
+ entity_t *peLink;
+ 
+-void UpdateTarget(vec3_t origin, vec3_t dir)
+-{
+-	trace_t	t;
+-	entity_t *pe;
+-	int i;
+-	char sz[128];
+-
+-	t = Test_Ray (origin, dir, 0);
+-
+-	if (!t.brush)
+-		return;
+-
+-	pe = t.brush->owner;
+-
+-	if (pe == NULL)
+-		return;
+-
+-	// is this the first?
+-	if (peLink != NULL)
+-	{
+-
+-		// Get the target id from out current target
+-		// if there is no id, make one
+-
+-		i = IntForKey(pe, "target");
+-		if (i <= 0)
+-		{
+-			i = GetUniqueTargetId(1);
+-			sprintf(sz, "%d", i);
+-
+-			SetKeyValue(pe, "target", sz);
+-		}
+-
+-		// set the target # into our src
+-
+-		sprintf(sz, "%d", i);
+-		SetKeyValue(peLink, "targetname", sz);
+-
+-		Sys_UpdateWindows(W_ENTITY);
+-
+-	}
+-
+-	// promote the target to the src
+-
+-	peLink = pe;
+-
+-}
+-
+ /*
+ ===========
+ Drag_Begin
+Index: radiant/xywindow.cpp
+===================================================================
+--- radiant/xywindow.cpp	(revision 304)
++++ radiant/xywindow.cpp	(working copy)
+@@ -270,16 +270,17 @@
+ void DrawPathLines (void)
+ {
+   int       i, j, k;
+-  vec3_t    mid, mid1;
++  vec3_t    mid, mid1, v;
+   entity_t *se, *te;
+   brush_t   *sb, *tb;
+   const char    *psz;
+-  vec3_t    dir, s1, s2;
++  vec3_t    dir, s1, s2, dirortho;
+   vec_t len, f;
+   int       arrows;
+   int           num_entities;
+   const char        *ent_target[MAX_MAP_ENTITIES];
+   entity_t  *ent_entity[MAX_MAP_ENTITIES];
++  int lines;
+ 
+   if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
+   {
+@@ -295,6 +296,12 @@
+       ent_entity[num_entities] = te;
+       num_entities++;
+     }
++    ent_target[num_entities] = ValueForKey (te, "killtarget");
++    if (ent_target[num_entities][0])
++    {
++      ent_entity[num_entities] = te;
++      num_entities++;
++    }
+   }
+ 
+   for (se = entities.next ; se != &entities ; se = se->next)
+@@ -308,6 +315,9 @@
+     if (sb == &se->brushes)
+       continue;
+ 
++	for (i=0 ; i<3 ; i++)
++		mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
++
+     for (k=0 ; k<num_entities ; k++)
+     {
+       if (strcmp (ent_target[k], psz))
+@@ -318,14 +328,20 @@
+       if (tb == &te->brushes)
+         continue;
+ 
+-      for (i=0 ; i<3 ; i++)
+-        mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
++	  lines = 0;
++	  if(!strcmp(ValueForKey(te, "target"), psz))
++		  lines += 1;
++	  if(!strcmp(ValueForKey(te, "killtarget"), psz))
++		  lines += 2;
+ 
+       for (i=0 ; i<3 ; i++)
+         mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5;
+ 
+       VectorSubtract (mid1, mid, dir);
+       len = VectorNormalize (dir, dir);
++	  dirortho[0] = -dir[1];
++	  dirortho[1] = dir[0];
++	  dirortho[2] = 0;
+       s1[0] = -dir[1]*8 + dir[0]*8;
+       s2[0] = dir[1]*8 + dir[0]*8;
+       s1[1] = dir[0]*8 + dir[1]*8;
+@@ -334,8 +350,13 @@
+       qglColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
+ 
+       qglBegin(GL_LINES);
+-      qglVertex3fv(mid);
+-      qglVertex3fv(mid1);
++	  for(i = -lines + 1; i < lines; i += 2)
++	  {
++		  VectorMA(mid, i, dirortho, v);
++		  qglVertex3fv(v);
++		  VectorMA(mid1, i, dirortho, v);
++		  qglVertex3fv(v);
++	  }
+ 
+       arrows = (int)(len / 256) + 1;
+ 
+Index: radiant/targetname.cpp
+===================================================================
+--- radiant/targetname.cpp	(revision 304)
++++ radiant/targetname.cpp	(working copy)
+@@ -24,11 +24,11 @@
+ /*!
+ connects two entities creating a unique target/targetname value 
+ */
+-void Entity_Connect(entity_t *e1, entity_t *e2)
++void Entity_Connect(entity_t *e1, entity_t *e2, bool kill)
+ {
+   const char *maptarget;
+   char newtarget[16];
+-  int maxtarget=0;  // highest t# value in the map
++  int id=0;  // highest t# value in the map
+   entity_t *e;      // map entities
+ 
+   if (e1 == e2)
+@@ -39,47 +39,54 @@
+ 		return;
+ 	}
+ 
+-  for (e=entities.next ; e != &entities ; e=e->next)
+-  {
+-    maptarget = ValueForKey (e, "target");
+-    if (maptarget && maptarget[0])
+-    {
+-      int targetnum = atoi(maptarget+1);
+-      if (targetnum > maxtarget)
+-        maxtarget = targetnum;
+-    }
+-  }
+-  sprintf (newtarget, "t%i", maxtarget+1);
++	id = GetUniqueTargetId(1);
++	sprintf (newtarget, "t%i", id);
+   
+ #ifdef _DEBUG
+   Sys_Printf("Connecting entities with new target/targetname: %s\n", newtarget);
+ #endif  
+   
+-	SetKeyValue (e1, "target", newtarget);
++  	if(kill)
++		SetKeyValue (e1, "killtarget", newtarget);
++	else
++		SetKeyValue (e1, "target", newtarget);
+ 	SetKeyValue (e2, "targetname", newtarget);
+ }
+ 
++static int TargetIdForKey(entity_t *pe, const char *key)
++{
++	const char *p = ValueForKey(pe, key);
++	if(!p)
++		return 0;
++	if(!*p)
++		return 0;
++	return atoi(p + 1);
++}
++
+ int GetUniqueTargetId(int iHint)
+ {
+-	int iMin, iMax, i;
++	int iMax, i;
+ 	bool fFound;
+ 	entity_t *pe;
+ 	
+ 	fFound = FALSE;
+ 	pe = entities.next;
+-	iMin = 0; 
+ 	iMax = 0;
+ 	
+ 	for (; pe != NULL && pe != &entities ; pe = pe->next)
+ 	{
+-		i = IntForKey(pe, "target");
+-		if (i)
+-		{
+-			iMin = MIN(i, iMin);
+-			iMax = MAX(i, iMax);
+-			if (i == iHint)
+-				fFound = TRUE;
+-		}
++		i = TargetIdForKey(pe, "target");
++		iMax = MAX(i, iMax);
++		if (i == iHint)
++			fFound = TRUE;
++		i = TargetIdForKey(pe, "targetname");
++		iMax = MAX(i, iMax);
++		if (i == iHint)
++			fFound = TRUE;
++		i = TargetIdForKey(pe, "killtarget");
++		iMax = MAX(i, iMax);
++		if (i == iHint)
++			fFound = TRUE;
+ 	}
+ 
+ 	if (fFound)
+Index: radiant/qe3.cpp
+===================================================================
+--- radiant/qe3.cpp	(revision 304)
++++ radiant/qe3.cpp	(working copy)
+@@ -704,7 +704,7 @@
+ from the first selected to the secon
+ ===============
+ */
+-void ConnectEntities (void)
++void ConnectEntities (bool kill)
+ {
+ 	entity_t	*e1, *e2;
+ 	const char		*target;
+@@ -734,7 +734,7 @@
+ 		return;
+ 	}
+ 
+-  target = ValueForKey (e1, "target");
++  target = ValueForKey (e1, kill ? "killtarget" : "target");
+   if (target && target[0])
+     newtarg = g_strdup(target);
+   else
+@@ -743,12 +743,12 @@
+     if(target && target[0])
+       newtarg = g_strdup(target);
+     else
+-      Entity_Connect(e1, e2);
++      Entity_Connect(e1, e2, kill);
+   }
+ 
+   if(newtarg != NULL)
+   {
+-    SetKeyValue(e1, "target", newtarg);
++    SetKeyValue(e1, kill ? "killtarget" : "target", newtarg);
+     SetKeyValue(e2, "targetname", newtarg);
+     g_free(newtarg);
+   }
+Index: radiant/qe3.h
+===================================================================
+--- radiant/qe3.h	(revision 304)
++++ radiant/qe3.h	(working copy)
+@@ -229,7 +229,7 @@
+ void SelectEdgeByRay (vec3_t org, vec3_t dir);
+ void SelectVertexByRay (vec3_t org, vec3_t dir);
+ 
+-void ConnectEntities (void);
++void ConnectEntities (bool kill = false);
+ 
+ extern	int	update_bits;
+ 
+@@ -878,7 +878,7 @@
+ 
+ // SPoG
+ // targetname.cpp
+-void Entity_Connect(entity_t *e1, entity_t *e2);
++void Entity_Connect(entity_t *e1, entity_t *e2, bool kill = false);
+ int GetUniqueTargetId(int iHint);
+ 
+ // xywindow.cpp




More information about the nexuiz-commits mailing list