Author Topic: Hive's swarm following around the corners.  (Read 11617 times)

==Troy==

  • Posts: 440
  • Turrets: +65/-67
Hive's swarm following around the corners.
« on: August 18, 2008, 09:00:43 pm »
A small patch (diff from latest Lakitu) which allows swarms to follow players around the corners. Its not the most optimal way to do it, but it works nicely and it is quite hard to get rid of the swarm, only doors or complicated brushwork will help.


Code: [Select]
Index: src/game/g_local.h
===================================================================
--- src/game/g_local.h (revision 87)
+++ src/game/g_local.h (working copy)
@@ -242,6 +242,10 @@
   int               lastDamageTime;
   
   int               bdnumb; // buildlog entry ID

+    #define MAX_WPA 31
+  vec3_t WPA[ MAX_WPA + 1 ];
+  int TotalWP;
 };
 
 typedef enum
Index: src/game/g_missile.c
===================================================================
--- src/game/g_missile.c (revision 87)
+++ src/game/g_missile.c (working copy)
@@ -582,34 +582,127 @@
 */
 void AHive_SearchAndDestroy( gentity_t *self )
 {
+
   vec3_t dir;
-  trace_t tr;
-
+  trace_t tr, tr2, tr3;
+  vec3_t Torigin;
+  gentity_t *traceEnt;

+ if (self->TotalWP == 0 )
+ {
+ self->TotalWP++;
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ 0 ]);
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ self->TotalWP ]);
+ }
   trap_Trace( &tr, self->r.currentOrigin, self->r.mins, self->r.maxs,
               self->target_ent->r.currentOrigin, self->r.ownerNum, self->clipmask );
+  traceEnt = &g_entities[ tr.entityNum ];
 
   //if there is no LOS or the parent hive is too far away or the target is dead or notargeting, return
-  if( tr.entityNum == ENTITYNUM_WORLD ||
-      Distance( self->r.currentOrigin, self->parent->r.currentOrigin ) > ( HIVE_RANGE * 5 ) ||
+  if( Distance( self->r.currentOrigin, self->parent->r.currentOrigin ) > ( HIVE_RANGE * 30 ) ||
       self->target_ent->health <= 0 || self->target_ent->flags & FL_NOTARGET )
   {
     self->r.ownerNum = ENTITYNUM_WORLD;
 
     self->think = AHive_ReturnToHive;
     self->nextthink = level.time + FRAMETIME;
+ return;
   }
   else
   {
-    VectorSubtract( self->target_ent->r.currentOrigin, self->r.currentOrigin, dir );
+ if ( tr.entityNum == ENTITYNUM_WORLD || traceEnt->s.eType == ET_BUILDABLE)
+ {
+ trap_Trace( &tr2, self->WPA[ self->TotalWP - 1 ], self->r.mins, self->r.maxs,
+ self->target_ent->r.currentOrigin, self->r.ownerNum, self->clipmask );
+     traceEnt = &g_entities[ tr2.entityNum ];
+ if ( tr2.entityNum == ENTITYNUM_WORLD || traceEnt->s.eType == ET_BUILDABLE )
+ {
+ trap_Trace( &tr3, self->WPA[ self->TotalWP ], self->r.mins, self->r.maxs,
+ self->target_ent->r.currentOrigin, self->r.ownerNum, self->clipmask ); // if the player turned around another corner while we were thinking, drop the target.
+   traceEnt = &g_entities[ tr3.entityNum ];
+ if ( tr3.entityNum == ENTITYNUM_WORLD || traceEnt->s.eType == ET_BUILDABLE )
+ {
+ self->r.ownerNum = ENTITYNUM_WORLD;
+
+ self->think = AHive_ReturnToHive;
+ self->nextthink = level.time + FRAMETIME;
+ //trap_SendServerCommand( -1, va( "print \"Lost Target\n\""));
+ return; // lost the track, get back home
+ }
+ else
+ {
+ if (self->TotalWP < MAX_WPA)
+ {
+ self->TotalWP++;
+ //trap_SendServerCommand( -1, va( "print \"New Waypoint, %i\n\"", self->TotalWP - 1));
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ self->TotalWP ]);
+ }
+ else
+ {
+ self->r.ownerNum = ENTITYNUM_WORLD;
+
+ self->think = AHive_ReturnToHive;
+ self->nextthink = level.time + FRAMETIME;
+ //trap_SendServerCommand( -1, va( "print \"Out Of memory\n\""));
+ return; // out of memory, get back home
+ }
+ }
+ }
+ else
+ {
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ self->TotalWP ]); //update latest waypoint without creating a new one, if there is a LOS from the old one
+ }
+ }
+ else
+ {
+ int i;
+ if (self->TotalWP > 1)
+ {
+ self->TotalWP = 1;
+ //trap_SendServerCommand( -1, va( "print \"Direct Line of Sight\n\""));
+ }
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ 0 ]);
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ self->TotalWP ]);
+
+
+ }
+
+ if (Distance( self->r.currentOrigin, self->WPA[ 0 ]) < 64 && self->TotalWP > 1) // snap the swarm to the waypoint if it is close enough.
+ {
+ int i;
+ VectorCopy(self->WPA[ 0 ], self->r.currentOrigin);
+ for (i = 0; i <= MAX_WPA; i++)
+ {
+ VectorCopy(self->WPA[i+1], self->WPA[i]);
+ }
+ self->TotalWP--;
+ if (self->TotalWP < 1) self->TotalWP = 1;
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ self->TotalWP ]);
+ //trap_SendServerCommand( -1, va( "print \"Waypoint Reached\n\""));
+ }
+
+ trap_Trace( &tr, self->r.currentOrigin, self->r.mins, self->r.maxs,
+        self->WPA[ 0 ], self->r.ownerNum, self->clipmask );
+   traceEnt = &g_entities[ tr.entityNum ];
+ if ( tr.entityNum == ENTITYNUM_WORLD || traceEnt->s.eType == ET_BUILDABLE )  // check for doors closing
+ {
+
+     self->r.ownerNum = ENTITYNUM_WORLD;
+
+ self->think = AHive_ReturnToHive;
+ self->nextthink = level.time + FRAMETIME;
+ //trap_SendServerCommand( -1, va( "print \"Invalid Waypoint\n\""));
+ return;
+ }
+
+ VectorSubtract( self->WPA[ 0 ], self->r.currentOrigin, dir );
     VectorNormalize( dir );
-
     //change direction towards the player
     VectorScale( dir, HIVE_SPEED, self->s.pos.trDelta );
     SnapVector( self->s.pos.trDelta );      // save net bandwidth
     VectorCopy( self->r.currentOrigin, self->s.pos.trBase );
     self->s.pos.trTime = level.time;
-
-    self->nextthink = level.time + HIVE_DIR_CHANGE_PERIOD;
+    self->nextthink = level.time + HIVE_DIR_CHANGE_PERIOD/2;
   }
 }
 
@@ -641,7 +734,8 @@
   bolt->methodOfDeath = MOD_SWARM;
   bolt->clipmask = MASK_SHOT;
   bolt->target_ent = self->target_ent;
-
+  bolt->TotalWP = 0;

   bolt->s.pos.trType = TR_LINEAR;
   bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME;   // move a bit on the very first frame
   VectorCopy( start, bolt->s.pos.trBase );

« Last Edit: August 25, 2008, 09:38:29 pm by ==Troy== »

mooseberry

  • Community Moderators
  • *
  • Posts: 4005
  • Turrets: +666/-325
Re: Hive's swarm following around the corners.
« Reply #1 on: August 18, 2008, 09:08:16 pm »
Yay, even more annoying hives!  :P

But good work!
Bucket: [You hear the distant howl of a coyote losing at Counterstrike.]

मैं हिन्दी का समर्थन

~Mooseberry.

Lakitu7

  • Tremulous Developers
  • *
  • Posts: 1002
  • Turrets: +120/-73
Re: Hive's swarm following around the corners.
« Reply #2 on: August 18, 2008, 09:47:34 pm »
Hmm, nice idea and nice work. I'm going to poke Norf and see what he thinks about trying a change like this on mgdev...

Norfenstein

  • Posts: 628
  • Turrets: +81/-78
Re: Hive's swarm following around the corners.
« Reply #3 on: August 18, 2008, 10:23:40 pm »
I'm not sure how often people actually try to run away from the swarms (I usually just dance around in the alien base until I die) but they do still need something, and this sounds like something good to try.

==Troy==

  • Posts: 440
  • Turrets: +65/-67
Re: Hive's swarm following around the corners.
« Reply #4 on: August 18, 2008, 11:05:32 pm »
Updated the code a little, added a WORKING check for doors now. :)

Bissig

  • Posts: 1309
  • Turrets: +103/-131
Re: Hive's swarm following around the corners.
« Reply #5 on: August 18, 2008, 11:28:28 pm »
I'd like to see swarms being more efficient ;-) Nice work!

techhead

  • Posts: 1496
  • Turrets: +77/-73
    • My (Virtually) Infinite Source of Knowledge (and Trivia)
Re: Hive's swarm following around the corners.
« Reply #6 on: August 19, 2008, 03:39:26 am »
I honestly think that they should either move slightly faster or slightly slower. With them moving at the same speed as a non-sprinting human, one can run in circles for a while until the swarm gets bored and runs back to the hive. Between non-sprint and sprint would be best, in my honest opinion.
Also, they should be unable to travel through water, even though water is seldom used in Tremulous maps.
I'm playing Tremulous on a Mac!
MGDev fan-club member
Techhead||TH
/"/""\"\
\"\""/"/
\\:.V.://
Copy and paste Granger into your signature!

==Troy==

  • Posts: 440
  • Turrets: +65/-67
Re: Hive's swarm following around the corners.
« Reply #7 on: August 25, 2008, 09:38:48 pm »
fixed a memory leak, the top post is updated.

Paradox

  • Posts: 2612
  • Turrets: +253/-250
    • Paradox Designs
Re: Hive's swarm following around the corners.
« Reply #8 on: August 26, 2008, 02:33:32 am »
Added to the P-G-Qvm porting list.

Soon ill have patched up and released a new version.

∧OMG ENTROPY∧

professor

  • Posts: 232
  • Turrets: +1/-33
Re: Hive's swarm following around the corners.
« Reply #9 on: August 26, 2008, 06:19:28 am »
 i like this idea
hows this though... u get a trapper :trapper: and mix it wit a hive :hive: then when the hummys come the swarm carrys the trapper juice and chases the hummy :human:
and its stuck till a friendly tyrant :tyrant: or granger :granger: wit :grenade: comes along!
http://static.flickr.com/24/141310872_e39ad59705_b.jpg
omg! someone cut the arm off my tyrant!!

Bomb

  • Guest
Re: Hive's swarm following around the corners.
« Reply #10 on: August 26, 2008, 02:20:29 pm »
i like this idea
hows this though... u get a trapper :trapper: and mix it wit a hive :hive: then when the hummys come the swarm carrys the trapper juice and chases the hummy :human:
and its stuck till a friendly tyrant :tyrant: or granger :granger: wit :grenade: comes along!


Lava Croft

  • Guest
Re: Hive's swarm following around the corners.
« Reply #11 on: August 26, 2008, 04:50:17 pm »
I'm starting to get visions of System Shock 2's bees. Good work!

professor

  • Posts: 232
  • Turrets: +1/-33
« Last Edit: August 26, 2008, 05:44:29 pm by professor »
http://static.flickr.com/24/141310872_e39ad59705_b.jpg
omg! someone cut the arm off my tyrant!!

==Troy==

  • Posts: 440
  • Turrets: +65/-67
Re: Hive's swarm following around the corners.
« Reply #13 on: September 01, 2008, 02:31:29 pm »
Hives can now shoot around corners (or rather, learn to shoot around corners). I am posting this separately, even though it uses the same principle as the above patch, but is not a realy improvement, just a different feature.

In this patch the hives learn to shoot around buildables/corners and the swarm itself follows the player around the corners/buildables, Yet again diff from Lakitu.

Code: [Select]
Index: src/game/g_buildable.c
===================================================================
--- src/game/g_buildable.c (revision 87)
+++ src/game/g_buildable.c (working copy)
@@ -1106,8 +1106,24 @@
 //==================================================================================
 
 
+qboolean Hive_CheckWP( vec3_t org1, vec3_t org2, gentity_t *ent )
+{
+  trace_t tr;
+  gentity_t *traceEnt;
 
+  trap_Trace( &tr, org1, NULL, NULL, org2, ent->s.number, MASK_SHOT );
+  traceEnt = &g_entities[ tr.entityNum ];

+  if( tr.entityNum == ENTITYNUM_WORLD || traceEnt->s.eType == ET_BUILDABLE )
+    return qfalse;
 
+  return qtrue;
+}
+
+
+
+
+
 /*
 ================
 AHive_Think
@@ -1120,10 +1136,14 @@
   int       entityList[ MAX_GENTITIES ];
   vec3_t    range = { ACIDTUBE_RANGE, ACIDTUBE_RANGE, ACIDTUBE_RANGE };
   vec3_t    mins, maxs;
-  int       i, num;
+  int       i, num, j, k;
   gentity_t *enemy;
   vec3_t    dirToTarget;
-
+  qboolean  visible, fvisible;
+  int TWP = -1, freeTWP = -1, createTWP = -1;
+  qboolean  WP1, WP2;


   self->powered = G_IsOvermindBuilt( );
 
   self->nextthink = level.time + BG_FindNextThinkForBuildable( self->s.modelindex );
@@ -1140,31 +1160,141 @@
 
   if( self->timestamp < level.time )
     self->active = qfalse; //nothing has returned in HIVE_REPEAT seconds, forget about it
-
+
+  if( self->RecheckTime < level.time)
+  {
+    self->RecheckTime = level.time + HIVE_RECHECK;
+ ;//trap_SendServerCommand( -1, va( "print \"Rechecking Hive, number of waypoints : %i\n\"", self->TotalWP));
+ for(j = 1; j <= self->TotalWP; j++)
+ {
+     while ( j <= self->TotalWP && (!Hive_CheckWP(self->r.currentOrigin, self->WPA[j-1], self) || (!Hive_CheckWP(self->WPA[j-1], self->WPA2[j-1], self) && self->inUse[j-1])))
+ {
+   for(k = j; k <= self->TotalWP; k++)
+   {
+     VectorCopy(self->WPA[k], self->WPA[k-1]);
+ VectorCopy(self->WPA2[k], self->WPA2[k-1]);
+ self->inUse[k-1] = self->inUse[k];
+   }
+   self->TotalWP--;
+   ;//trap_SendServerCommand( -1, va( "print \"Removed invalid waypoint\n\""));
+ }
+ }
+  }


   if( self->spawned && !self->active && G_FindOvermind( self ) )
   {
     //do some damage
     num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
+ self->targWP = -1;
     for( i = 0; i < num; i++ )
     {
       enemy = &g_entities[ entityList[ i ] ];
 
       if( enemy->flags & FL_NOTARGET )
- continue;
+     continue;
 
-      if( enemy->health <= 0 )
+      if( enemy->health <= 0 || !enemy->client || enemy->client->ps.stats[ STAT_PTEAM ] != PTE_HUMANS)
         continue;
+
+   ;//trap_SendServerCommand( -1, va( "print \"Target Detected\n\""));
+      if( !Hive_CheckWP( self->r.currentOrigin, enemy->r.currentOrigin, self ) )
+   {
+     ;//trap_SendServerCommand( -1, va( "print \"no LOS, checking waypoints\n\""));
+ TWP = freeTWP = createTWP = -1;
+     for (j = 1; j <= self->TotalWP; j++)
+ {
+   WP1 = Hive_CheckWP( self->WPA[j-1], enemy->r.currentOrigin, self );
+   if( self->inUse[j-1] )
+     WP2 = Hive_CheckWP( self->WPA2[j-1], enemy->r.currentOrigin, self );
+   else
+     WP2 = qfalse;
+
+   if (!WP1 && WP2) { TWP = -2 - (j-1); break; }  
+   if (WP1 && WP2) { TWP = j-1; break; }
+   if (WP1 && !WP2 && self->inUse[j-1] ) createTWP = j-1;
+   if (WP1 && !self->inUse[j-1] ) freeTWP = j-1;
+ }
+
+ if (TWP == -1)
+ {
+   if (freeTWP == -1)
+   {
+     if (createTWP != -1 && self->TotalWP <= MAX_WPA)
+ {
+   VectorCopy( self->WPA[createTWP], self->WPA[self->TotalWP]);
+   VectorCopy( enemy->r.currentOrigin, self->WPA2[self->TotalWP]);
+       self->inUse[self->TotalWP] = qtrue;
+       self->TotalWP++;
+   self->targWP = createTWP;
+       ;//trap_SendServerCommand( -1, va( "print \"Waypoint cloned\n\""));
+ }
+   }
+   else
+   {
+     VectorCopy( enemy->r.currentOrigin, self->WPA2[freeTWP]);
+     self->inUse[freeTWP] = qtrue;
+ self->targWP = freeTWP;
+ ;//trap_SendServerCommand( -1, va( "print \"Secondary Assigned\n\""));
+   }  
+ }
+ else
+ {
+   self->targWP = TWP;
+   ;//trap_SendServerCommand( -1, va( "print \"Firing normally\n\""));
+ }
+
+
+ if (self->targWP == -1)
+   continue;
+ else
+   ;//trap_SendServerCommand( -1, va( "print \"Found Waypoint, here it goes!\n\""));
+  
+   }
+   else
+   {
+     ;//trap_SendServerCommand( -1, va( "print \"We have LOS, record waypoint\n\""));
+ if (self->TotalWP <= MAX_WPA)
+ {
+     visible = qfalse;
+ fvisible = qfalse;
+     for (j = 1; j <= self->TotalWP; j++)
+ {
+   if ( (self->inUse[j-1] && (visible = Hive_CheckWP(self->WPA2[j-1], enemy->r.currentOrigin, self))) || 
+        (!self->inUse[j-1] && (fvisible = Hive_CheckWP(self->WPA[j-1], enemy->r.currentOrigin, self)))) break;
+ }
+ if (!visible)
+ {
+   if (fvisible)
+   {
+ VectorCopy( enemy->r.currentOrigin, self->WPA[j-1]);
+ ;//trap_SendServerCommand( -1, va( "print \"Waypoint Replaced\n\""));
+   }
+   else
+   {
+   VectorCopy( enemy->r.currentOrigin, self->WPA[self->TotalWP]);
+   self->inUse[self->TotalWP] = qfalse;
+   self->TotalWP++;
+   ;//trap_SendServerCommand( -1, va( "print \"Waypoint Stored\n\""));
+   }
+ }
+ else
+   ;//trap_SendServerCommand( -1, va( "print \"Unnessesary Waypoint, ignored\n\""));
+ }
+ else
+   ;//trap_SendServerCommand( -1, va( "print \"Out of Memory, ignored\n\""));
+   }
+     
+ ;//trap_SendServerCommand( -1, va( "print \"Launching the swarm!\n\""));
 
-      if( !G_Visible( self, enemy ) )
-        continue;
-
-      if( enemy->client && enemy->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
-      {
         self->active = qtrue;
         self->target_ent = enemy;
         self->timestamp = level.time + HIVE_REPEAT;
-
-        VectorSubtract( enemy->s.pos.trBase, self->s.pos.trBase, dirToTarget );
+ if (self->targWP == -1)
+   VectorSubtract( enemy->s.pos.trBase, self->s.pos.trBase, dirToTarget );
+ else
+   VectorSubtract( self->WPA[self->targWP], self->s.pos.trBase, dirToTarget );
+
         VectorNormalize( dirToTarget );
         vectoangles( dirToTarget, self->turretAim );
 
@@ -1172,7 +1302,7 @@
         FireWeapon( self );
         G_SetBuildableAnim( self, BANIM_ATTACK1, qfalse );
         return;
-      }
+     
     }
   }
 
Index: src/game/g_local.h
===================================================================
--- src/game/g_local.h (revision 87)
+++ src/game/g_local.h (working copy)
@@ -242,6 +242,15 @@
   int               lastDamageTime;
   
   int               bdnumb; // buildlog entry ID

+    #define MAX_WPA 31
+ #define HIVE_RECHECK 30000
+  vec3_t WPA[ MAX_WPA + 1 ];
+  vec3_t WPA2[ MAX_WPA + 1 ];
+  qboolean inUse[ MAX_WPA + 1];
+  int TotalWP;
+  int targWP;
+  int RecheckTime;
 };
 
 typedef enum
Index: src/game/g_missile.c
===================================================================
--- src/game/g_missile.c (revision 87)
+++ src/game/g_missile.c (working copy)
@@ -582,34 +582,127 @@
 */
 void AHive_SearchAndDestroy( gentity_t *self )
 {
+
   vec3_t dir;
-  trace_t tr;
-
+  trace_t tr, tr2, tr3;
+  vec3_t Torigin;
+  gentity_t *traceEnt;

+ if (self->TotalWP == 0 )
+ {
+ self->TotalWP++;
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ 0 ]);
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ self->TotalWP ]);
+ }
   trap_Trace( &tr, self->r.currentOrigin, self->r.mins, self->r.maxs,
               self->target_ent->r.currentOrigin, self->r.ownerNum, self->clipmask );
+  traceEnt = &g_entities[ tr.entityNum ];
 
   //if there is no LOS or the parent hive is too far away or the target is dead or notargeting, return
-  if( tr.entityNum == ENTITYNUM_WORLD ||
-      Distance( self->r.currentOrigin, self->parent->r.currentOrigin ) > ( HIVE_RANGE * 5 ) ||
+  if( Distance( self->r.currentOrigin, self->parent->r.currentOrigin ) > ( HIVE_RANGE * 30 ) ||
       self->target_ent->health <= 0 || self->target_ent->flags & FL_NOTARGET )
   {
     self->r.ownerNum = ENTITYNUM_WORLD;
 
     self->think = AHive_ReturnToHive;
     self->nextthink = level.time + FRAMETIME;
+ return;
   }
   else
   {
-    VectorSubtract( self->target_ent->r.currentOrigin, self->r.currentOrigin, dir );
+ if ( tr.entityNum == ENTITYNUM_WORLD || traceEnt->s.eType == ET_BUILDABLE)
+ {
+ trap_Trace( &tr2, self->WPA[ self->TotalWP - 1 ], self->r.mins, self->r.maxs,
+ self->target_ent->r.currentOrigin, self->r.ownerNum, self->clipmask );
+     traceEnt = &g_entities[ tr2.entityNum ];
+ if ( tr2.entityNum == ENTITYNUM_WORLD || traceEnt->s.eType == ET_BUILDABLE )
+ {
+ trap_Trace( &tr3, self->WPA[ self->TotalWP ], self->r.mins, self->r.maxs,
+ self->target_ent->r.currentOrigin, self->r.ownerNum, self->clipmask ); // if the player turned around another corner while we were thinking, drop the target.
+   traceEnt = &g_entities[ tr3.entityNum ];
+ if ( tr3.entityNum == ENTITYNUM_WORLD || traceEnt->s.eType == ET_BUILDABLE )
+ {
+ self->r.ownerNum = ENTITYNUM_WORLD;
+
+ self->think = AHive_ReturnToHive;
+ self->nextthink = level.time + FRAMETIME;
+ //;//trap_SendServerCommand( -1, va( "print \"Lost Target\n\""));
+ return; // lost the track, get back home
+ }
+ else
+ {
+ if (self->TotalWP < MAX_WPA)
+ {
+ self->TotalWP++;
+ //;//trap_SendServerCommand( -1, va( "print \"New Waypoint, %i\n\"", self->TotalWP - 1));
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ self->TotalWP ]);
+ }
+ else
+ {
+ self->r.ownerNum = ENTITYNUM_WORLD;
+
+ self->think = AHive_ReturnToHive;
+ self->nextthink = level.time + FRAMETIME;
+ //;//trap_SendServerCommand( -1, va( "print \"Out Of memory\n\""));
+ return; // out of memory, get back home
+ }
+ }
+ }
+ else
+ {
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ self->TotalWP ]); //update latest waypoint without creating a new one, if there is a LOS from the old one
+ }
+ }
+ else
+ {
+ int i;
+ if (self->TotalWP > 1)
+ {
+ self->TotalWP = 1;
+ //;//trap_SendServerCommand( -1, va( "print \"Direct Line of Sight\n\""));
+ }
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ 0 ]);
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ self->TotalWP ]);
+
+
+ }
+
+ if (Distance( self->r.currentOrigin, self->WPA[ 0 ]) < 64 && self->TotalWP > 1) // snap the swarm to the waypoint if it is close enough.
+ {
+ int i;
+ VectorCopy(self->WPA[ 0 ], self->r.currentOrigin);
+ for (i = 0; i <= MAX_WPA; i++)
+ {
+ VectorCopy(self->WPA[i+1], self->WPA[i]);
+ }
+ self->TotalWP--;
+ if (self->TotalWP < 1) self->TotalWP = 1;
+ VectorCopy(self->target_ent->r.currentOrigin, self->WPA[ self->TotalWP ]);
+ //;//trap_SendServerCommand( -1, va( "print \"Waypoint Reached\n\""));
+ }
+
+ trap_Trace( &tr, self->r.currentOrigin, self->r.mins, self->r.maxs,
+        self->WPA[ 0 ], self->r.ownerNum, self->clipmask );
+   traceEnt = &g_entities[ tr.entityNum ];
+ if ( tr.entityNum == ENTITYNUM_WORLD || traceEnt->s.eType == ET_BUILDABLE )  // check for doors closing
+ {
+
+     self->r.ownerNum = ENTITYNUM_WORLD;
+
+ self->think = AHive_ReturnToHive;
+ self->nextthink = level.time + FRAMETIME;
+ //;//trap_SendServerCommand( -1, va( "print \"Invalid Waypoint\n\""));
+ return;
+ }
+
+ VectorSubtract( self->WPA[ 0 ], self->r.currentOrigin, dir );
     VectorNormalize( dir );
-
     //change direction towards the player
     VectorScale( dir, HIVE_SPEED, self->s.pos.trDelta );
     SnapVector( self->s.pos.trDelta );      // save net bandwidth
     VectorCopy( self->r.currentOrigin, self->s.pos.trBase );
     self->s.pos.trTime = level.time;
-
-    self->nextthink = level.time + HIVE_DIR_CHANGE_PERIOD;
+    self->nextthink = level.time + HIVE_DIR_CHANGE_PERIOD/2;
   }
 }
 
@@ -641,7 +734,29 @@
   bolt->methodOfDeath = MOD_SWARM;
   bolt->clipmask = MASK_SHOT;
   bolt->target_ent = self->target_ent;
-
+  bolt->TotalWP = 0;

+  if(self->targWP != -1)
+  {
+    if(self->targWP >= 0)
+    {
+ bolt->TotalWP++;
+ VectorCopy(self->WPA[self->targWP], bolt->WPA[ 0 ]);
+ VectorCopy(self->WPA[self->targWP], bolt->WPA[ bolt->TotalWP ]);
+     ;//trap_SendServerCommand( -1, va( "print \"Swarm : Waypoint Received, proceeding to target\n\""));
+ }
+ else
+ {
+ int TW;
+ TW = abs(self->targWP) - 2;
+ bolt->TotalWP += 2;
+ VectorCopy(self->WPA[TW], bolt->WPA[ 0 ]);
+ VectorCopy(self->WPA2[TW], bolt->WPA[ 1 ]);
+ VectorCopy(self->WPA2[TW], bolt->WPA[ bolt->TotalWP ]);
+     ;//trap_SendServerCommand( -1, va( "print \"Swarm : 2 Waypoints received, proceeding to target\n\""));
+ }
+  }

   bolt->s.pos.trType = TR_LINEAR;
   bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME;   // move a bit on the very first frame
   VectorCopy( start, bolt->s.pos.trBase );




Edit : pwef! added even more complicated algorythm, since the first one did not solve the problem for all cases that could happen. Not the best way to implement, but it is quite effective.
« Last Edit: September 01, 2008, 09:52:43 pm by ==Troy== »