r4956 - trunk/data/qcsrc/server
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Sat Nov 1 03:59:56 EDT 2008
Author: tzork
Date: 2008-11-01 03:59:52 -0400 (Sat, 01 Nov 2008)
New Revision: 4956
Added:
trunk/data/qcsrc/server/movelib.qc
trunk/data/qcsrc/server/steerlib.qc
Modified:
trunk/data/qcsrc/server/pathlib.qc
Log:
Functions for easy access to steering, pathing and moving.
Added: trunk/data/qcsrc/server/movelib.qc
===================================================================
--- trunk/data/qcsrc/server/movelib.qc (rev 0)
+++ trunk/data/qcsrc/server/movelib.qc 2008-11-01 07:59:52 UTC (rev 4956)
@@ -0,0 +1,71 @@
+.float mass;
+
+/**
+ Simulate drag
+ self.velocity = movelib_vdrag(self.velocity,0.02,0.5);
+**/
+vector movelib_drag(float drag, float exp)
+{
+ float lspeed,ldrag;
+
+ lspeed = vlen(self.velocity);
+ ldrag = lspeed * drag;
+ ldrag = ldrag * drag * exp;
+ ldrag = 1 - (ldrag / lspeed);
+
+ return self.velocity * ldrag;
+}
+
+/**
+ Simulate drag
+ self.velocity = movelib_vdrag(somespeed,0.01,0.7);
+**/
+float movelib_dragflt(float fspeed,float drag,float exp)
+{
+ float ldrag;
+
+ ldrag = fspeed * drag;
+ ldrag = ldrag * ldrag * exp;
+ ldrag = 1 - (ldrag / fspeed);
+
+ return ldrag;
+}
+
+/**
+ Do a inertia simulation based on velocity.
+ Basicaly, this allows you to simulate objects loss steering with speed.
+ self.velocity = movelib_inertia_fromspeed(self.velocity,newvel,1000,0.1,0.9);
+**/
+vector movelib_inertmove_byspeed(vector vel_new, float vel_max,float newmin,float oldmax)
+{
+ float influense;
+
+ influense = vlen(self.velocity) * (1 / vel_max);
+
+ influense = bound(newmin,influense,oldmax);
+
+ return (vel_new * (1 - influense)) + (self.velocity * influense);
+}
+
+vector movelib_inertmove(vector new_vel,float new_bias)
+{
+ return new_vel * new_bias + self.velocity * (1-new_bias);
+}
+
+
+/**
+ Applies absolute force to a velocity
+**/
+vector movelib_accelerate(vector vel,float force)
+{
+ return normalize(vel) * (vlen(vel) + force);
+}
+vector movelib_decelerate(vector vel,float force)
+{
+ return normalize(vel) * (vlen(vel) - force);
+}
+
+vector movelib_velocity_transfer(entity source,entity destination)
+{
+ return '0 0 0';
+}
Modified: trunk/data/qcsrc/server/pathlib.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib.qc 2008-10-31 22:13:09 UTC (rev 4955)
+++ trunk/data/qcsrc/server/pathlib.qc 2008-11-01 07:59:52 UTC (rev 4956)
@@ -2,20 +2,26 @@
#define PLF_NOOPTIMIZE 2
#define PLF_SUBPATH3D 4
-#define path_flags lip
+//#define PATHLIB_RDFIELDS
+#ifdef PATHLIB_RDFIELDS
+ #define path_flags lip
-//.float pathgroup;
-// #define pathgroup version
-#define path_subpathing_size autoswitch
-#define path_subpathing_bboxexpand welcomemessage_time
-/*
-.entity path_next;
-.entity path_prev;
-*/
-#define path_next swampslug
-#define path_prev lasertarget
+ #define path_subpathing_size autoswitch
+ #define path_subpathing_bboxexpand welcomemessage_time
+ #define path_next swampslug
+ #define path_prev lasertarget
+#else
+ .entity path_next;
+ .entity path_prev;
+
+ .float path_subpathing_size;
+ .float path_subpathing_bboxexpand;
+ .float path_flags;
+#endif
+
#define pathlib_garbagetime 120
+#define pathib_maxdivide 256
.float(vector start,vector end) path_validate;
@@ -48,9 +54,6 @@
point = spawn();
point.classname = "path_node";
- //point.think = SUB_Remove;
- //point.nectthink = time + pathlib_garbagetime;
-
if(first)
point.owner = first;
else
@@ -63,7 +66,10 @@
point.path_prev = parent;
if(next)
+ {
point.path_next = next;
+ //point.path_nodelength = vlen(point.origin - next.origin)
+ }
else
point.classname = "path_end";
@@ -77,7 +83,6 @@
return point;
}
-#define pathib_maxdivide 128
vector pathlib_findsubpath(entity start,vector vcrash,entity end,float maxsize)
{
float x,y,z;
@@ -222,6 +227,9 @@
}
}
+/**
+ Run a A*-like pathing from 'from' to 'to'
+**/
entity pathlib_makepath(vector from, vector to,float pathflags,float subpathing_size, float subpathing_bboxexpand)
{
entity e_start,e_end;
@@ -261,6 +269,8 @@
}
+
+/* TESTING */
void pathlib_test_think()
{
pathlib_showpath(self.enemy);
Added: trunk/data/qcsrc/server/steerlib.qc
===================================================================
--- trunk/data/qcsrc/server/steerlib.qc (rev 0)
+++ trunk/data/qcsrc/server/steerlib.qc 2008-11-01 07:59:52 UTC (rev 4956)
@@ -0,0 +1,397 @@
+/**
+ Pull toward a point, The further away, the stronger the pull.
+**/
+vector steerlib_arrive(vector point,float maximal_distance)
+{
+ float distance;
+ vector direction;
+
+ distance = bound(0.001,vlen(self.origin - point),maximal_distance);
+ direction = normalize(point - self.origin);
+ return direction * (distance / maximal_distance);
+}
+
+/**
+ Pull toward a point increasing the pull the closer we get
+**/
+vector steerlib_attract(vector point, float maximal_distance)
+{
+ float distance;
+ vector direction;
+
+ distance = bound(0.001,vlen(self.origin - point),maximal_distance);
+ direction = normalize(point - self.origin);
+
+ return direction * (1-(distance / maximal_distance));
+}
+
+/**
+ Move away from a point.
+**/
+vector steerlib_repell(vector point,float maximal_distance)
+{
+ float distance;
+ vector direction;
+
+ distance = bound(0.001,vlen(self.origin - point),maximal_distance);
+ direction = normalize(self.origin - point);
+
+ return direction * (1-(distance / maximal_distance));
+}
+
+/**
+ Keep at ideal_distance away from point
+**/
+vector steerlib_standoff(vector point,float ideal_distance)
+{
+ float distance;
+ vector direction;
+
+ distance = vlen(self.origin - point);
+
+
+ if(distance < ideal_distance)
+ {
+ direction = normalize(self.origin - point);
+ return direction * (distance / ideal_distance);
+ }
+
+ direction = normalize(point - self.origin);
+ return direction * (ideal_distance / distance);
+
+}
+
+/**
+ A random heading in a forward halfcicrle
+**/
+vector steerlib_waner(float range,float tresh,vector oldpoint)
+{
+ vector wander_point;
+ wander_point = v_forward - oldpoint;
+
+ if (vlen(wander_point) > tresh)
+ return oldpoint;
+
+ range = bound(0,range,1);
+
+ wander_point = self.origin + v_forward * 128;
+ wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
+
+ return normalize(wander_point - self.origin);
+}
+
+/**
+ Dodge a point-
+**/
+vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
+{
+ float distance;
+
+ distance = max(vlen(self.origin - point),min_distance);
+
+ return dodge_dir * (min_distance/distance);
+}
+
+/**
+ flocking by .flock_id
+ Group will move towards the unified direction while keeping close to eachother.
+**/
+.float flock_id;
+vector steerlib_flock(float radius, float standoff,float separation_force,float flock_force)
+{
+ entity flock_member;
+ vector push,pull;
+ float ccount;
+
+ flock_member = findradius(self.origin,radius);
+ while(flock_member)
+ {
+ if(flock_member != self)
+ if(flock_member.flock_id == self.flock_id)
+ {
+ ++ccount;
+ push = push + (steerlib_repell(flock_member.origin,standoff) * separation_force);
+ pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity,radius) * flock_force);
+ }
+ flock_member = flock_member.chain;
+ }
+ return push + (pull* (1 / ccount));
+}
+
+/**
+ All members want to be in the center, and keep away from eachother.
+ The furtehr form the center the more they want to be there.
+**/
+vector steerlib_swarm(float radius, float standoff,float separation_force,float swarm_force)
+{
+ entity swarm_member;
+ vector force,center;
+ float ccount;
+
+ swarm_member = findradius(self.origin,radius);
+
+ while(swarm_member)
+ {
+ if(swarm_member.flock_id == self.flock_id)
+ {
+ ++ccount;
+ center = center + swarm_member.origin;
+ force = force + (steerlib_repell(swarm_member.origin,standoff) * separation_force);
+ }
+ swarm_member = swarm_member.chain;
+ }
+
+ center = center * (1 / ccount);
+ force = force + (steerlib_arrive(center,radius) * swarm_force);
+
+ return force;
+}
+
+/**
+ Steer towards the direction least obstructed.
+ Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
+**/
+vector steerlib_traceavoid(float pitch,float length)
+{
+ vector vup_left,vup_right,vdown_left,vdown_right;
+ float fup_left,fup_right,fdown_left,fdown_right;
+ vector v_left,v_down;
+ //vector point;
+
+ /*
+ traceline(self.origin,self.origin + v_forward * length,MOVE_NOMONSTERS,self);
+ if(trace_fraction == 1)
+ return '0 0 0';
+ */
+
+ v_left = v_right * -1;
+ v_down = v_up * -1;
+
+ vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
+ traceline(self.origin, self.origin + vup_left,MOVE_NOMONSTERS,self);
+ //vup_left = trace_endpos;
+ fup_left = trace_fraction;
+
+ //te_lightning1(world,self.origin, trace_endpos);
+
+ vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
+ traceline(self.origin,self.origin + vup_right ,MOVE_NOMONSTERS,self);
+ //vup_right = trace_endpos;
+ fup_right = trace_fraction;
+
+ //te_lightning1(world,self.origin, trace_endpos);
+
+ vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
+ traceline(self.origin,self.origin + vdown_left,MOVE_NOMONSTERS,self);
+ //vdown_left = trace_endpos;
+ fdown_left = trace_fraction;
+
+ //te_lightning1(world,self.origin, trace_endpos);
+
+ vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
+ traceline(self.origin,self.origin + vdown_right,MOVE_NOMONSTERS,self);
+ //vdown_right = trace_endpos;
+ fdown_right = trace_fraction;
+
+ //te_lightning1(world,self.origin, trace_endpos);
+
+ //(v_for * f_for) +
+
+ //point = self.origin + (vup_left * fup_left) + (vup_right * fup_right) +
+ // (vdown_left * fdown_left) + (vdown_right * fdown_right);
+
+ vector upwish,downwish,leftwish,rightwish;
+ upwish = v_up * (fup_left + fup_right);
+ downwish = v_down * (fdown_left + fdown_right);
+ leftwish = v_left * (fup_left + fdown_left);
+ rightwish = v_right * (fup_right + fdown_right);
+
+ return (upwish+leftwish+downwish+rightwish) * 0.25;
+
+ //point = point * 0.2; // /5
+
+ // return normalize(point - self.origin) * (1- (fup_left+fup_right+fdown_left+fdown_right) * 0.25);
+}
+
+
+
+//////////////////////////////////////////////
+// Testting //
+// Everything below this point is a mess :D //
+//////////////////////////////////////////////
+#define TLIBS_TETSLIBS
+#ifdef TLIBS_TETSLIBS
+void flocker_die()
+{
+ sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+
+ pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+
+ self.owner.cnt += 1;
+ self.owner = world;
+
+ self.nextthink = time;
+ self.think = SUB_Remove;
+}
+
+
+void flocker_think()
+{
+ vector dodgemove,swarmmove;
+ vector reprellmove,wandermove,newmove;
+
+ self.angles_x = self.angles_x * -1;
+ makevectors(self.angles);
+ self.angles_x = self.angles_x * -1;
+
+ dodgemove = steerlib_traceavoid(0.35,1000);
+ swarmmove = steerlib_swarm(1000,100,150,400);
+ reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,1000) * 700;
+
+ if(vlen(dodgemove) == 0)
+ {
+ self.pos1 = steerlib_waner(0.5,0.1,self.pos1);
+ wandermove = self.pos1 * 50;
+ }
+ else
+ self.pos1 = normalize(self.velocity);
+
+ dodgemove = dodgemove * 700;
+
+ newmove = swarmmove + reprellmove + wandermove + dodgemove;
+ self.velocity = movelib_inertmove_byspeed(newmove,900,0.4,0.8);
+ //self.velocity = movelib_inertmove(dodgemove,0.65);
+
+ self.velocity = movelib_drag(0.02,0.6);
+
+ self.angles = vectoangles(self.velocity);
+
+ if(self.health <= 0)
+ flocker_die();
+ else
+ self.nextthink = time + 0.1;
+}
+
+
+void spawn_flocker()
+{
+ entity flocker;
+
+ flocker = spawn ();
+
+ setorigin(flocker, self.origin + '0 0 32');
+ setmodel (flocker, "models/turrets/rocket.md3");
+ setsize (flocker, '-3 -3 -3', '3 3 3');
+
+ flocker.flock_id = self.flock_id;
+ flocker.classname = "flocker";
+ flocker.owner = self;
+ flocker.think = flocker_think;
+ flocker.nextthink = time + random() * 5;
+ flocker.solid = SOLID_BBOX;
+ flocker.movetype = MOVETYPE_BOUNCEMISSILE;
+ flocker.effects = EF_LOWPRECISION;
+ flocker.velocity = randomvec() * 300;
+ flocker.angles = vectoangles(flocker.velocity);
+ flocker.health = 10;
+ flocker.pos1 = normalize(flocker.velocity + randomvec() * 0.1);
+
+ self.cnt = self.cnt -1;
+
+}
+
+void flockerspawn_think()
+{
+
+
+ if(self.cnt > 0)
+ spawn_flocker();
+
+ self.nextthink = time + self.delay;
+
+}
+
+void flocker_hunter_think()
+{
+ vector dodgemove,attractmove,newmove;
+ entity e,ee;
+ float d,bd;
+
+ self.angles_x = self.angles_x * -1;
+ makevectors(self.angles);
+ self.angles_x = self.angles_x * -1;
+
+ if(self.enemy)
+ if(vlen(self.enemy.origin - self.origin) < 64)
+ {
+ ee = self.enemy;
+ ee.health = -1;
+ self.enemy = world;
+
+ }
+
+ if(!self.enemy)
+ {
+ e = findchainfloat(flock_id,self.flock_id);
+ while(e)
+ {
+ d = vlen(self.origin - e.origin);
+
+ if(e != self.owner)
+ if(e != ee)
+ if(d > bd)
+ {
+ self.enemy = e;
+ bd = d;
+ }
+ e = e.chain;
+ }
+ }
+
+ if(self.enemy)
+ attractmove = steerlib_attract(self.enemy.origin,5000) * 1100;
+ else
+ attractmove = normalize(self.velocity) * 200;
+
+ dodgemove = steerlib_traceavoid(0.35,1500) * 1700;
+
+ newmove = dodgemove + attractmove;
+ self.velocity = movelib_inertmove_byspeed(newmove,850,0.5,0.9);
+ self.velocity = movelib_drag(0.01,0.5);
+
+
+ self.angles = vectoangles(self.velocity);
+ self.nextthink = time + 0.1;
+}
+
+
+float globflockcnt;
+void spawnfunc_flockerspawn()
+{
+ precache_model ( "models/turrets/rocket.md3");
+ precache_model("models/turrets/c512.md3");
+ ++globflockcnt;
+
+ if(!self.cnt) self.cnt = 20;
+ if(!self.delay) self.delay = 0.25;
+ if(!self.flock_id) self.flock_id = globflockcnt;
+
+ self.think = flockerspawn_think;
+ self.nextthink = time + 0.25;
+
+ self.enemy = spawn();
+
+ setmodel(self.enemy, "models/turrets/rocket.md3");
+ setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
+
+ self.enemy.classname = "FLock Hunter";
+ self.enemy.scale = 3;
+ self.enemy.effects = EF_LOWPRECISION;
+ self.enemy.movetype = MOVETYPE_BOUNCEMISSILE;
+ self.enemy.solid = SOLID_BBOX;
+ self.enemy.think = flocker_hunter_think;
+ self.enemy.nextthink = time + 10;
+ self.enemy.flock_id = self.flock_id;
+ self.enemy.owner = self;
+}
+#endif
More information about the nexuiz-commits
mailing list