r1809 - trunk/data/qcsrc/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Wed Aug 9 09:41:26 EDT 2006


Author: div0
Date: 2006-08-09 09:41:26 -0400 (Wed, 09 Aug 2006)
New Revision: 1809

Modified:
   trunk/data/qcsrc/server/t_jumppads.qc
Log:
New parameter for jump pads: height.

|height| = position of the highest point of the jump trajectory, measured from
           the higher one of the jumppad and its target
sgn height indicates whether the jump's highest points is reached INSIDE the jump
           trajectory (positive) or OUTSIDE (negative). Use negative heights to
		   target points on the ceiling.

--This line , and those below, will be ignored--
            
M    server /t_jumppads.qc
            


Modified: trunk/data/qcsrc/server/t_jumppads.qc
===================================================================
--- trunk/data/qcsrc/server/t_jumppads.qc	2006-08-06 18:53:27 UTC (rev 1808)
+++ trunk/data/qcsrc/server/t_jumppads.qc	2006-08-09 13:41:26 UTC (rev 1809)
@@ -2,11 +2,109 @@
 float PUSH_SILENT		= 2;
 
 .float pushltime;
+.float height;
+
+float trigger_push_calculatevelocity_flighttime;
+
+/*
+	trigger_push_calculatevelocity
+
+	Arguments:
+	  org - origin of the object which is to be pushed
+	  tgt - target entity (can be either a point or a model entity; if it is
+	        the latter, its midpoint is used)
+	  ht  - jump height, measured from the higher one of org and tgt's midpoint
+    
+	Returns: velocity for the jump
+	the global trigger_push_calculatevelocity_flighttime is set to the total
+	jump time
+ */
+
+vector(vector org, entity tgt, float ht) trigger_push_calculatevelocity =
+{
+	local float grav, sdist, zdist, vs, vz, jumpheight, trajsign;
+	local vector sdir, torg;
+
+	torg = tgt.origin;
+	if(tgt.model)
+		torg = torg + (tgt.mins + tgt.maxs) * 0.5;
+
+	grav = cvar("sv_gravity");
+
+	zdist = torg_z - org_z;
+	sdist = vlen(torg - org - zdist * '0 0 1');
+	sdir = normalize(torg - org - zdist * '0 0 1');
+
+	// how high do we need to push the player?
+	jumpheight = fabs(ht);
+	if(zdist > 0)
+		jumpheight = jumpheight + zdist;
+
+	/*
+		STOP.
+
+		You will not understand the following equations anyway...
+		But here is what I did to get them.
+
+		I used the functions
+
+		  s(t) = t * vs
+		  z(t) = t * vz - 1/2 grav t^2
+
+		and solved for:
+		
+		  s(ti) = sdist
+		  z(ti) = zdist
+		  max(z, ti) = jumpheight
+
+		From these three equations, you will find the three parameters vs, vz
+		and ti.
+	 */
+
+	// push him so high...
+	vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)!
+	if(ht < 0)
+		if(zdist < 0)
+			vz = -vz;
+
+	// how far to push him?
+	if(zdist == 0)
+	{
+		trigger_push_calculatevelocity_flighttime = sqrt(jumpheight * 8 / grav);
+		vs = sdist / trigger_push_calculatevelocity_flighttime;
+			// trajsign is ignored (the high point MUST be inside the jump!)
+	}
+	else
+	{
+		if(ht > 0)
+			trajsign = +1;
+		else
+			trajsign = -1;
+		
+		// >0: the lower speed that achieves "it"
+		//     (parabola's maximum inside the jump)
+		// <0: the higher speed that achieves "it"
+		//     (parabola's maximum outside the jump)
+
+		vs = sqrt(jumpheight - zdist);
+		vs = sqrt(jumpheight) - trajsign * vs; // fteqcc sucks
+		vs = fabs(vs * sqrt(grav/2) / zdist);
+		//vs = fabs((sdist / zdist) * sqrt(grav/2) * (sqrt(jumpheight) - trajsign * sqrt(jumpheight - zdist)));
+		trigger_push_calculatevelocity_flighttime = 1 / vs;
+			// note: vs cannot be zero here. The difference between the sqrts is zero IFF zdist == 0, which we have excluded.
+		vs = vs * sdist;
+
+		// cases to test: "jump up", "jump down" with positive and negative height
+	}
+
+	dprint("trigger_push_calculatevelocity_flighttime: "); dprint(ftos(trigger_push_calculatevelocity_flighttime)); dprint("\n");
+
+	// finally calculate the velocity
+	return sdir * vs + '0 0 1' * vz;
+}
+
 void() trigger_push_touch =
 {
-	local float flighttime, dist, grav;
-	local vector org;
-
 	// FIXME: add a .float for whether an entity should be tossed by jumppads
 	if (other.classname != "player")
 	if (other.classname != "corpse")
@@ -31,8 +129,6 @@
 		return;
 	}
 
-	org = other.origin;
-
 	if (other.classname == "player")
 	{
 		local float i;
@@ -53,21 +149,8 @@
 		}
 	}
 
-	// figure out how long it will take to hit the point considering gravity
-	grav = cvar("sv_gravity");
-	flighttime = sqrt((self.enemy.origin_z - org_z) / (0.5 * grav));
-	if (!flighttime)
-		return;
+	self.movedir = trigger_push_calculatevelocity(other.origin, self.enemy, self.height);
 
-	// how far in X and Y to move
-	self.movedir = (self.enemy.origin - org);
-	self.movedir_z = 0;
-	dist = vlen(self.movedir);
-
-	// finally calculate the velocity
-	self.movedir = normalize(self.movedir) * (dist / flighttime);
-	self.movedir_z = flighttime * grav;
-
 	other.flags = other.flags - (other.flags & FL_ONGROUND);
 	// reset tracking of oldvelocity for impact damage (sudden velocity changes)
 	other.oldvelocity = other.velocity = self.movedir;
@@ -90,10 +173,8 @@
 void() trigger_push_findtarget =
 {
 	local entity e;
-	local float grav;
+	local vector org;
 	local float flighttime;
-	local float dist;
-	local vector org;
 
 	// first calculate a typical start point for the jump
 	org = (self.absmin + self.absmax) * 0.5;
@@ -110,24 +191,8 @@
 			return;
 		}
 
-		// figure out how long it will take to hit the point considering gravity
-		grav = cvar("sv_gravity");
-		flighttime = sqrt((self.enemy.origin_z - org_z) / (0.5 * grav));
-		if (!flighttime)
-		{
-			objerror("trigger_push: jump pad with bad destination\n");
-			remove(self);
-			return;
-		}
-
-		// how far in X and Y to move
-		self.movedir = (self.enemy.origin - org);
-		self.movedir_z = 0;
-		dist = vlen(self.movedir);
-
-		// finally calculate the velocity
-		self.movedir = normalize(self.movedir) * (dist / flighttime);
-		self.movedir_z = flighttime * grav;
+		self.movedir = trigger_push_calculatevelocity(org, self.enemy, self.height);
+		flighttime = trigger_push_calculatevelocity_flighttime;
 	}
 	else
 		flighttime = 0;
@@ -144,6 +209,18 @@
 	waypoint_spawnforteleporter(self, self.dest, flighttime);
 };
 
+/*
+ * ENTITY PARAMETERS:
+ *
+ *   target:  target of jump
+ *   height:  the absolute value is the height of the highest point of the jump
+ *            trajectory above the higher one of the player and the target.
+ *            the sign indicates whether the highest point is INSIDE (positive)
+ *            or OUTSIDE (negative) of the jump trajectory. General rule: use
+ *            positive values for targets mounted on the floor, and use negative
+ *            values to target a point on the ceiling.
+ *   movedir: if target is not set, this * speed * 10 is the velocity to be reached.
+ */
 void() trigger_push =
 {
 	if (self.angles != '0 0 0')




More information about the nexuiz-commits mailing list