This tutorial was originally written by AssKicka at solidground@planetquake.com.

Included here are personal notes made to deal with areas that were difficult to follow in the original tutorial due to for example differing version numbers.

To get around the problem of differing numbers included the source code necessary to determine the where the changes need to be made will be included as well as a rough line number

This version assumes that the following versions are being used: Note
1. Adding the function that will search the area for targets to suck

file - g_utils.c
line - anywhere, suggest at the end of the file
note - This function runs through all the entities in a level and checks if any entities are in the radius (rad) of the entity 'ent'. The 'ent' entity and 'rad' float are passed to this function from the calling function.
/*
================
findradius, tute11.1
================
*/
gentity_t *findradius (gentity_t *ent, vec3_t org, float rad) 
{
   vec3_t eorg;
   int j;

   if (!ent)
      ent = g_entities;
   else
      ent++;

   for (; ent < &g_entities[level.num_entities]; ent++)
   {
      if (!ent->inuse)
         continue;

      for (j=0; j<3; j++)
         eorg[j] = org[j] - (ent->r.currentOrigin[j] + (ent->r.mins[j] + ent->r.maxs[j])*0.5);

      if (VectorLength(eorg) > rad)
         continue;
         return ent;
   }

   return NULL;
}       

file - g_local.h
line - 442
note - adding the function prototype
//
// g_utils.c
//
   gentity_t *findradius (gentity_t *ent, vec3_t org, float rad); //tute11.2      

file - g_missile.c
line - near the other think functions
note - adding the entity think function
/*
================
G_RunMissile
================
*/
void G_RunMissile( gentity_t *ent ) 
{
   .
   .
   .
}   

/*
=================
G_Suck //tute11.3
=================
*/
static void G_Suck( gentity_t *self ) 
{
   gentity_t *target;
   vec3_t start,dir,end;

   target = NULL;

   //check if there are any entity's within a radius of 500 units.
   while ((target = findradius(target, self->r.currentOrigin, 500)) != NULL)
   {
      // target must not be vortex grenade
      if (target == self) 
         continue;

      // target must be a client
      if (!target->client) 
         continue;

      // target must not be the player who fired the vortex grenade 
      if (target == self->parent) 
         continue;

      // target must be able to take damage
      if (!target->takedamage) 
         continue;

         // put target position in start
         VectorCopy(target->r.currentOrigin, start); 
         
         // put grenade position in end
         VectorCopy(self->r.currentOrigin, end); 
         
         // subtract start from end to get directional vector
         VectorSubtract(end, start, dir); 
         
         VectorNormalize(dir); 

         // scale directional vector by 200 and add to the targets velocity
         VectorScale(dir,200, target->client->ps.velocity);
         
         // make targets move direction = to directional vector.
         VectorCopy(dir, target->movedir); 
   }

   self->nextthink = level.time + 20; 

   // check if vortext grenade is older than 20 seconds.
   if (level.time > self->wait) 
      G_ExplodeMissile( self);
}

4. Changing the fire_grenade function's think function

file - g_missle.c
line - 635
/*
=================
fire_grenade
=================
*/
gentity_t *fire_grenade (gentity_t *self, vec3_t start, vec3_t dir) {
   .
   .
   .
   bolt->nextthink = level.time + 2500;
   bolt->think = G_ExplodeMissile;
   .
   .
   .
}   

to look like this

/*
=================
fire_grenade
=================
*/
gentity_t *fire_grenade (gentity_t *self, vec3_t start, vec3_t dir) {
   .
   .
   .
   //tute11.4
   bolt->nextthink = level.time + 1000; // call G_Suck in 1 second
   bolt->think = G_Suck;
   bolt->wait = level.time + 20000; // vortext grenade lifetime.
   .
   .
   .
}   



Recompile game.



Disclaimer:
This is a personal page published by the author. The ideas and information expressed on it have not been approved or authorised by Monash University either explicitly or impliedly. In no event shall Monash University be liable for any damages whatsoever resulting from any action arising in connection with the use of this information or its publication, including any action for infringement of copyright or defamation.