Example #1
0
HLDS_DLLEXPORT void SV_MoveToOrigin_I(edict_t *ent, const vec3_t pflGoal, float dist, int iMoveType) {

   vec3_t var_c_temp;


   var_c_temp[0] = pflGoal[0];
   var_c_temp[1] = pflGoal[1];
   var_c_temp[2] = pflGoal[2];

   if(ent->v.flags & (FL_FLY | FL_SWIM | FL_ONGROUND)) {
      if(iMoveType == MOVE_NORMAL) {

         if(SV_StepDirection(ent, ent->v.ideal_yaw, dist) == 0) {
            SV_NewChaseDir2(ent, var_c_temp, dist);
         }
      }
      else {

         var_c_temp[0] -= ent->v.origin[0];
         var_c_temp[1] -= ent->v.origin[1];

         if(ent->v.flags & (FL_FLY | FL_SWIM)) {
            var_c_temp[2] -= ent->v.origin[2];
         }
         else { //If on ground, I guess we just don't worry about the third axis.  Sorta makes sense.
            var_c_temp[2] = 0;
         }

         VectorNormalize(var_c_temp);
         VectorScale(var_c_temp, dist, var_c_temp);
         SV_FlyDirection(ent, var_c_temp);
      }
   }
}
Example #2
0
void SV_MoveToOrigin( edict_t *ent, const vec3_t pflGoal, float dist, int iMoveType )
{
	vec3_t	vecDist;

	VectorCopy( pflGoal, vecDist );

	if( ent->v.flags & ( FL_FLY|FL_SWIM|FL_ONGROUND ))
	{
		if( iMoveType == MOVE_NORMAL )
		{
			if( SV_StepDirection( ent, ent->v.ideal_yaw, dist ) == 0 )
			{
				SV_NewChaseDir( ent, vecDist, dist );
			}
		}
		else
		{
			vecDist[0] -= ent->v.origin[0];
			vecDist[1] -= ent->v.origin[1];

			if( ent->v.flags & ( FL_FLY|FL_SWIM ))
				vecDist[2] -= ent->v.origin[2];
			else vecDist[2] = 0.0f;

			VectorNormalize( vecDist );
			VectorScale( vecDist, dist, vecDist );
			SV_FlyDirection( ent, vecDist );
		}
	}
}
Example #3
0
void SV_NewChaseDir1 (edict_t *self, edict_t *goal, float dist)
{
	int		i, bestyaw, minyaw, maxyaw;	
	vec3_t	v;

	if (!goal)
		return;

	VectorSubtract(goal->s.origin, self->s.origin, v);
	bestyaw = vectoyaw(v);

	minyaw = bestyaw - 90;
	maxyaw = bestyaw + 90;

	if (minyaw < 0)
		minyaw += 360;
	if (maxyaw > 360)
		maxyaw -= 360;

	for (i=minyaw; i<maxyaw; i+=30) {
		if (SV_StepDirection(self, i, dist, false))
			return;
	}

	//gi.dprintf("couldnt find a better direction!\n");
	SV_NewChaseDir(self, goal, dist);
}
Example #4
0
/*
======================
SV_MoveToGoal

======================
*/
void SV_MoveToGoal (void)
{
	edict_t		*ent, *goal;
	float		dist;
#ifdef QUAKE2
	edict_t		*enemy;
#endif

	ent = PROG_TO_EDICT(pr_global_struct->self);
	goal = PROG_TO_EDICT(ent->v.goalentity);
	dist = G_FLOAT(OFS_PARM0);

	if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
	{
		G_FLOAT(OFS_RETURN) = 0;
		return;
	}

// if the next step hits the enemy, return immediately
#ifdef QUAKE2
	enemy = PROG_TO_EDICT(ent->v.enemy);
	if (enemy != sv.edicts &&  SV_CloseEnough (ent, enemy, dist) )
#else
	if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts &&  SV_CloseEnough (ent, goal, dist) )
#endif
		return;

// bump around...
	if ( (rand()&3)==1 ||
	!SV_StepDirection (ent, ent->v.ideal_yaw, dist))
	{
		SV_NewChaseDir (ent, goal, dist);
	}
}
Example #5
0
// NOTE: pos should be the final goal, because monster will stop moving after reaching it!
void M_MoveToPosition (edict_t *ent, vec3_t pos, float dist)
{
	vec3_t v;

	// stay in-place for medic healing
	if (ent->holdtime > level.time) 
		return;

	// need to be touching the ground
	if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM)) && !ent->waterlevel)
	{
		//gi.dprintf("not touching ground\n");
		return;
	}

	// we are close enough
	if (distance(ent->s.origin, pos) < 32)
	{
		//gi.dprintf("close enough %.0f\n", distance(ent->s.origin, pos));
		// look at the final position
		VectorSubtract(pos, ent->s.origin, v);
		VectorNormalize(v);
		ent->ideal_yaw = vectoyaw(v);
		M_ChangeYaw(ent);
		return;
	}

	// dont move so fast in the water
	if (!(ent->flags & (FL_FLY|FL_SWIM)) && (ent->waterlevel > 1))
		dist *= 0.5;

	// if we can't take a step, try moving in another direction
	if (!SV_StepDirection (ent, ent->ideal_yaw, dist, true))
	{
		//gi.dprintf("couldn't step\n");
		// if the monster hasn't moved much, then increment
		// the number of frames it has been stuck
		if (distance(ent->s.origin, ent->monsterinfo.stuck_org) < 64)
			ent->monsterinfo.stuck_frames++;
		else
			ent->monsterinfo.stuck_frames = 0;

		// record current position for comparison
		VectorCopy(ent->s.origin, ent->monsterinfo.stuck_org);

		// attempt a course-correction
		if (ent->inuse && (level.time > ent->monsterinfo.bump_delay))
		{
			//gi.dprintf("tried course correction\n");
			//SV_NewChaseDir (ent, goal, dist);
			SV_NewChaseDir2(ent, pos, dist);
			ent->monsterinfo.bump_delay = level.time + FRAMETIME*GetRandom(3, 9);
			return;
		}
	}
	//else
		//gi.dprintf("step OK\n");
}
Example #6
0
qboolean CheckYawStep (edict_t *self, float minyaw, float maxyaw, float dist)
{
	int		i, max;
	float	yaw;

	AngleCheck(&minyaw);
	AngleCheck(&maxyaw);

	// calculate the maximum yaw variance
	max = 360 - fabs(minyaw - maxyaw);

	// we will start at the minimum yaw angle and move towards maxyaw
	yaw = minyaw;

	for (i = 0; i < max; i += 30) 
	{
		// if we changed course a while ago, then try a partial step 50% of the time
		if (level.time - self->monsterinfo.bump_delay > 1.0 || random() < 0.5)
		{
			yaw += i;
			AngleCheck(&yaw);

			if (SV_StepDirection(self, yaw, dist, true))
			{
				//gi.dprintf("attempt small step\n");
				return true;
			}
		}
		// otherwise, we might be stuck, so try a full step
		else
		{
			if (SV_StepDirection(self, i, dist, false))
			{
				//gi.dprintf("attempt full step\n");
				return true;
			}
		}
	}

	return false;
}
Example #7
0
/*
====================
M_MoveAwayFromFlare
====================
*/
qboolean M_MoveAwayFromFlare(edict_t *self, float dist)
{
	edict_t *e = NULL;
	edict_t *goal = NULL;
	vec3_t delta;
	vec3_t forward;

	// find the closest flare
	while(1)
	{
		e = findradius(e, self->s.origin, 256);
		if (e == NULL)
			break;

		if (Q_stricmp(e->classname, "flare") == 0)
			break;
	}
	
	goal = G_Spawn();
	self->goalentity = goal;
	if (e == NULL)
	{
		// just move forward
		AngleVectors(self->s.angles, forward, NULL, NULL);
		VectorMA(self->s.origin, 128, forward, goal->s.origin);
	}
	else
	{
		VectorSubtract(self->s.origin, e->s.origin, delta);
		VectorNormalize(delta);
		VectorMA(self->s.origin, 128, delta, goal->s.origin);
	}

	if (rand() & (7 == 1))
	{
		// set the ideal_yaw
		VectorSubtract(goal->s.origin, self->s.origin, delta);
		self->ideal_yaw = vectoyaw(delta);
	}

	if ( (rand()&3)==1 || !SV_StepDirection (self, self->ideal_yaw, dist))
	{
		SV_NewChaseDir (self, goal, dist);
	}

	self->goalentity = NULL;
	G_FreeEdict(goal);

	return true;
}
Example #8
0
/*
======================
M_MoveToGoal
======================
*/
void M_MoveToGoal(edict_t *ent, float dist){
	edict_t	*goal;
	
	goal = ent->goalentity;
	
	if(!ent->groundentity && !(ent->flags &(FL_FLY | FL_SWIM)))
		return;
		
	// if the next step hits the enemy, return immediately
	if(ent->enemy && SV_CloseEnough(ent, ent->enemy, dist))
		return;
		
	// bump around...
	if((rand()&3) == 1 || !SV_StepDirection(ent, ent->ideal_yaw, dist)){
		if(ent->inuse)
			SV_NewChaseDir(ent, goal, dist);
	}
}
Example #9
0
/*
======================
SV_MoveToGoal

======================
*/
void SV_MoveToGoal (void)
{
	edict_t		*ent, *goal;
	float		dist;

	ent = PROG_TO_EDICT(PR_GLOBAL_STRUCT(self));	// Entity moving
	goal = PROG_TO_EDICT(ent->v.goalentity);	// its goalentity
	dist = G_FLOAT(OFS_PARM0);			// how far to move

// Reset trace_plane_normal
	VectorCopy(vec3_origin, PR_GLOBAL_STRUCT(trace_plane_normal));

// If not onground, flying, or swimming, return 0
	if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
	{
		G_FLOAT(OFS_RETURN) = 0;
		return;
	}

// if the next step hits the enemy, return immediately
	if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts &&  SV_CloseEnough (ent, goal, dist) )
	{
		G_FLOAT(OFS_RETURN) = 0;
		return;
	}

// bump around...
	if (!SV_StepDirection (ent, ent->v.ideal_yaw, dist))//If can't go in a direction (including step check) or 30% chance...
	{
		SV_NewChaseDir (ent, goal, dist);//Find a new direction to go in instead
		G_FLOAT(OFS_RETURN) = 0;
	}
	else
	{
		if ((rand()&3)==1)
		{
			SV_NewChaseDir (ent, goal, dist);//Find a new direction to go in instead
		}
		G_FLOAT(OFS_RETURN) = 1;
	}
	return;
}
Example #10
0
/*
======================
M_MoveToGoal
======================
*/
void M_MoveToGoal (edict_t *ent, float dist)
{
    edict_t		*goal;

    goal = ent->goalentity;

    if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM)))
        return;

// if the next step hits the enemy, return immediately
    if (ent->enemy &&  SV_CloseEnough (ent, ent->enemy, dist) )
        return;

// bump around...
//	if ( (rand()&3)==1 || !SV_StepDirection (ent, ent->ideal_yaw, dist))
// PMM - charging monsters (AI_CHARGING) don't deflect unless they have to
    if ( (((rand()&3)==1) && !(ent->monsterinfo.aiflags & AI_CHARGING)) || !SV_StepDirection (ent, ent->ideal_yaw, dist))
    {
        if (ent->inuse)
            SV_NewChaseDir (ent, goal, dist);
    }
}
Example #11
0
/*
======================
M_MoveToGoal
======================
*/
void M_MoveToGoal (edict_t *ent, float dist)
{
    edict_t		*goal;

    goal = ent->goalentity;

    if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM)))
        return;

    // if the next step hits the enemy, return immediately
    if (ent->enemy &&  SV_CloseEnough (ent, ent->enemy, dist) )
        return;

    if ( (((rand()&3)==1) && !(ent->monsterinfo.aiflags & AI_CHARGING)) || !SV_StepDirection (ent, ent->ideal_yaw, dist))
    {
        if (ent->monsterinfo.aiflags & AI_BLOCKED)
        {
            ent->monsterinfo.aiflags &= ~AI_BLOCKED;
            return;
        }
        if (ent->inuse)
            SV_NewChaseDir (ent, goal, dist);
    }
}
Example #12
0
File: ai.c Project: yquake2/zaero
/*
=============
ai_schoolWalk

The monster is walking it's beat
=============
*/
void ai_schoolWalk (edict_t *self, float dist)
{
  float speed;

  if(!(self->monsterinfo.aiflags & AI_SCHOOLING))
  {
    ai_walk(self, dist);
    return;
  }

  // init school var's for this frame
  self->zRaduisList = NULL;

  if(self->enemy || FindTarget(self))
  {
    ai_walk(self, dist);
    return;
  }
  else
  {
    // run schooling routines
    switch(zSchoolMonsters(self, dist, 1, &speed))
    {
    case 0:
		  self->monsterinfo.stand (self);
      break;

    case 2:
		  self->monsterinfo.run (self);
      break;
    }
  }

  // do the normal walk stuff
  SV_StepDirection (self, self->ideal_yaw, dist);
}
Example #13
0
void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
{
	float		deltax,deltay;
	float			d[3];
	float		tdir, olddir, turnaround;

	olddir = anglemod( (int)(actor->v.ideal_yaw/45)*45 );
	turnaround = anglemod(olddir - 180);

	deltax = enemy->v.origin[0] - actor->v.origin[0];
	deltay = enemy->v.origin[1] - actor->v.origin[1];
	if (deltax>10)
		d[1]= 0;
	else if (deltax<-10)
		d[1]= 180;
	else
		d[1]= DI_NODIR;
	if (deltay<-10)
		d[2]= 270;
	else if (deltay>10)
		d[2]= 90;
	else
		d[2]= DI_NODIR;

// try direct route
	if (d[1] != DI_NODIR && d[2] != DI_NODIR)
	{
		if (d[1] == 0)
			tdir = d[2] == 90 ? 45 : 315;
		else
			tdir = d[2] == 90 ? 135 : 215;
			
		if (tdir != turnaround && SV_StepDirection(actor, tdir, dist))
			return;
	}

// try other directions
	if ( ((rand()&3) & 1) ||  abs(deltay)>abs(deltax))
	{
		tdir=d[1];
		d[1]=d[2];
		d[2]=tdir;
	}

	if (d[1]!=DI_NODIR && d[1]!=turnaround 
	&& SV_StepDirection(actor, d[1], dist))
			return;

	if (d[2]!=DI_NODIR && d[2]!=turnaround
	&& SV_StepDirection(actor, d[2], dist))
			return;

/* there is no direct path to the player, so pick another direction */

	if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist))
			return;

	if (rand()&1) 	/*randomly determine direction of search*/
	{
		for (tdir=0 ; tdir<=315 ; tdir += 45)
			if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
					return;
	}
	else
	{
		for (tdir=315 ; tdir >=0 ; tdir -= 45)
			if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
					return;
	}

	if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
			return;

	actor->v.ideal_yaw = olddir;		// can't move

// if a bridge was pulled out from underneath a monster, it may not have
// a valid standing position at all

	if (!SV_CheckBottom (actor))
		SV_FixCheckBottom (actor);

}
Example #14
0
void SV_NewChaseDir( edict_t *actor, vec3_t destination, float dist )
{
	float	deltax, deltay;
	float	tempdir, olddir, turnaround;
	vec3_t	d;

	olddir = anglemod(((int)( actor->v.ideal_yaw / 45.0f )) * 45.0f );
	turnaround = anglemod( olddir - 180 );

	deltax = destination[0] - actor->v.origin[0];
	deltay = destination[1] - actor->v.origin[1];

	if( deltax > 10 )
		d[1] = 0.0f;
	else if( deltax < -10 )
		d[1] = 180.0f;
	else d[1] = -1;

	if( deltay < -10 )
		d[2] = 270.0f;
	else if( deltay > 10 )
		d[2] = 90.0f;
	else d[2] = -1;

	// try direct route
	if( d[1] != -1 && d[2] != -1 )
	{
		if( d[1] == 0.0f )
			tempdir = ( d[2] == 90.0f ) ? 45.0f : 315.0f;
		else tempdir = ( d[2] == 90.0f ) ? 135.0f : 215.0f;

		if( tempdir != turnaround && SV_StepDirection( actor, tempdir, dist ))
			return;
	}

	// try other directions
	if( Com_RandomLong( 0, 1 ) != 0 || fabs( deltay ) > fabs( deltax ))
	{
		tempdir = d[1];
		d[1] = d[2];
		d[2] = tempdir;
	}

	if( d[1] != -1 && d[1] != turnaround && SV_StepDirection( actor, d[1], dist ))
		return;

	if( d[2] != -1 && d[2] != turnaround && SV_StepDirection( actor, d[2], dist ))
		return;

	// there is no direct path to the player, so pick another direction
	if( olddir != -1 && SV_StepDirection( actor, olddir, dist ))
		return;

	// fine, just run somewhere.
	if( Com_RandomLong( 0, 1 ) != 1 )
	{
		for( tempdir = 0; tempdir <= 315; tempdir += 45 )
		{
			if( tempdir != turnaround && SV_StepDirection( actor, tempdir, dist ))
				return;
		}
	}
	else
	{
		for( tempdir = 315; tempdir >= 0; tempdir -= 45 )
		{
			if( tempdir != turnaround && SV_StepDirection( actor, tempdir, dist ))
				return;
		}
	}

	// we tried. run backwards. that ought to work...
	if( turnaround != -1 && SV_StepDirection( actor, turnaround, dist ))
		return;

	// well, we're stuck somehow.
	actor->v.ideal_yaw = olddir;

	// if a bridge was pulled out from underneath a monster, it may not have
	// a valid standing position at all.
	if( !SV_CheckBottom( actor, MOVE_NORMAL ))
	{
		actor->v.flags |= FL_PARTIALGROUND;
	}
}
Example #15
0
void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
{
	float	deltax,deltay;
	float	d[3];
	float	tdir, olddir, turnaround;

	//FIXME: how did we get here with no enemy
	if (!enemy)
		return;

	if(actor->flags & FL_ROBOT)
		olddir = anglemod( (int)(actor->ideal_yaw+0.5) );
	else
		olddir = anglemod( (int)(actor->ideal_yaw/45)*45 );
	turnaround = anglemod(olddir - 180);

	deltax = enemy->s.origin[0] - actor->s.origin[0];
	deltay = enemy->s.origin[1] - actor->s.origin[1];

	if(actor->flags & FL_ROBOT)
	{
		d[1] = d[2] = olddir;
	}
	else
	{
		if (deltax>10)
			d[1]= 0;
		else if (deltax<-10)
			d[1]= 180;
		else
			d[1]= DI_NODIR;
		if (deltay<-10)
			d[2]= 270;
		else if (deltay>10)
			d[2]= 90;
		else
			d[2]= DI_NODIR;
	}

// try direct route
	if (d[1] != DI_NODIR && d[2] != DI_NODIR)
	{
		if(actor->flags & FL_ROBOT)
			tdir = d[1];
		else
		{
			if (d[1] == 0)
				tdir = d[2] == 90 ? 45 : 315;
			else
				tdir = d[2] == 90 ? 135 : 215;
		}
		if (tdir != turnaround && SV_StepDirection(actor, tdir, dist))
			return;
	}

	// Robots give up if direct path doesn't work
	if(actor->flags & FL_ROBOT)
	{
		actor->ideal_yaw = olddir;		// can't move
		if (!M_CheckBottom (actor))
			SV_FixCheckBottom (actor);
	}

// try other directions
	if ( ((rand()&3) & 1) ||  abs(deltay)>abs(deltax))
	{
		tdir=d[1];
		d[1]=d[2];
		d[2]=tdir;
	}
	if (d[1]!=DI_NODIR && d[1]!=turnaround 
	&& SV_StepDirection(actor, d[1], dist))
			return;

	if (d[2]!=DI_NODIR && d[2]!=turnaround
	&& SV_StepDirection(actor, d[2], dist))
			return;

	if (actor->inuse && (actor->health > 0) && actor->monsterinfo.blocked) {
		if (actor->monsterinfo.blocked(actor, dist))
			return;
	}


/* there is no direct path to the player, so pick another direction */

	if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist))
			return;

	if (rand()&1) 	/*randomly determine direction of search*/
	{
		for (tdir=0 ; tdir<=315 ; tdir += 45)
			if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
					return;
	}
	else
	{
		for (tdir=315 ; tdir >=0 ; tdir -= 45)
			if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
					return;
	}

	if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
			return;

	actor->ideal_yaw = olddir;		// can't move

// if a bridge was pulled out from underneath a monster, it may not have
// a valid standing position at all

	if (!M_CheckBottom (actor))
		SV_FixCheckBottom (actor);
}
Example #16
0
void SV_NewChaseDir2(edict_t *actor, vec3_t destination, float dist) {

   float deltax, deltay;
   float tempdir, olddir, turnaround;
   vec3_t d;

   olddir = anglemod(((int)(actor->v.ideal_yaw / 45.0)) * 45.0); //So, we're shaving down some of the precision.  Ohkay.
   turnaround = anglemod(olddir - 180);

   deltax = destination[0] - actor->v.origin[0];
   deltay = destination[1] - actor->v.origin[1];

   if(deltax > 10) { d[1]= 0; }
   else if(deltax < -10) { d[1]= 180; }
   else { d[1] = -1; } //DI_NODIR, so in this function, -1 is a reserved 'null' like value.

   if(deltay < -10) { d[2] = 270; }
   else if(deltay > 10) { d[2] = 90; }
   else { d[2] = -1; }

   // try direct route
   if(d[1] != -1 && d[2] != -1) {

      if(d[1] == 0) {
         if(d[2] == 90) { tempdir = 45; }
         else { tempdir = 315; }
      }
      else {
         if(d[2] == 90) { tempdir = 135; }
         else { tempdir = 215; }
      }

      if(tempdir != turnaround && SV_StepDirection(actor, tempdir, dist) != 0) {
         return;
      }
   }

   // try other directions
   if(RandomLong(0, 1) != 0 || fabs(deltay) > fabs(deltax)) { //These were originally cast as int before compared.  I cannot think of any compelling reason to do so.

      tempdir = d[1];
      d[1] = d[2];
      d[2] = tempdir;
   }

   if(d[1] != -1 && d[1] != turnaround && SV_StepDirection(actor, d[1], dist) != 0) {
      return;
   }
   if(d[2] != -1 && d[2] != turnaround && SV_StepDirection(actor, d[2], dist) != 0) {
      return;
   }

   /* there is no direct path to the player, so pick another direction */
   if(olddir != -1 && SV_StepDirection(actor, olddir, dist) != 0) {
      return;
   }

   //Fine, just run somewhere.
   if(RandomLong(0, 1) != 0) {
      for(tempdir = 0; tempdir <= 315; tempdir += 45) {
         if(tempdir != turnaround && SV_StepDirection(actor, tempdir, dist) != 0) {
            return;
         }
      }
   }
   else {
      for(tempdir = 315; tempdir >= 0; tempdir -= 45) {
         if(tempdir != turnaround && SV_StepDirection(actor, tempdir, dist) != 0) {
            return;
         }
      }
   }

   //We tried.  Run backwards.  THAT ought to work...
   if(turnaround != -1 && SV_StepDirection(actor, turnaround, dist) != 0) {
      return;
   }

   //Well, we're stuck somehow.
   actor->v.ideal_yaw = olddir;

   // if a bridge was pulled out from underneath a monster, it may not have
   // a valid standing position at all.

   if(SV_CheckBottom(actor) == 0) {
      SV_FixCheckBottom(actor);
   }
}
Example #17
0
/*
======================
M_MoveToGoal
======================
*/
void M_MoveToGoal (edict_t *ent, float dist)
{
	edict_t		*goal;
	
	goal = ent->goalentity;

	if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM)))
		return;

	// Lazarus range checks
	if (!(ent->monsterinfo.aiflags & (AI_CHASE_THING | AI_CHICKEN)))
	{
		if (ent->enemy && (ent->monsterinfo.min_range > 0) && ((goal==ent->enemy) || !goal) ) {
			float dist;
			dist = realrange(ent,ent->enemy);
			if(dist < ent->monsterinfo.min_range)
			{
				ent->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_RANGE_PAUSE);
				ent->monsterinfo.rangetime = level.time + 0.5;
				ent->monsterinfo.stand(ent);
				return;
			}
		}
		if ((ent->enemy) && (level.time > ent->monsterinfo.rangetime + 0.5) && ((goal==ent->enemy) || !goal) )
		{
			float dist;
			dist = realrange(ent,ent->enemy);
			if((dist < ent->monsterinfo.ideal_range[0]) && (rand() & 3))
			{
				ent->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_RANGE_PAUSE);
				ent->monsterinfo.rangetime = level.time + 1.0;
				ent->monsterinfo.stand(ent);
				return;
			}
			if((dist < ent->monsterinfo.ideal_range[1]) && (dist > ent->monsterinfo.ideal_range[0]) && (rand() & 1))
			{
				ent->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_RANGE_PAUSE);
				ent->monsterinfo.rangetime = level.time + 0.2;
				ent->monsterinfo.stand(ent);
				return;
			}
		}
	}

	if( (ent->monsterinfo.aiflags & AI_FOLLOW_LEADER) &&
		(ent->movetarget) &&
		(ent->movetarget->inuse) &&
		(ent->movetarget->health > 0) ) {

		if(ent->enemy)
			ent->monsterinfo.currentmove = &actor_move_run;
		else
		{
			float	R;

			R = realrange(ent,ent->movetarget);
			if(R > ACTOR_FOLLOW_RUN_RANGE)
				ent->monsterinfo.currentmove = &actor_move_run;
			else if(R < ACTOR_FOLLOW_STAND_RANGE && ent->movetarget->client) {
				ent->monsterinfo.pausetime = level.time + 0.5;
				ent->monsterinfo.currentmove = &actor_move_stand;
				return;
			}
			else
				ent->monsterinfo.currentmove = &actor_move_walk;
		}
	}

//	If the next step hits the enemy, return immediately. Don't do this for
//	AI_CHASE_THING, since we want monster to actually touch or pass through
//	"thing"
	if (ent->enemy && !(ent->monsterinfo.aiflags & AI_CHASE_THING) && SV_CloseEnough (ent, ent->enemy, dist) )
		return;

// bump around...
	if ( (rand()&3)==1 || !SV_StepDirection (ent, ent->ideal_yaw, dist))
	{
		if (ent->inuse)
			SV_NewChaseDir (ent, goal, dist);
	}
}
Example #18
0
/*
======================
M_MoveToGoal
======================
*/
void M_MoveToGoal (edict_t *ent, float dist)
{
	edict_t		*goal;

	goal = ent->goalentity;

	if (ent->holdtime > level.time) // stay in-place for medic healing
		return;

	if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM)) && !ent->waterlevel)
	{
		//gi.dprintf("not touching ground\n");
		return;
	}

// if the next step hits the enemy, return immediately
	if (ent->enemy && (ent->enemy->solid == SOLID_BBOX) 
		&& SV_CloseEnough (ent, ent->enemy, dist) )
//GHz START
	{
		vec3_t v;

		// we need to keep turning to avoid getting stuck doing nothing
		if (ent->goalentity && ent->goalentity->inuse) // 3.89 make sure the monster still has a goal!
		{
			VectorSubtract(ent->goalentity->s.origin, ent->s.origin, v);
			VectorNormalize(v);
			ent->ideal_yaw = vectoyaw(v);
			M_ChangeYaw(ent);
		}
		return;
	}
//GHz END

	// dont move so fast in the water
	if (!(ent->flags & (FL_FLY|FL_SWIM)) && (ent->waterlevel > 1))
		dist *= 0.5;

// bump around...
	// if we can't take a step, try moving in another direction
	if (!SV_StepDirection (ent, ent->ideal_yaw, dist, true))
	{
		//gi.dprintf("couldnt step\n");
		// if the monster hasn't moved much, then increment
		// the number of frames it has been stuck
		if (distance(ent->s.origin, ent->monsterinfo.stuck_org) < 64)
			ent->monsterinfo.stuck_frames++;
		else
			ent->monsterinfo.stuck_frames = 0;

		// record current position for comparison
		VectorCopy(ent->s.origin, ent->monsterinfo.stuck_org);

		// attempt a course-correction
		if (ent->inuse && (level.time > ent->monsterinfo.bump_delay))
		{
			//gi.dprintf("tried course correction %s\n", ent->goalentity?"true":"false");
			SV_NewChaseDir (ent, goal, dist);
			ent->monsterinfo.bump_delay = level.time + FRAMETIME*GetRandom(2, 5);
			return;
		}
	}
}