[nexuiz-commits] r8626 - trunk/data/qcsrc/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Mon Feb 8 05:42:18 EST 2010


Author: div0
Date: 2010-02-08 05:42:18 -0500 (Mon, 08 Feb 2010)
New Revision: 8626

Modified:
   trunk/data/qcsrc/server/portals.qc
   trunk/data/qcsrc/server/portals.qh
   trunk/data/qcsrc/server/t_teleporters.qc
Log:
a trigger_warpzone entity (a silent everything-teleporting teleporter). IT HAS NO VISUALS YET, NEEDS TO BE ADDED TO ENGINE.
Neither does it have hitscan or radiusdamage support yet, but it should get that, even though UT's warpzones didn't.
Projectiles should already be able to get past it.
More to come once rendering supports them in some way...

Modified: trunk/data/qcsrc/server/portals.qc
===================================================================
--- trunk/data/qcsrc/server/portals.qc	2010-02-07 15:44:21 UTC (rev 8625)
+++ trunk/data/qcsrc/server/portals.qc	2010-02-08 10:42:18 UTC (rev 8626)
@@ -19,14 +19,69 @@
 	return vbest * v;
 }
 
+vector Portal_ApplyTransformToPlayerAngle(vector transform, vector vangle)
+{
+	vector old_forward, old_up;
+	vector old_yawforward;
+	vector new_forward, new_up;
+	vector new_yawforward;
+
+	vector ang;
+	ang = vangle;
+	/*
+	   ang_x = bound(-89, mod(-ang_x + 180, 360) - 180, 89);
+	   ang = AnglesTransform_Multiply(transform, ang);
+	 */
+
+	// PLAYERS use different math
+	ang_x = -ang_x;
+
+	//print("reference: ", vtos(AnglesTransform_Multiply(transform, ang)), "\n");
+
+	fixedmakevectors(ang);
+	old_forward = v_forward;
+	old_up = v_up;
+	fixedmakevectors(ang_y * '0 1 0');
+	old_yawforward = v_forward;
+
+	// their aiming directions are portalled...
+	new_forward = AnglesTransform_Apply(transform, old_forward);
+	new_up = AnglesTransform_Apply(transform, old_up);
+	new_yawforward = AnglesTransform_Apply(transform, old_yawforward);
+
+	// but now find a new sense of direction
+	// this is NOT easy!
+	// assume new_forward points straight up.
+	// What is our yaw?
+	//
+	// new_up could now point forward OR backward... which direction to choose?
+
+	if(new_forward_z > 0.7 || new_forward_z < -0.7) // far up; in this case, the "up" vector points backwards
+	{
+		// new_yawforward and new_yawup define the new aiming half-circle
+		// we "just" need to find out whether new_up or -new_up is in that half circle
+		ang = fixedvectoangles(new_forward); // this still gets us a nice pitch value...
+		if(new_up * new_yawforward < 0)
+			new_up = -1 * new_up;
+		ang_y = vectoyaw(new_up); // this vector is the yaw we want
+		//print("UP/DOWN path: ", vtos(ang), "\n");
+	}
+	else
+	{
+		// good angles; here, "forward" suffices
+		ang = fixedvectoangles(new_forward);
+		//print("GOOD path: ", vtos(ang), "\n");
+	}
+
+	ang_x = -ang_x;
+	ang_z = vangle_z;
+	return ang;
+}
+
 .vector right_vector;
 float Portal_TeleportPlayer(entity teleporter, entity player)
 {
 	vector from, to, safe, step, transform, ang, newvel;
-	vector new_forward, new_up;
-	vector old_forward, old_up;
-	vector new_yawforward;
-	vector old_yawforward;
 	float planeshift, s, t;
 
 	if not(teleporter.enemy)
@@ -87,61 +142,9 @@
 
 	// ang_x stuff works around weird quake angles
 	if(player.classname == "player")
-	{
-		ang = player.v_angle;
-		/*
-		ang_x = bound(-89, mod(-ang_x + 180, 360) - 180, 89);
-		ang = AnglesTransform_Multiply(transform, ang);
-		*/
-
-		// PLAYERS use different math
-		ang_x = -ang_x;
-
-		//print("reference: ", vtos(AnglesTransform_Multiply(transform, ang)), "\n");
-
-		fixedmakevectors(ang);
-		old_forward = v_forward;
-		old_up = v_up;
-		fixedmakevectors(ang_y * '0 1 0');
-		old_yawforward = v_forward;
-
-		// their aiming directions are portalled...
-		new_forward = AnglesTransform_Apply(transform, old_forward);
-		new_up = AnglesTransform_Apply(transform, old_up);
-		new_yawforward = AnglesTransform_Apply(transform, old_yawforward);
-
-		// but now find a new sense of direction
-		// this is NOT easy!
-		// assume new_forward points straight up.
-		// What is our yaw?
-		//
-		// new_up could now point forward OR backward... which direction to choose?
-
-		if(new_forward_z > 0.7 || new_forward_z < -0.7) // far up; in this case, the "up" vector points backwards
-		{
-			// new_yawforward and new_yawup define the new aiming half-circle
-			// we "just" need to find out whether new_up or -new_up is in that half circle
-			ang = fixedvectoangles(new_forward); // this still gets us a nice pitch value...
-			if(new_up * new_yawforward < 0)
-				new_up = -1 * new_up;
-			ang_y = vectoyaw(new_up); // this vector is the yaw we want
-			//print("UP/DOWN path: ", vtos(ang), "\n");
-		}
-		else
-		{
-			// good angles; here, "forward" suffices
-			ang = fixedvectoangles(new_forward);
-			//print("GOOD path: ", vtos(ang), "\n");
-		}
-
-		ang_x = -ang_x;
-		ang_z = player.angles_z;
-	}
+		ang = Portal_ApplyTransformToPlayerAngle(transform, player.v_angle);
 	else
-	{
-		ang = player.angles;
 		ang = AnglesTransform_Multiply(transform, player.angles);
-	}
 
 	// factor -1 allows chaining portals, but may be weird
 	player.right_vector = -1 * AnglesTransform_Apply(transform, player.right_vector);
@@ -156,7 +159,7 @@
 	}
 
 	tdeath_hit = 0;
-	TeleportPlayer(teleporter, player, to, ang, newvel, teleporter.enemy.absmin, teleporter.enemy.absmax);
+	TeleportPlayer(teleporter, player, to, ang, newvel, teleporter.enemy.absmin, teleporter.enemy.absmax, TELEPORT_FLAGS_PORTAL);
 	if(tdeath_hit)
 	{
 		// telefrag within 1 second of portal creation = amazing

Modified: trunk/data/qcsrc/server/portals.qh
===================================================================
--- trunk/data/qcsrc/server/portals.qh	2010-02-07 15:44:21 UTC (rev 8625)
+++ trunk/data/qcsrc/server/portals.qh	2010-02-08 10:42:18 UTC (rev 8626)
@@ -6,3 +6,5 @@
 float Portal_SpawnOutPortalAtTrace(entity own, vector dir, float id);
 float Portal_SpawnInPortalAtTrace(entity own, vector dir, float id);
 void Portal_ClearWithID(entity own, float id);
+
+vector Portal_ApplyTransformToPlayerAngle(vector transform, vector vangle);

Modified: trunk/data/qcsrc/server/t_teleporters.qc
===================================================================
--- trunk/data/qcsrc/server/t_teleporters.qc	2010-02-07 15:44:21 UTC (rev 8625)
+++ trunk/data/qcsrc/server/t_teleporters.qc	2010-02-08 10:42:18 UTC (rev 8626)
@@ -65,7 +65,14 @@
 }
 
 .entity pusher;
-void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax)
+#define TELEPORT_FLAG_SOUND 1
+#define TELEPORT_FLAG_PARTICLES 2
+#define TELEPORT_FLAG_TDEATH 4
+
+#define TELEPORT_FLAGS_WARPZONE   0
+#define TELEPORT_FLAGS_PORTAL     (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES)
+#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
+void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
 {
 	entity oldself;
 	entity telefragger;
@@ -80,9 +87,13 @@
 
 	if(self.pushltime < time) // only show one teleport effect per teleporter per 0.2 seconds, for better fps
 	{
-		sound (player, CHAN_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTN_NORM);
-		pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1);
-		pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1);
+		if(tflags & TELEPORT_FLAG_SOUND)
+			sound (player, CHAN_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTN_NORM);
+		if(tflags & TELEPORT_FLAG_PARTICLES)
+		{
+			pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1);
+			pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1);
+		}
 		self.pushltime = time + 0.2;
 	}
 
@@ -100,8 +111,9 @@
 
 	if(player.classname == "player")
 	{
-		if(player.takedamage && player.deadflag == DEAD_NO && !g_race && !g_cts && cvar("g_telefrags"))
-			tdeath(player, teleporter, telefragger, telefragmin, telefragmax);
+		if(tflags & TELEPORT_FLAG_TDEATH)
+			if(player.takedamage && player.deadflag == DEAD_NO && !g_race && !g_cts && cvar("g_telefrags"))
+				tdeath(player, teleporter, telefragger, telefragmin, telefragmax);
 
 		// player no longer is on ground
 		player.flags &~= FL_ONGROUND;
@@ -192,7 +204,7 @@
 			other.velocity = normalize(other.velocity) * max(0, cvar("g_teleport_maxspeed"));
 
 	o = e.origin + '0 0 1' * (1 - other.mins_z - 24);
-	TeleportPlayer(self, other, o, e.mangle, v_forward * vlen(other.velocity), '0 0 0', '0 0 0');
+	TeleportPlayer(self, other, o, e.mangle, v_forward * vlen(other.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
 
 	if(e.target)
 	{
@@ -285,3 +297,147 @@
 		return;
 	}
 }
+
+
+// the transform
+.vector warpzone_origin, warpzone_angles;
+.vector warpzone_forward;
+.vector warpzone_transform;
+
+void warpzone_updatetransform()
+{
+	// 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;
+	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.mins, player.maxs, o1, MOVE_NOMONSTERS, player);
+	if(trace_startsolid)
+	{
+		print("in solid\n");
+		return 0; // TODO nudge out of solid here!
+	}
+
+	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, 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))
+	{
+	}
+	else
+	{
+		dprint("WARPZONE FAIL AHAHAHAHAH))\n");
+	}
+
+	if(self.aiment.target)
+	{
+		oldself = self;
+		activator = other;
+		self = self.aiment;
+		SUB_UseTargets();
+		self = oldself;
+	}
+}
+void warpzone_findtarget (void)
+{
+	if(self.target == "")
+	{
+		objerror("Warp zone with no target");
+		return;
+	}
+	self.enemy = find(world, targetname, self.target);
+	if(self.enemy == world)
+	{
+		objerror("Warp zone with nonexisting target");
+		return;
+	}
+
+	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;
+	}
+
+	// now enable touch
+	self.touch = warpzone_touch;
+}
+
+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
+	
+	EXACTTRIGGER_INIT;
+
+	self.use = trigger_teleport_use; // set team
+	InitializeEntity(self, warpzone_findtarget, INITPRIO_FINDTARGET);
+	InitializeEntity(self, warpzone_updatetransform, INITPRIO_LAST);
+}



More information about the nexuiz-commits mailing list