示例#1
0
/*
=============
ai_run

The monster has an enemy it is trying to kill
=============
*/
void ai_run( float dist )
{
	vec3_t tmpv;

	if ( k_bloodfest )
	{
		if ( (int)self->s.v.flags & FL_SWIM )
		{
			dist *= 5; // let fish swim faster in bloodfest mode.
		}
		else if ( self->bloodfest_boss )
		{
			dist *= 2; // let boss move faster
		}
	}

	movedist = dist;

	// see if the enemy is dead
	if ( ISDEAD( PROG_TO_EDICT( self->s.v.enemy ) ) || ( (int)PROG_TO_EDICT( self->s.v.enemy )->s.v.flags & FL_NOTARGET ) )
	{
		self->s.v.enemy = EDICT_TO_PROG( world );

		// FIXME: look all around for other targets
		if ( self->oldenemy && ISLIVE( self->oldenemy ) && !( (int)self->oldenemy->s.v.flags & FL_NOTARGET ) )
		{
			self->s.v.enemy = EDICT_TO_PROG( self->oldenemy );
			HuntTarget ();
		}
		else
		{
			if ( !self->movetarget || self->movetarget == world )
			{
				if ( self->th_stand )
					self->th_stand();
			}
			else
			{
				if ( self->th_walk )
					self->th_walk();
			}

			return;
		}
	}

	self->show_hostile = g_globalvars.time + 1;		// wake up other monsters

// check knowledge of enemy
	enemy_vis = visible( PROG_TO_EDICT( self->s.v.enemy ) );
	if ( enemy_vis )
		self->search_time = g_globalvars.time + 5; // does not search for enemy next 5 seconds

// look for other coop players
	if ( coop && self->search_time < g_globalvars.time )
	{
		if ( FindTarget() )
		{
			// this is fix for too frequent enemy sighting, required for bloodfest mode.
			if ( !visible( PROG_TO_EDICT( self->s.v.enemy ) ) )
			{
				self->search_time = g_globalvars.time + 5; // does not search for enemy next 5 seconds
			}
			return;
		}
	}

	enemy_infront = infront( PROG_TO_EDICT( self->s.v.enemy ) );
	enemy_range   = range( PROG_TO_EDICT( self->s.v.enemy ) );
	VectorSubtract( PROG_TO_EDICT( self->s.v.enemy )->s.v.origin, self->s.v.origin, tmpv);
	enemy_yaw     = vectoyaw( tmpv );

	if ( self->attack_state == AS_MISSILE )
	{
		//dprint ("ai_run_missile\n");
		ai_run_missile();
		return;
	}

	if ( self->attack_state == AS_MELEE )
	{
		//dprint ("ai_run_melee\n");
		ai_run_melee();
		return;
	}

	if ( CheckAnyAttack() )
		return;					// beginning an attack

	if ( self->attack_state == AS_SLIDING )
	{
		ai_run_slide();
		return;
	}

	// head straight in
	movetogoal( dist );		// done in C code...
}
示例#2
0
/*
=============
ai_run

The monster has an enemy it is trying to kill
=============
*/
void ai_run (edict_t *self, float dist)
{
	vec3_t		v;
	edict_t		*tempgoal;
	edict_t		*save;
	bool	newcourse;
	edict_t		*marker;
	float		d1, d2;
	trace_t		tr;
	vec3_t		v_forward, v_right;
	float		left, center, right;
	vec3_t		left_target, right_target;

	// if we're going to a combat point, just proceed
	if (self->monsterinfo.aiflags & AI_COMBAT_POINT)
	{
		M_MoveToGoal (self, dist);
		return;
	}

	if (self->monsterinfo.aiflags & AI_SOUND_TARGET)
	{
		VectorSubtract (self->s.origin, self->enemy->s.origin, v);
		if (VectorLength(v) < 64)
		{
			self->monsterinfo.aiflags |= (AI_STAND_GROUND | AI_TEMP_STAND_GROUND);
			self->monsterinfo.stand (self);
			return;
		}

		M_MoveToGoal (self, dist);

		if (!FindTarget (self))
			return;
	}

	if (ai_checkattack (self, dist))
		return;

	if (self->monsterinfo.attack_state == AS_SLIDING)
	{
		ai_run_slide (self, dist);
		return;
	}

	if (enemy_vis)
	{
		M_MoveToGoal (self, dist);
		self->monsterinfo.aiflags &= ~AI_LOST_SIGHT;
		VectorCopy (self->enemy->s.origin, self->monsterinfo.last_sighting);
		self->monsterinfo.trail_time = level.time;
		return;
	}

#ifdef AI_FIXME
	// coop will change to another enemy if visible
	if (coop->integer)
	{	// FIXME: insane guys get mad with this, which causes crashes!
		if (FindTarget (self))
			return;
	}
#endif

	if ((self->monsterinfo.search_time) && (level.time > (self->monsterinfo.search_time + 20000)))
	{
		M_MoveToGoal (self, dist);
		self->monsterinfo.search_time = 0;
		return;
	}

	save = self->goalentity;
	tempgoal = G_Spawn();
	self->goalentity = tempgoal;

	newcourse = false;

	if (!(self->monsterinfo.aiflags & AI_LOST_SIGHT))
	{
		// just lost sight of the player, decide where to go first
		self->monsterinfo.aiflags |= (AI_LOST_SIGHT | AI_PURSUIT_LAST_SEEN);
		self->monsterinfo.aiflags &= ~(AI_PURSUE_NEXT | AI_PURSUE_TEMP);
		newcourse = true;
	}

	if (self->monsterinfo.aiflags & AI_PURSUE_NEXT)
	{
		self->monsterinfo.aiflags &= ~AI_PURSUE_NEXT;

		// give ourself more time since we got this far
		self->monsterinfo.search_time = level.time + 5000;

		if (self->monsterinfo.aiflags & AI_PURSUE_TEMP)
		{
			self->monsterinfo.aiflags &= ~AI_PURSUE_TEMP;
			marker = NULL;
			VectorCopy (self->monsterinfo.saved_goal, self->monsterinfo.last_sighting);
			newcourse = true;
		}
		else if (self->monsterinfo.aiflags & AI_PURSUIT_LAST_SEEN)
		{
			self->monsterinfo.aiflags &= ~AI_PURSUIT_LAST_SEEN;
			marker = G_PlayerTrail_PickFirst (self);
		}
		else
		{
			marker = G_PlayerTrail_PickNext (self);
		}

		if (marker)
		{
			VectorCopy (marker->s.origin, self->monsterinfo.last_sighting);
			self->monsterinfo.trail_time = marker->timeStamp;
			self->s.angles[YAW] = self->ideal_yaw = marker->s.angles[YAW];
			newcourse = true;
		}
	}

	VectorSubtract (self->s.origin, self->monsterinfo.last_sighting, v);
	d1 = VectorLength(v);
	if (d1 <= dist)
	{
		self->monsterinfo.aiflags |= AI_PURSUE_NEXT;
		dist = d1;
	}

	VectorCopy (self->monsterinfo.last_sighting, self->goalentity->s.origin);

	if (newcourse)
	{
		G_Trace (&tr, self->s.origin, self->r.mins, self->r.maxs, self->monsterinfo.last_sighting, self, MASK_PLAYERSOLID);
		if (tr.fraction < 1)
		{
			VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
			d1 = VectorLength(v);
			center = tr.fraction;
			d2 = d1 * ((center+1)/2);
			self->s.angles[YAW] = self->ideal_yaw = vectoyaw(v);
			AngleVectors(self->s.angles, v_forward, v_right, NULL);

			VectorSet(v, d2, -16, 0);
			G_ProjectSource (self->s.origin, v, v_forward, v_right, left_target);
			G_Trace (&tr, self->s.origin, self->r.mins, self->r.maxs, left_target, self, MASK_PLAYERSOLID);
			left = tr.fraction;

			VectorSet(v, d2, 16, 0);
			G_ProjectSource (self->s.origin, v, v_forward, v_right, right_target);
			G_Trace (&tr, self->s.origin, self->r.mins, self->r.maxs, right_target, self, MASK_PLAYERSOLID);
			right = tr.fraction;

			center = (d1*center)/d2;
			if (left >= center && left > right)
			{
				if (left < 1)
				{
					VectorSet(v, d2 * left * 0.5, -16, 0);
					G_ProjectSource (self->s.origin, v, v_forward, v_right, left_target);
				}
				VectorCopy (self->monsterinfo.last_sighting, self->monsterinfo.saved_goal);
				self->monsterinfo.aiflags |= AI_PURSUE_TEMP;
				VectorCopy (left_target, self->goalentity->s.origin);
				VectorCopy (left_target, self->monsterinfo.last_sighting);
				VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
				self->s.angles[YAW] = self->ideal_yaw = vectoyaw(v);
			}
			else if (right >= center && right > left)
			{
				if (right < 1)
				{
					VectorSet(v, d2 * right * 0.5, 16, 0);
					G_ProjectSource (self->s.origin, v, v_forward, v_right, right_target);
				}
				VectorCopy (self->monsterinfo.last_sighting, self->monsterinfo.saved_goal);
				self->monsterinfo.aiflags |= AI_PURSUE_TEMP;
				VectorCopy (right_target, self->goalentity->s.origin);
				VectorCopy (right_target, self->monsterinfo.last_sighting);
				VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
				self->s.angles[YAW] = self->ideal_yaw = vectoyaw(v);
			}
		}
	}

	M_MoveToGoal (self, dist);

	G_FreeEdict(tempgoal);

	if (self)
		self->goalentity = save;
}