[nexuiz-commits] r8687 - in trunk/data/qcsrc: . client common server warpzonelib

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Sun Feb 28 14:42:26 EST 2010


Author: div0
Date: 2010-02-28 14:42:26 -0500 (Sun, 28 Feb 2010)
New Revision: 8687

Added:
   trunk/data/qcsrc/warpzonelib/
   trunk/data/qcsrc/warpzonelib/COPYING
   trunk/data/qcsrc/warpzonelib/anglestransform.qc
   trunk/data/qcsrc/warpzonelib/anglestransform.qh
   trunk/data/qcsrc/warpzonelib/client.qc
   trunk/data/qcsrc/warpzonelib/client.qh
   trunk/data/qcsrc/warpzonelib/common.qc
   trunk/data/qcsrc/warpzonelib/common.qh
   trunk/data/qcsrc/warpzonelib/server.qc
   trunk/data/qcsrc/warpzonelib/server.qh
   trunk/data/qcsrc/warpzonelib/util_server.qc
   trunk/data/qcsrc/warpzonelib/util_server.qh
Modified:
   trunk/data/qcsrc/client/Main.qc
   trunk/data/qcsrc/client/View.qc
   trunk/data/qcsrc/client/progs.src
   trunk/data/qcsrc/common/util.qc
   trunk/data/qcsrc/common/util.qh
   trunk/data/qcsrc/server/miscfunctions.qc
   trunk/data/qcsrc/server/portals.qc
   trunk/data/qcsrc/server/progs.src
   trunk/data/qcsrc/server/t_teleporters.qc
   trunk/data/qcsrc/server/w_campingrifle.qc
Log:
warpzonelib - the beginning
NOTE: this patch breaks something on CLIENT side.

Modified: trunk/data/qcsrc/client/Main.qc
===================================================================
--- trunk/data/qcsrc/client/Main.qc	2010-02-28 19:42:21 UTC (rev 8686)
+++ trunk/data/qcsrc/client/Main.qc	2010-02-28 19:42:26 UTC (rev 8687)
@@ -839,51 +839,6 @@
 	psrandom(s);
 }
 
-float FL_CAMERA = 8192;
-.vector warpzone_transform;
-void Ent_WarpZone(float isnew)
-{
-	if not(self.enemy)
-	{
-		self.enemy = spawn();
-		self.enemy.classname = "warpzone_from";
-	}
-	self.classname = "warpzone_to";
-	self.origin_x = ReadCoord();
-	self.origin_y = ReadCoord();
-	self.origin_z = ReadCoord();
-	self.modelindex = ReadShort();
-	self.mins_x = ReadCoord();
-	self.mins_y = ReadCoord();
-	self.mins_z = ReadCoord();
-	self.maxs_x = ReadCoord();
-	self.maxs_y = ReadCoord();
-	self.maxs_z = ReadCoord();
-	self.enemy.oldorigin_x = ReadCoord();
-	self.enemy.oldorigin_y = ReadCoord();
-	self.enemy.oldorigin_z = ReadCoord();
-	self.enemy.avelocity_x = ReadCoord();
-	self.enemy.avelocity_y = ReadCoord();
-	self.enemy.avelocity_z = ReadCoord();
-	self.oldorigin_x = ReadCoord();
-	self.oldorigin_y = ReadCoord();
-	self.oldorigin_z = ReadCoord();
-	self.avelocity_x = ReadCoord();
-	self.avelocity_y = ReadCoord();
-	self.avelocity_z = ReadCoord();
-
-	self.avelocity = AnglesTransform_TurnDirection(self.avelocity);
-	self.warpzone_transform = AnglesTransform_Divide(self.avelocity, self.enemy.avelocity);
-
-	self.flags = FL_CAMERA;
-	self.drawmask = MASK_NORMAL;
-
-	// link me
-	//setmodel(self, self.model);
-	setorigin(self, self.origin);
-	setsize(self, self.mins, self.maxs);
-}
-
 // CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
 // The only parameter reflects if the entity is "new" to the client, meaning it just came into the client's PVS.
 void Ent_RadarLink();
@@ -941,7 +896,7 @@
 		case ENT_CLIENT_WALL: Ent_Wall(); break;
 		case ENT_CLIENT_MODELEFFECT: Ent_ModelEffect(bIsNewEntity); break;
 		case ENT_CLIENT_TUBANOTE: Ent_TubaNote(bIsNewEntity); break;
-		case ENT_CLIENT_WARPZONE: Ent_WarpZone(bIsNewEntity); break;
+		case ENT_CLIENT_WARPZONE: WarpZone_Read(bIsNewEntity); break;
 		default:
 			error(strcat("unknown entity type in CSQC_Ent_Update: ", ftos(self.enttype), "\n"));
 			break;

Modified: trunk/data/qcsrc/client/View.qc
===================================================================
--- trunk/data/qcsrc/client/View.qc	2010-02-28 19:42:21 UTC (rev 8686)
+++ trunk/data/qcsrc/client/View.qc	2010-02-28 19:42:26 UTC (rev 8687)
@@ -358,22 +358,11 @@
 	ticrate = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
 	vo = '0 0 1' * getstati(STAT_VIEWHEIGHT);
 
-	// if view origin is INSIDE a warpzone, we are screwed and must
-	// temporarily move the origin to the other side of the warp
-	pmove_org = pmove_org + vo;
-	for(e = world; (e = find(e, classname, "warpzone_to")); )
-	{
-		//print(sprintf("does %s (%s to %s) touch %s?\n", e.model, vtos(e.absmin), vtos(e.absmax), vtos(pmove_org)));
-		if(BoxTouchesBrush(pmove_org, pmove_org, e, world))
-		{
-			pmove_org = AnglesTransform_Apply(e.warpzone_transform, pmove_org - e.enemy.oldorigin) + e.oldorigin;
-			input_angles = AnglesTransform_Multiply(e.warpzone_transform, input_angles);
-			R_SetView(VF_ORIGIN, pmove_org);
-			R_SetView(VF_ANGLES, input_angles);
-			break;
-		}
-	}
-	pmove_org = pmove_org - vo;
+	warpzone_fixview_origin = pmove_org + vo;
+	warpzone_fixview_angles = input_angles;
+	WarpZone_FixView();
+	pmove_org = warpzone_fixview_origin - vo;
+	input_angles = warpzone_fixview_angles;
 
 	// Render the Scene
 	if(!intermission || !view_set)

Modified: trunk/data/qcsrc/client/progs.src
===================================================================
--- trunk/data/qcsrc/client/progs.src	2010-02-28 19:42:21 UTC (rev 8686)
+++ trunk/data/qcsrc/client/progs.src	2010-02-28 19:42:26 UTC (rev 8687)
@@ -6,6 +6,11 @@
 csqc_constants.qc
 ../common/constants.qh
 csqc_builtins.qc
+
+../warpzonelib/anglestransform.qh
+../warpzonelib/common.qh
+../warpzonelib/client.qh
+
 ../common/mathlib.qh
 ../common/util.qh
 ../common/items.qh
@@ -61,3 +66,7 @@
 ../common/items.qc
 
 ../common/mathlib.qc
+
+../warpzonelib/anglestransform.qc
+../warpzonelib/common.qc
+../warpzonelib/client.qc

Modified: trunk/data/qcsrc/common/util.qc
===================================================================
--- trunk/data/qcsrc/common/util.qc	2010-02-28 19:42:21 UTC (rev 8686)
+++ trunk/data/qcsrc/common/util.qc	2010-02-28 19:42:26 UTC (rev 8687)
@@ -686,13 +686,6 @@
 	traceline(v0 + dvy + dvz, v0 + dvx + dvy + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
 	return 1;
 }
-
-void fixedmakevectors(vector a)
-{
-	// a makevectors that actually inverts vectoangles
-	a_x = -a_x;
-	makevectors(a);
-}
 #endif
 
 string fixPriorityList(string order, float from, float to, float subtract, float complete)
@@ -1211,53 +1204,6 @@
 float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins_x >= bmins_x && smaxs_x <= bmaxs_x && smins_y >= bmins_y && smaxs_y <= bmaxs_y && smins_z >= bmins_z && smaxs_z <= bmaxs_z;};
 
 #ifndef MENUQC
-// angles transforms
-// angles in fixedmakevectors/fixedvectoangles space
-vector AnglesTransform_Apply(vector transform, vector v)
-{
-	fixedmakevectors(transform);
-	return v_forward * v_x
-	     + v_right   * (-v_y)
-		 + v_up      * v_z;
-}
-
-vector AnglesTransform_Multiply(vector t1, vector t2)
-{
-	vector m_forward, m_up;
-	fixedmakevectors(t2); m_forward = v_forward; m_up = v_up;
-	m_forward = AnglesTransform_Apply(t1, m_forward); m_up = AnglesTransform_Apply(t1, m_up);
-	return fixedvectoangles2(m_forward, m_up);
-}
-
-vector AnglesTransform_Invert(vector transform)
-{
-	vector i_forward, i_up;
-	fixedmakevectors(transform);
-	// we want angles that turn v_forward into '1 0 0', v_right into '0 1 0' and v_up into '0 0 1'
-	// but these are orthogonal unit vectors!
-	// so to invert, we can simply fixedvectoangles the TRANSPOSED matrix
-	// TODO is this always -transform?
-	i_forward_x = v_forward_x;
-	i_forward_y = -v_right_x;
-	i_forward_z = v_up_x;
-	i_up_x = v_forward_z;
-	i_up_y = -v_right_z;
-	i_up_z = v_up_z;
-	return fixedvectoangles2(i_forward, i_up);
-}
-
-vector AnglesTransform_TurnDirection(vector transform)
-{
-	// turn 180 degrees around v_up
-	// changes in-direction to out-direction
-	fixedmakevectors(transform);
-	return fixedvectoangles2(-1 * v_forward, 1 * v_up);
-}
-
-vector AnglesTransform_Divide(vector to_transform, vector from_transform)
-{
-	return AnglesTransform_Multiply(to_transform, AnglesTransform_Invert(from_transform));
-}
 #endif
 
 float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLengthUpToWidth_widthFunction_t w)

Modified: trunk/data/qcsrc/common/util.qh
===================================================================
--- trunk/data/qcsrc/common/util.qh	2010-02-28 19:42:21 UTC (rev 8686)
+++ trunk/data/qcsrc/common/util.qh	2010-02-28 19:42:26 UTC (rev 8687)
@@ -77,10 +77,6 @@
 
 #ifndef MENUQC
 float CheckWireframeBox(entity forent, vector v0, vector dvx, vector dvy, vector dvz);
-
-void fixedmakevectors(vector a);
-#define fixedvectoangles2 vectoangles2
-#define fixedvectoangles vectoangles
 #endif
 
 string fixPriorityList(string pl, float from, float to, float subtract, float complete);
@@ -132,14 +128,6 @@
 float boxesoverlap(vector m1, vector m2, vector m3, vector m4);
 float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs);
 
-#ifndef MENUQC
-vector AnglesTransform_Apply(vector transform, vector v);
-vector AnglesTransform_Multiply(vector t1, vector t2);
-vector AnglesTransform_Invert(vector transform);
-vector AnglesTransform_TurnDirection(vector transform);
-vector AnglesTransform_Divide(vector to_transform, vector from_transform);
-#endif
-
 typedef float(string s, vector size) textLengthUpToWidth_widthFunction_t;
 typedef float(string s) textLengthUpToLength_lenFunction_t;
 float textLengthUpToWidth(string theText, float maxWidth, vector size, textLengthUpToWidth_widthFunction_t tw);

Modified: trunk/data/qcsrc/server/miscfunctions.qc
===================================================================
--- trunk/data/qcsrc/server/miscfunctions.qc	2010-02-28 19:42:21 UTC (rev 8686)
+++ trunk/data/qcsrc/server/miscfunctions.qc	2010-02-28 19:42:26 UTC (rev 8687)
@@ -51,61 +51,9 @@
     return f;
 }
 
-void move_out_of_solid_expand(entity e, vector by)
-{
-    float eps = 0.0625;
-    tracebox(e.origin, e.mins - '1 1 1' * eps, e.maxs + '1 1 1' * eps, e.origin + by, MOVE_WORLDONLY, e);
-    if (trace_startsolid)
-        return;
-    if (trace_fraction < 1)
-    {
-        // hit something
-        // adjust origin in the other direction...
-        setorigin(e,e.origin - by * (1 - trace_fraction));
-    }
-}
+#define move_out_of_solid(e) WarpZoneLib_MoveOutOfSolid(e)
 
-float move_out_of_solid(entity e)
-{
-    vector o, m0, m1;
 
-    o = e.origin;
-    traceline(o, o, MOVE_WORLDONLY, e);
-    if (trace_startsolid)
-        return 0;
-
-    tracebox(o, e.mins, e.maxs, o, MOVE_WORLDONLY, e);
-    if (!trace_startsolid)
-        return 1;
-
-    m0 = e.mins;
-    m1 = e.maxs;
-    e.mins = '0 0 0';
-    e.maxs = '0 0 0';
-    move_out_of_solid_expand(e, '1 0 0' * m0_x);
-    e.mins_x = m0_x;
-    move_out_of_solid_expand(e, '1 0 0' * m1_x);
-    e.maxs_x = m1_x;
-    move_out_of_solid_expand(e, '0 1 0' * m0_y);
-    e.mins_y = m0_y;
-    move_out_of_solid_expand(e, '0 1 0' * m1_y);
-    e.maxs_y = m1_y;
-    move_out_of_solid_expand(e, '0 0 1' * m0_z);
-    e.mins_z = m0_z;
-    move_out_of_solid_expand(e, '0 0 1' * m1_z);
-    e.maxs_z = m1_z;
-    setorigin(e, e.origin);
-
-    tracebox(e.origin, e.mins, e.maxs, e.origin, MOVE_WORLDONLY, e);
-    if (trace_startsolid)
-    {
-        setorigin(e, o);
-        return 0;
-    }
-
-    return 1;
-}
-
 string STR_PLAYER = "player";
 string STR_SPECTATOR = "spectator";
 string STR_OBSERVER = "observer";

Modified: trunk/data/qcsrc/server/portals.qc
===================================================================
--- trunk/data/qcsrc/server/portals.qc	2010-02-28 19:42:21 UTC (rev 8686)
+++ trunk/data/qcsrc/server/portals.qc	2010-02-28 19:42:26 UTC (rev 8687)
@@ -351,7 +351,7 @@
 
 void Portal_Connect(entity teleporter, entity destination)
 {
-	teleporter.portal_transform = AnglesTransform_Divide(AnglesTransform_TurnDirection(destination.angles), teleporter.angles);
+	teleporter.portal_transform = AnglesTransform_Divide(AnglesTransform_TurnDirectionFR(destination.angles), teleporter.angles);
 
 	teleporter.enemy = destination;
 	destination.enemy = teleporter;

Modified: trunk/data/qcsrc/server/progs.src
===================================================================
--- trunk/data/qcsrc/server/progs.src	2010-02-28 19:42:21 UTC (rev 8686)
+++ trunk/data/qcsrc/server/progs.src	2010-02-28 19:42:26 UTC (rev 8687)
@@ -6,6 +6,12 @@
 builtins.qh
 extensions.qh
 post-builtins.qh
+
+../warpzonelib/anglestransform.qh
+../warpzonelib/common.qh
+../warpzonelib/util_server.qh
+../warpzonelib/server.qh
+
 ../common/mathlib.qh
 constants.qh
 ../common/constants.qh
@@ -165,3 +171,8 @@
 
 anticheat.qc
 cheats.qc
+
+../warpzonelib/anglestransform.qc
+../warpzonelib/common.qc
+../warpzonelib/util_server.qc
+../warpzonelib/server.qc

Modified: trunk/data/qcsrc/server/t_teleporters.qc
===================================================================
--- trunk/data/qcsrc/server/t_teleporters.qc	2010-02-28 19:42:21 UTC (rev 8686)
+++ trunk/data/qcsrc/server/t_teleporters.qc	2010-02-28 19:42:26 UTC (rev 8687)
@@ -298,199 +298,19 @@
 	}
 }
 
-
-// the transform
-.vector warpzone_origin, warpzone_angles;
-.vector warpzone_forward;
-.vector warpzone_transform;
-
-void warpzone_updatetransform()
+void WarpZone_PostTeleportPlayer(entity pl)
 {
-	if(!self.enemy || self.enemy.enemy != self)
+	UpdateCSQCProjectileAfterTeleport(pl);
+	if(pl.classname == "player")
 	{
-		objerror("Invalid warp zone detected. Killed.");
-		return;
+		// reset tracking of oldvelocity for impact damage (sudden velocity changes)
+		pl.oldvelocity = pl.velocity;
 	}
-
-	// 1. update this, and the enemy, warp zone
-	self.warpzone_origin = self.aiment.origin;
-	self.warpzone_angles = self.aiment.angles;
-	self.enemy.warpzone_origin = self.enemy.aiment.origin;
-	self.enemy.warpzone_angles = self.enemy.aiment.angles;
-
-	// 2. combine the angle transforms
-	//    current forward must be turned into previous backward
-	self.warpzone_transform = AnglesTransform_Divide(AnglesTransform_TurnDirection(self.enemy.warpzone_angles), self.warpzone_angles);
-
-	// 3. store off a saved forward vector for plane hit decisions
-	fixedmakevectors(self.warpzone_angles);
-	self.warpzone_forward = v_forward;
 }
 
-float warpzone_teleport(entity player)
-{
-	vector o0, a0, v0, o1, a1, v1;
-
-	o0 = player.origin + player.view_ofs;
-	v0 = player.velocity;
-	a0 = player.angles;
-
-	if((o0 - self.warpzone_origin) * self.warpzone_forward >= 0) // wrong side of the portal
-		return 2;
-		// no failure, we simply don't want to teleport yet; TODO in
-		// this situation we may want to create a temporary clone
-		// entity of the player to fix graphics glitch
-
-	o1 = AnglesTransform_Apply(self.warpzone_transform, o0 - self.warpzone_origin) + self.enemy.warpzone_origin;
-	v1 = AnglesTransform_Apply(self.warpzone_transform, v0);
-	if(player.classname == "player")
-		a1 = Portal_ApplyTransformToPlayerAngle(self.warpzone_transform, player.v_angle);
-	else
-		a1 = AnglesTransform_Multiply(self.warpzone_transform, a0);
-
-	// put him inside solid
-	tracebox(o1 - player.view_ofs, player.mins, player.maxs, o1 - player.view_ofs, MOVE_NOMONSTERS, player);
-	if(trace_startsolid)
-	{
-		setorigin(player, o1 - player.view_ofs);
-		if(move_out_of_solid(player))
-		{
-			setorigin(player, o0);
-			o1 = player.origin + player.view_ofs;
-		}
-		else
-		{
-			setorigin(player, o0 - player.view_ofs);
-			return 0; // cannot fix
-		}
-	}
-
-	if((o1 - self.enemy.warpzone_origin) * self.enemy.warpzone_forward <= 0) // wrong side of the portal post-teleport
-	{
-		print("inconsistent warp zones or evil roundoff error\n");
-		return 0;
-	}
-
-	//print(sprintf("warpzone: %f %f %f -> %f %f %f\n", o0_x, o0_y, o0_z, o1_x, o1_y, o1_z));
-
-	//o1 = trace_endpos;
-	TeleportPlayer(self, other, o1 - player.view_ofs, a1, v1, '0 0 0', '0 0 0', TELEPORT_FLAGS_WARPZONE);
-
-	return 1;
-}
-
-void warpzone_touch (void)
-{
-	entity oldself, e;
-
-	if (other.health < 1)
-		return;
-
-	if(self.team)
-		if((self.spawnflags & 4 == 0) == (self.team != other.team))
-			return;
-
-	EXACTTRIGGER_TOUCH;
-
-	e = self.enemy;
-	if(warpzone_teleport(other))
-	{
-		if(self.aiment.target)
-		{
-			oldself = self;
-			activator = other;
-			self = self.aiment;
-			SUB_UseTargets();
-			self = oldself;
-		}
-	}
-	else
-	{
-		dprint("WARPZONE FAIL AHAHAHAHAH))\n");
-	}
-}
-void warpzone_findtarget (void)
-{
-	entity e;
-
-	if(self.killtarget == "")
-	{
-		objerror("Warp zone with no killtarget");
-		return;
-	}
-	self.aiment = find(world, targetname, self.killtarget);
-	if(self.aiment == world)
-	{
-		objerror("Warp zone with nonexisting killtarget");
-		return;
-	}
-
-	// this way only one of the two ents needs to target
-	if(self.target != "")
-	{
-		e = find(world, targetname, self.target);
-		if(e)
-		{
-			self.enemy = e;
-			self.enemy.enemy = self;
-		}
-	}
-
-	// now enable touch
-	self.touch = warpzone_touch;
-}
-
-float warpzone_send(entity to, float sendflags)
-{
-	WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE);
-
-	// we need THESE to render the warpzone (and cull properly)...
-	WriteCoord(MSG_ENTITY, self.origin_x);
-	WriteCoord(MSG_ENTITY, self.origin_y);
-	WriteCoord(MSG_ENTITY, self.origin_z);
-
-	WriteShort(MSG_ENTITY, self.modelindex);
-	WriteCoord(MSG_ENTITY, self.mins_x);
-	WriteCoord(MSG_ENTITY, self.mins_y);
-	WriteCoord(MSG_ENTITY, self.mins_z);
-	WriteCoord(MSG_ENTITY, self.maxs_x);
-	WriteCoord(MSG_ENTITY, self.maxs_y);
-	WriteCoord(MSG_ENTITY, self.maxs_z);
-
-	// we need THESE to calculate the proper transform
-	WriteCoord(MSG_ENTITY, self.warpzone_origin_x);
-	WriteCoord(MSG_ENTITY, self.warpzone_origin_y);
-	WriteCoord(MSG_ENTITY, self.warpzone_origin_z);
-	WriteCoord(MSG_ENTITY, self.warpzone_angles_x);
-	WriteCoord(MSG_ENTITY, self.warpzone_angles_y);
-	WriteCoord(MSG_ENTITY, self.warpzone_angles_z);
-	WriteCoord(MSG_ENTITY, self.enemy.warpzone_origin_x);
-	WriteCoord(MSG_ENTITY, self.enemy.warpzone_origin_y);
-	WriteCoord(MSG_ENTITY, self.enemy.warpzone_origin_z);
-	WriteCoord(MSG_ENTITY, self.enemy.warpzone_angles_x);
-	WriteCoord(MSG_ENTITY, self.enemy.warpzone_angles_y);
-	WriteCoord(MSG_ENTITY, self.enemy.warpzone_angles_z);
-
-	return TRUE;
-}
-
 void spawnfunc_trigger_warpzone(void)
 {
-	// warp zone entities must have:
-	// "killtarget" pointing to a target_position with a direction arrow
-	//              that points AWAY from the warp zone, and that is inside
-	//              the warp zone trigger
-	// "target"     pointing to an identical warp zone at another place in
-	//              the map, with another killtarget to designate its
-	//              orientation
-	
-	string m;
-	m = self.model;
-	EXACTTRIGGER_INIT;
-	setmodel(self, m);
-
-	self.use = trigger_teleport_use; // set team
-	InitializeEntity(self, warpzone_findtarget, INITPRIO_FINDTARGET);
-	InitializeEntity(self, warpzone_updatetransform, INITPRIO_LAST);
-	Net_LinkEntity(self, FALSE, 0, warpzone_send);
+	WarpZone_InitStep_SpawnFunc();
+	InitializeEntity(self, WarpZone_InitStep_FindTarget, INITPRIO_FINDTARGET);
+	InitializeEntity(self, WarpZone_InitStep_UpdateTransform, INITPRIO_LAST);
 }

Modified: trunk/data/qcsrc/server/w_campingrifle.qc
===================================================================
--- trunk/data/qcsrc/server/w_campingrifle.qc	2010-02-28 19:42:21 UTC (rev 8686)
+++ trunk/data/qcsrc/server/w_campingrifle.qc	2010-02-28 19:42:26 UTC (rev 8687)
@@ -239,3 +239,84 @@
 	return TRUE;
 };
 #endif
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     Ç[Kg|º^fÆ,9Þ@ª	w_deathtypestring = "sniped themself somehow";
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+		{
+			if(w_deathtype & HITTYPE_BOUNCE)
+				w_deathtypestring = "failed to hide from #'s bullet hail";
+			else
+				w_deathtypestring = "died in #'s bullet hail";
+		}
+		else
+		{
+			if(w_deathtype & HITTYPE_BOUNCE)
+			{
+				// TODO special headshot message here too?
+				w_deathtypestring = "failed to hide from #'s rifle";
+			}
+			else
+			{
+				if(w_deathtype & HITTYPE_HEADSHOT)
+					w_deathtypestring = "got hit in the head by #";
+				else
+					w_deathtypestring = "was sniped by #";
+			}
+		}
+	}
+	else if (req == WR_RELOAD)
+	{
+		W_CampingRifle_Reload();
+	}
+	else if (req == WR_RESETPLAYER)
+	{
+		self.campingrifle_accumulator = time - cvar("g_balance_campingrifle_bursttime");
+		self.campingrifle_bulletcounter = cvar("g_balance_campingrifle_magazinecapacity");
+		W_CampingRifle_CheckMaxBullets(FALSE);
+	}
+	return TRUE;
+};
+#endif
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     tì‡{³ío¸?~á…Ñ	w_deathtypestring = "sniped themself somehow";
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+		{
+			if(w_deathtype & HITTYPE_BOUNCE)
+				w_deathtypestring = "failed to hide from #'s bullet hail";
+			else
+				w_deathtypestring = "died in #'s bullet hail";
+		}
+		else
+		{
+			if(w_deathtype & HITTYPE_BOUNCE)
+			{
+				// TODO special headshot message here too?
+				w_deathtypestring = "failed to hide from #'s rifle";
+			}
+			else
+			{
+				if(w_deathtype & HITTYPE_HEADSHOT)
+					w_deathtypestring = "got hit in the head by #";
+				else
+					w_deathtypestring = "was sniped by #";
+			}
+		}
+	}
+	else if (req == WR_RELOAD)
+	{
+		W_CampingRifle_Reload();
+	}
+	else if (req == WR_RESETPLAYER)
+	{
+		self.campingrifle_accumulator = time - cvar("g_balance_campingrifle_bursttime");
+		self.campingrifle_bulletcounter = cvar("g_balance_campingrifle_magazinecapacity");
+		W_CampingRifle_CheckMaxBullets(FALSE);
+	}
+	return TRUE;
+};
+#endif
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
\ No newline at end of file

Added: trunk/data/qcsrc/warpzonelib/COPYING
===================================================================
--- trunk/data/qcsrc/warpzonelib/COPYING	                        (rev 0)
+++ trunk/data/qcsrc/warpzonelib/COPYING	2010-02-28 19:42:26 UTC (rev 8687)
@@ -0,0 +1,21 @@
+/*
+Copyright (c) 2010 Rudolf Polzer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/

Added: trunk/data/qcsrc/warpzonelib/anglestransform.qc
===================================================================
--- trunk/data/qcsrc/warpzonelib/anglestransform.qc	                        (rev 0)
+++ trunk/data/qcsrc/warpzonelib/anglestransform.qc	2010-02-28 19:42:26 UTC (rev 8687)
@@ -0,0 +1,99 @@
+// helper function
+void fixedmakevectors(vector a)
+{
+	// a makevectors that actually inverts vectoangles
+	a_x = -a_x;
+	makevectors(a);
+}
+
+// angles transforms
+// angles in fixedmakevectors/fixedvectoangles space
+vector AnglesTransform_Apply(vector transform, vector v)
+{
+	fixedmakevectors(transform);
+	return v_forward * v_x
+	     + v_right   * (-v_y)
+		 + v_up      * v_z;
+}
+
+vector AnglesTransform_Multiply(vector t1, vector t2)
+{
+	vector m_forward, m_up;
+	fixedmakevectors(t2); m_forward = v_forward; m_up = v_up;
+	m_forward = AnglesTransform_Apply(t1, m_forward); m_up = AnglesTransform_Apply(t1, m_up);
+	return fixedvectoangles2(m_forward, m_up);
+}
+
+vector AnglesTransform_Invert(vector transform)
+{
+	vector i_forward, i_up;
+	fixedmakevectors(transform);
+	// we want angles that turn v_forward into '1 0 0', v_right into '0 1 0' and v_up into '0 0 1'
+	// but these are orthogonal unit vectors!
+	// so to invert, we can simply fixedvectoangles the TRANSPOSED matrix
+	// TODO is this always -transform?
+	i_forward_x = v_forward_x;
+	i_forward_y = -v_right_x;
+	i_forward_z = v_up_x;
+	i_up_x = v_forward_z;
+	i_up_y = -v_right_z;
+	i_up_z = v_up_z;
+	return fixedvectoangles2(i_forward, i_up);
+}
+
+vector AnglesTransform_TurnDirectionFR(vector transform)
+{
+	// turn 180 degrees around v_up
+	// changes in-direction to out-direction
+	//fixedmakevectors(transform);
+	//return fixedvectoangles2(-1 * v_forward, 1 * v_up);
+	transform_x = 180 - transform_x;
+	transform_y = 180 + transform_y;
+	transform_z = -transform_z;
+	return transform;
+}
+
+vector AnglesTransform_TurnDirectionFU(vector transform)
+{
+	// turn 180 degrees around v_up
+	// changes in-direction to out-direction
+	//fixedmakevectors(transform);
+	//return fixedvectoangles2(-1 * v_forward, 1 * v_up);
+	transform_x = 180 - transform_x;
+	transform_y = 180 + transform_y;
+	transform_z = 180 - transform_z;
+	return transform;
+}
+
+vector AnglesTransform_Divide(vector to_transform, vector from_transform)
+{
+	return AnglesTransform_Multiply(to_transform, AnglesTransform_Invert(from_transform));
+}
+
+vector AnglesTransform_Normalize(vector t, float minimize_roll)
+{
+	float need_flip;
+	// first, bring all angles in their range...
+	t_x = t_x - 360 * rint(t_x / 360);
+	t_y = t_y - 360 * rint(t_y / 360);
+	t_z = t_z - 360 * rint(t_z / 360);
+	if(minimize_roll)
+		need_flip = (t_z > 90 || t_z <= -90);
+	else
+		need_flip = (t_x > 90 || t_x < -90); // for pitch we prefer to allow exactly -90 degrees for looking straight down
+	if(need_flip)
+	{
+		if(t_x >= 0) t_x = 180 - t_x; else t_x = -180 - t_x;
+		if(t_y > 0) t_y -= 180; else t_y += 180;
+		if(t_z > 0) t_z -= 180; else t_z += 180;
+	}
+	return t;
+}
+
+vector AnglesTransform_ApplyToVAngles(vector transform, vector v)
+{
+	v_x = -v_x;
+	v = AnglesTransform_ApplyToAngles(transform, v);
+	v_x = -v_x;
+	return v;
+}

Added: trunk/data/qcsrc/warpzonelib/anglestransform.qh
===================================================================
--- trunk/data/qcsrc/warpzonelib/anglestransform.qh	                        (rev 0)
+++ trunk/data/qcsrc/warpzonelib/anglestransform.qh	2010-02-28 19:42:26 UTC (rev 8687)
@@ -0,0 +1,15 @@
+void fixedmakevectors(vector a);
+#define fixedvectoangles2 vectoangles2
+#define fixedvectoangles vectoangles
+
+vector AnglesTransform_Apply(vector transform, vector v);
+vector AnglesTransform_Multiply(vector t1, vector t2);
+vector AnglesTransform_Invert(vector transform);
+vector AnglesTransform_TurnDirectionFU(vector transform);
+vector AnglesTransform_TurnDirectionFR(vector transform);
+vector AnglesTransform_Divide(vector to_transform, vector from_transform);
+
+vector AnglesTransform_Normalize(vector t, float minimize_roll); // makes sure all angles are in their range: yaw in -180..180, pitch in -90..90, roll in -180..180 (or if minimize_roll is set, pitch in -180..180, roll in -90..90)
+
+#define AnglesTransform_ApplyToAngles(t,v) AnglesTransform_Multiply(t, v)
+vector AnglesTransform_ApplyToVAngles(vector transform, vector v);

Added: trunk/data/qcsrc/warpzonelib/client.qc
===================================================================
--- trunk/data/qcsrc/warpzonelib/client.qc	                        (rev 0)
+++ trunk/data/qcsrc/warpzonelib/client.qc	2010-02-28 19:42:26 UTC (rev 8687)
@@ -0,0 +1,84 @@
+float FL_CAMERA = 8192;
+.vector warpzone_transform;
+void WarpZone_Read(float isnew)
+{
+	if not(self.enemy)
+	{
+		self.enemy = spawn();
+		self.enemy.classname = "warpzone_from";
+	}
+	self.classname = "warpzone_to";
+	self.origin_x = ReadCoord();
+	self.origin_y = ReadCoord();
+	self.origin_z = ReadCoord();
+	self.modelindex = ReadShort();
+	self.mins_x = ReadCoord();
+	self.mins_y = ReadCoord();
+	self.mins_z = ReadCoord();
+	self.maxs_x = ReadCoord();
+	self.maxs_y = ReadCoord();
+	self.maxs_z = ReadCoord();
+	self.enemy.oldorigin_x = ReadCoord();
+	self.enemy.oldorigin_y = ReadCoord();
+	self.enemy.oldorigin_z = ReadCoord();
+	self.enemy.avelocity_x = ReadCoord();
+	self.enemy.avelocity_y = ReadCoord();
+	self.enemy.avelocity_z = ReadCoord();
+	self.oldorigin_x = ReadCoord();
+	self.oldorigin_y = ReadCoord();
+	self.oldorigin_z = ReadCoord();
+	self.avelocity_x = ReadCoord();
+	self.avelocity_y = ReadCoord();
+	self.avelocity_z = ReadCoord();
+
+	self.avelocity = AnglesTransform_TurnDirectionFR(self.avelocity);
+	self.warpzone_transform = AnglesTransform_Divide(self.avelocity, self.enemy.avelocity);
+	
+	print(vtos(AnglesTransform_Apply(self.warpzone_transform, '0 0 1')), "\n");
+
+	self.flags = FL_CAMERA;
+	self.drawmask = MASK_NORMAL;
+
+	// link me
+	//setmodel(self, self.model);
+	setorigin(self, self.origin);
+	setsize(self, self.mins, self.maxs);
+}
+
+float warpzone_saved;
+vector warpzone_saved_origin;
+vector warpzone_saved_angles;
+void WarpZone_FixView()
+{
+	entity e;
+	float roll;
+	warpzone_saved = 0;
+	for(e = world; (e = find(e, classname, "warpzone_to")); )
+	{
+		//print(sprintf("does %s (%s to %s) touch %s?\n", e.model, vtos(e.absmin), vtos(e.absmax), vtos(pmove_org)));
+		if(BoxTouchesBrush(pmove_org, pmove_org, e, world))
+		{
+			warpzone_saved_origin = warpzone_fixview_origin;
+			warpzone_saved_angles = warpzone_fixview_angles;
+			warpzone_saved = 1;
+			roll = warpzone_fixview_angles_z;
+			warpzone_fixview_angles_z = 0;
+			warpzone_fixview_origin = AnglesTransform_Apply(e.warpzone_transform, warpzone_fixview_origin - e.enemy.oldorigin) + e.oldorigin;
+			warpzone_fixview_angles = AnglesTransform_Normalize(AnglesTransform_ApplyToVAngles(e.warpzone_transform, warpzone_fixview_angles), TRUE);
+			warpzone_fixview_angles_z = roll;
+			R_SetView(VF_ORIGIN, warpzone_fixview_origin);
+			R_SetView(VF_ANGLES, warpzone_fixview_angles);
+			break;
+		}
+	}
+}
+void WarpZone_UnFixView()
+{
+	if(warpzone_saved)
+	{
+		warpzone_fixview_origin = warpzone_saved_origin;
+		warpzone_fixview_angles = warpzone_saved_angles;
+		R_SetView(VF_ORIGIN, warpzone_fixview_origin);
+		R_SetView(VF_ANGLES, warpzone_fixview_angles);
+	}
+}

Added: trunk/data/qcsrc/warpzonelib/client.qh
===================================================================
--- trunk/data/qcsrc/warpzonelib/client.qh	                        (rev 0)
+++ trunk/data/qcsrc/warpzonelib/client.qh	2010-02-28 19:42:26 UTC (rev 8687)
@@ -0,0 +1,6 @@
+void WarpZone_Read(float bIsNewEntity);
+
+vector warpzone_fixview_origin;
+vector warpzone_fixview_angles;
+void WarpZone_FixView(); // this saves the previous values
+void WarpZone_UnFixView(); // and restores them

Added: trunk/data/qcsrc/warpzonelib/common.qc
===================================================================
--- trunk/data/qcsrc/warpzonelib/common.qc	                        (rev 0)
+++ trunk/data/qcsrc/warpzonelib/common.qc	2010-02-28 19:42:26 UTC (rev 8687)
@@ -0,0 +1 @@
+// empty yet

Added: trunk/data/qcsrc/warpzonelib/common.qh
===================================================================
--- trunk/data/qcsrc/warpzonelib/common.qh	                        (rev 0)
+++ trunk/data/qcsrc/warpzonelib/common.qh	2010-02-28 19:42:26 UTC (rev 8687)
@@ -0,0 +1 @@
+// empty

Added: trunk/data/qcsrc/warpzonelib/server.qc
===================================================================
--- trunk/data/qcsrc/warpzonelib/server.qc	                        (rev 0)
+++ trunk/data/qcsrc/warpzonelib/server.qc	2010-02-28 19:42:26 UTC (rev 8687)
@@ -0,0 +1,214 @@
+void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
+{
+	vector from;
+
+	makevectors (to_angles);
+
+	from = player.origin;
+	setorigin (player, to);
+	player.oldorigin = to; // for DP's unsticking
+	player.angles = to_angles;
+	player.fixangle = TRUE;
+	player.velocity = to_velocity;
+
+	if(player.effects & EF_TELEPORT_BIT)
+		player.effects &~= EF_TELEPORT_BIT;
+	else
+		player.effects |= EF_TELEPORT_BIT;
+
+	if(player.classname == "player")
+		player.flags &~= FL_ONGROUND;
+
+	WarpZone_PostTeleportPlayer(player);
+}
+
+// the transform
+.vector warpzone_origin, warpzone_angles;
+.vector warpzone_forward;
+.vector warpzone_transform;
+
+float WarpZone_Teleport(entity player)
+{
+	vector o0, a0, v0, o1, a1, v1;
+
+	o0 = player.origin + player.view_ofs;
+	v0 = player.velocity;
+	a0 = player.angles;
+
+	if((o0 - self.warpzone_origin) * self.warpzone_forward >= 0) // wrong side of the portal
+		return 2;
+	// no failure, we simply don't want to teleport yet; TODO in
+	// this situation we may want to create a temporary clone
+	// entity of the player to fix graphics glitch
+
+	o1 = AnglesTransform_Apply(self.warpzone_transform, o0 - self.warpzone_origin) + self.enemy.warpzone_origin;
+	v1 = AnglesTransform_Apply(self.warpzone_transform, v0);
+	if(player.classname == "player")
+		a1 = AnglesTransform_Normalize(AnglesTransform_ApplyToVAngles(self.warpzone_transform, player.v_angle), TRUE);
+	else
+		a1 = AnglesTransform_ApplyToAngles(self.warpzone_transform, a0);
+
+	// put him inside solid
+	tracebox(o1 - player.view_ofs, player.mins, player.maxs, o1 - player.view_ofs, MOVE_NOMONSTERS, player);
+	if(trace_startsolid)
+	{
+		setorigin(player, o1 - player.view_ofs);
+		if(WarpZoneLib_MoveOutOfSolid(player))
+		{
+			setorigin(player, o0);
+			o1 = player.origin + player.view_ofs;
+		}
+		else
+		{
+			setorigin(player, o0 - player.view_ofs);
+			return 0; // cannot fix
+		}
+	}
+
+	if((o1 - self.enemy.warpzone_origin) * self.enemy.warpzone_forward <= 0) // wrong side of the portal post-teleport
+	{
+		print("inconsistent warp zones or evil roundoff error\n");
+		return 0;
+	}
+
+	//print(sprintf("warpzone: %f %f %f -> %f %f %f\n", o0_x, o0_y, o0_z, o1_x, o1_y, o1_z));
+
+	//o1 = trace_endpos;
+	TeleportPlayer(self, other, o1 - player.view_ofs, a1, v1, '0 0 0', '0 0 0', TELEPORT_FLAGS_WARPZONE);
+
+	return 1;
+}
+
+void WarpZone_Touch (void)
+{
+	entity oldself, e;
+
+	// FIXME needs a better check to know what is safe to teleport and what not
+	if(other.movetype == MOVETYPE_NONE)
+		return;
+
+	EXACTTRIGGER_TOUCH;
+
+	e = self.enemy;
+	if(WarpZone_Teleport(other))
+	{
+		if(self.aiment.target)
+		{
+			oldself = self;
+			activator = other;
+			self = self.aiment;
+			SUB_UseTargets();
+			self = oldself;
+		}
+	}
+	else
+	{
+		dprint("WARPZONE FAIL AHAHAHAHAH))\n");
+	}
+}
+
+float WarpZone_Send(entity to, float sendflags)
+{
+	WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE);
+
+	// we need THESE to render the warpzone (and cull properly)...
+	WriteCoord(MSG_ENTITY, self.origin_x);
+	WriteCoord(MSG_ENTITY, self.origin_y);
+	WriteCoord(MSG_ENTITY, self.origin_z);
+
+	WriteShort(MSG_ENTITY, self.modelindex);
+	WriteCoord(MSG_ENTITY, self.mins_x);
+	WriteCoord(MSG_ENTITY, self.mins_y);
+	WriteCoord(MSG_ENTITY, self.mins_z);
+	WriteCoord(MSG_ENTITY, self.maxs_x);
+	WriteCoord(MSG_ENTITY, self.maxs_y);
+	WriteCoord(MSG_ENTITY, self.maxs_z);
+
+	// we need THESE to calculate the proper transform
+	WriteCoord(MSG_ENTITY, self.warpzone_origin_x);
+	WriteCoord(MSG_ENTITY, self.warpzone_origin_y);
+	WriteCoord(MSG_ENTITY, self.warpzone_origin_z);
+	WriteCoord(MSG_ENTITY, self.warpzone_angles_x);
+	WriteCoord(MSG_ENTITY, self.warpzone_angles_y);
+	WriteCoord(MSG_ENTITY, self.warpzone_angles_z);
+	WriteCoord(MSG_ENTITY, self.enemy.warpzone_origin_x);
+	WriteCoord(MSG_ENTITY, self.enemy.warpzone_origin_y);
+	WriteCoord(MSG_ENTITY, self.enemy.warpzone_origin_z);
+	WriteCoord(MSG_ENTITY, self.enemy.warpzone_angles_x);
+	WriteCoord(MSG_ENTITY, self.enemy.warpzone_angles_y);
+	WriteCoord(MSG_ENTITY, self.enemy.warpzone_angles_z);
+
+	return TRUE;
+}
+
+void WarpZone_InitStep_SpawnFunc()
+{
+	// warp zone entities must have:
+	// "killtarget" pointing to a target_position with a direction arrow
+	//              that points AWAY from the warp zone, and that is inside
+	//              the warp zone trigger
+	// "target"     pointing to an identical warp zone at another place in
+	//              the map, with another killtarget to designate its
+	//              orientation
+
+	// TODO nexuiz specific
+	string m;
+	m = self.model;
+	EXACTTRIGGER_INIT;
+	setmodel(self, m);
+	Net_LinkEntity(self, FALSE, 0, WarpZone_Send);
+}
+
+void WarpZone_InitStep_FindTarget()
+{
+	entity e;
+
+	if(self.killtarget == "")
+	{
+		objerror("Warp zone with no killtarget");
+		return;
+	}
+	self.aiment = find(world, targetname, self.killtarget);
+	if(self.aiment == world)
+	{
+		objerror("Warp zone with nonexisting killtarget");
+		return;
+	}
+
+	// this way only one of the two ents needs to target
+	if(self.target != "")
+	{
+		e = find(world, targetname, self.target);
+		if(e)
+		{
+			self.enemy = e;
+			self.enemy.enemy = self;
+		}
+	}
+
+	// now enable touch
+	self.touch = WarpZone_Touch;
+}
+
+void WarpZone_InitStep_UpdateTransform()
+{
+	if(!self.enemy || self.enemy.enemy != self)
+	{
+		objerror("Invalid warp zone detected. Killed.");
+		return;
+	}
+
+	// 1. update this, and the enemy, warp zone
+	self.warpzone_origin = self.aiment.origin;
+	self.warpzone_angles = self.aiment.angles;
+	self.enemy.warpzone_origin = self.enemy.aiment.origin;
+	self.enemy.warpzone_angles = self.enemy.aiment.angles;
+
+	// 2. combine the angle transforms
+	//    current forward must be turned into previous backward
+	self.warpzone_transform = AnglesTransform_Divide(AnglesTransform_TurnDirectionFR(self.enemy.warpzone_angles), self.warpzone_angles);
+
+	// 3. store off a saved forward vector for plane hit decisions
+	fixedmakevectors(self.warpzone_angles);
+	self.warpzone_forward = v_forward;
+}

Added: trunk/data/qcsrc/warpzonelib/server.qh
===================================================================
--- trunk/data/qcsrc/warpzonelib/server.qh	                        (rev 0)
+++ trunk/data/qcsrc/warpzonelib/server.qh	2010-02-28 19:42:26 UTC (rev 8687)
@@ -0,0 +1,10 @@
+void WarpZone_InitStep_SpawnFunc();
+void WarpZone_InitStep_FindTarget();
+void WarpZone_InitStep_UpdateTransform();
+
+// THESE must be defined by calling QC code:
+void spawnfunc_trigger_warpzone(); // must call the init steps in order, first all spawnfunc init steps, then all findtarget init steps, then all updatetransform init steps
+void WarpZone_PostTeleportPlayer(entity pl);
+
+// server must also define a float called ENT_CLIENT_WARPZONE for the initial byte of WarpZone entities
+const float ENT_CLIENT_WARPZONE;

Added: trunk/data/qcsrc/warpzonelib/util_server.qc
===================================================================
--- trunk/data/qcsrc/warpzonelib/util_server.qc	                        (rev 0)
+++ trunk/data/qcsrc/warpzonelib/util_server.qc	2010-02-28 19:42:26 UTC (rev 8687)
@@ -0,0 +1,55 @@
+void WarpZoneLib_MoveOutOfSolid_Expand(entity e, vector by)
+{
+	float eps = 0.0625;
+	tracebox(e.origin, e.mins - '1 1 1' * eps, e.maxs + '1 1 1' * eps, e.origin + by, MOVE_WORLDONLY, e);
+	if (trace_startsolid)
+		return;
+	if (trace_fraction < 1)
+	{
+		// hit something
+		// adjust origin in the other direction...
+		setorigin(e,e.origin - by * (1 - trace_fraction));
+	}
+}
+
+float WarpZoneLib_MoveOutOfSolid(entity e)
+{
+	vector o, m0, m1;
+
+	o = e.origin;
+	traceline(o, o, MOVE_WORLDONLY, e);
+	if (trace_startsolid)
+		return FALSE;
+
+	tracebox(o, e.mins, e.maxs, o, MOVE_WORLDONLY, e);
+	if (!trace_startsolid)
+		return TRUE;
+
+	m0 = e.mins;
+	m1 = e.maxs;
+	e.mins = '0 0 0';
+	e.maxs = '0 0 0';
+	WarpZoneLib_MoveOutOfSolid_Expand(e, '1 0 0' * m0_x);
+	e.mins_x = m0_x;
+	WarpZoneLib_MoveOutOfSolid_Expand(e, '1 0 0' * m1_x);
+	e.maxs_x = m1_x;
+	WarpZoneLib_MoveOutOfSolid_Expand(e, '0 1 0' * m0_y);
+	e.mins_y = m0_y;
+	WarpZoneLib_MoveOutOfSolid_Expand(e, '0 1 0' * m1_y);
+	e.maxs_y = m1_y;
+	WarpZoneLib_MoveOutOfSolid_Expand(e, '0 0 1' * m0_z);
+	e.mins_z = m0_z;
+	WarpZoneLib_MoveOutOfSolid_Expand(e, '0 0 1' * m1_z);
+	e.maxs_z = m1_z;
+	setorigin(e, e.origin);
+
+	tracebox(e.origin, e.mins, e.maxs, e.origin, MOVE_WORLDONLY, e);
+	if (trace_startsolid)
+	{
+		setorigin(e, o);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+

Added: trunk/data/qcsrc/warpzonelib/util_server.qh
===================================================================
--- trunk/data/qcsrc/warpzonelib/util_server.qh	                        (rev 0)
+++ trunk/data/qcsrc/warpzonelib/util_server.qh	2010-02-28 19:42:26 UTC (rev 8687)
@@ -0,0 +1 @@
+float WarpZoneLib_MoveOutOfSolid(entity e);



More information about the nexuiz-commits mailing list