Homing Grenades


 

Posted by WarZone (209.223.137.*) on February 06, 1999 at 15:02:42:


//========================================================================
void Homing_Think(edict_t *grenade) {
  vec3_t dir, forward, right, up;
  edict_t *ent = NULL;
  edict_t *best = NULL;
  float b_dist = 99999;
  float dist = 0;


  if (grenade->delay > level.time)
    return;

  //pick the closest "enemy" or, keep the current one
/*
  //uncomment this if you like
  if (grenade->goalentity && grenade->goalentity->inuse && !grenade->goalentity->deadflag)
    best = grenade->goalentity;
  else
*/
  while ((ent = findradius (ent, grenade->s.origin, 1500)) != NULL)
  {
    if (ent == grenade->owner)
      continue;
    if (!ent->takedamage)
      continue;
    if (OnSameTeam(ent, grenade->owner))
      continue;

    if (ent->deadflag == DEAD_DEAD)
      continue;
    if (!CanDamage (grenade, ent))
      continue;

    VectorSubtract (ent->s.origin, grenade->s.origin, dir);
    dist = VectorLength (dir);
    if (dist < b_dist)
    {
      b_dist = dist;
      best = ent;
    }
  }
  grenade->goalentity = best;
 
  if (grenade->goalentity)
  {
//    gi.dprintf ("targeting %s\n", grenade->goalentity->classname);

    // Calculate some directional stuff..
    VectorSubtract(grenade->goalentity->s.origin, grenade->s.origin, dir);

    vectoangles (dir, dir);
    VectorCopy (dir, grenade->s.angles);
    VectorCopy (dir, grenade->movedir);
    AngleVectors(dir, forward, right, up);

    right[0] += 5 * crandom();
    right[1] += 5 * crandom();
    right[2] = 0;

    VectorNormalize(dir);

    VectorMA(dir, 20 + 20 * random(), up, grenade->velocity);
    VectorMA(dir, 10 * crandom(), right, grenade->velocity);
    VectorMA(dir, 250, forward, grenade->velocity);

    //make it roll :)
    VectorSet (grenade->avelocity, 0, VectorLength (grenade->velocity), 0); // is that the right axis??
    grenade->groundentity = NULL;
  }
  else if (rand() % 20 == 0)
    grenade->think (grenade); // blow it up randomly if it can't find a target
}

//========================================================================
void Fire_Homing_Grenade (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float damage_radius)
{
  edict_t *grenade;
  vec3_t dir, forward, right, up;

  vectoangles (aimdir, dir);
  AngleVectors (dir, forward, right, up);


  grenade = G_Spawn();
  grenade->owner = self;
  grenade->activator = self;
  grenade->goalentity = NULL; // Targeted Player.
  grenade->classname = "hominggrenade";
  VectorCopy (start, grenade->s.origin);
  grenade->s.origin[2] += 10;
  VectorScale (aimdir, speed, grenade->velocity);
  VectorMA (grenade->velocity, 100 + random() * 30.0, up, grenade->velocity);
  VectorMA (grenade->velocity, crandom() * 10.0, right, grenade->velocity);
  VectorSet (grenade->avelocity, 300, 300, 300);
  grenade->movetype = MOVETYPE_BOUNCE;
  grenade->clipmask = MASK_SHOT;
  grenade->solid = SOLID_BBOX;
  grenade->s.effects |= EF_GRENADE;
  VectorSet(grenade->mins, -3, -3, -3);
  VectorSet(grenade->maxs, 3, 3, 3);
  grenade->s.modelindex = gi.modelindex("models/objects/grenade2/tris.md2");
  grenade->dmg = damage;
  grenade->dmg_radius = damage_radius;
  grenade->spawnflags = 1;
  grenade->s.sound = gi.soundindex("world/airhiss1.wav");

  grenade->delay = level.time + 1.5;

  grenade->touch = Grenade_Touch;
  grenade->prethink = Homing_Think;
  grenade->nextthink = level.time + 10.0;
  grenade->think = Grenade_Explode;

  gi.linkentity(grenade);
}

Paste the above near the top of g_weapon.c then paste the following line somewhere in your sorce. As a test, you could also put this code at the top of the fire_grenade2() function with a "return;" right afterward to turn all of your hand grenades into homing grenades. Or, you might want to toggle the homing grenades via a client command. Its up to you.


  Fire_Homing_Grenade (player, start, aimdir, damage, 20, dmg_radius); // change the parameters as neccessary!


-- WarZone