コード例 #1
0
ファイル: g_monsterai.cpp プロジェクト: Picmip/qfusion
void FoundTarget (edict_t *self)
{
	// let other monsters see this monster for a while
	if (self->enemy->r.client)
	{
		level.sight_entity = self;
		level.sight_entity_framenum = level.framenum;
	}

	self->show_hostile = level.time + 1000;		// wake up other monsters

	VectorCopy(self->enemy->s.origin, self->monsterinfo.last_sighting);
	self->monsterinfo.trail_time = level.time;

	if (!self->combattarget)
	{
		HuntTarget (self);
		return;
	}

	self->goalentity = self->movetarget = G_PickTarget(self->combattarget);
	if (!self->movetarget)
	{
		self->goalentity = self->movetarget = self->enemy;
		HuntTarget (self);
		G_Printf ("%s at %s, combattarget %s not found\n", self->classname, vtos(self->s.origin), self->combattarget);
		return;
	}

	// clear out our combattarget, these are a one shot deal
	self->combattarget = NULL;
	self->monsterinfo.aiflags |= AI_COMBAT_POINT;

	// clear the targetname, that point is ours!
	self->movetarget->targetname = NULL;
	self->monsterinfo.pausetime = 0;

	// run for it
	self->monsterinfo.run (self);
}
コード例 #2
0
ファイル: sp_ai.c プロジェクト: JosephPecoraro/ktx
void FoundTarget()
{
	if ( PROG_TO_EDICT( self->s.v.enemy )->ct == ctPlayer )
	{	// let other monsters see this monster for a while
		sight_entity = self;
		sight_entity_time = g_globalvars.time;
	}

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

	SightSound ();
	HuntTarget ();
}
コード例 #3
0
/*
=====================
hintpath_stop

Makes a monster stop following hint_paths.
=====================
*/
void hintpath_stop (edict_t *monster)
{
	monster->movetarget = monster->goalentity = NULL;
	monster->monsterinfo.last_hint_time = level.time;
	monster->monsterinfo.goal_hint = NULL;
	monster->monsterinfo.aiflags &= ~AI_HINT_PATH;

	// If we don't have an enemy to get mad at, just stand around like an unactivated monster.
	if (!has_valid_enemy(monster))
	{
		monster->enemy = NULL;
		monster->monsterinfo.pausetime = level.time + 100000000;
		monster->monsterinfo.stand (monster);
	}
	else if (visible(monster, monster->enemy)) 	// attack if we can see our foe
		FoundTarget (monster);
	else // keep pursuing
		HuntTarget (monster);
}
コード例 #4
0
ファイル: m_medic.c プロジェクト: qbism/qbq2
void medic_StopPatrolling (edict_t *self)
{
	self->goalentity = NULL;
	self->movetarget = NULL;
	self->monsterinfo.aiflags &= ~AI_MEDIC_PATROL;
	if (!(self->monsterinfo.aiflags & AI_MEDIC))
	{
		if(medic_FindDeadMonster(self))
			return;
	}
	if (has_valid_enemy(self))
	{
		if (visible(self, self->enemy))
		{
			FoundTarget (self);
			return;
		}
		HuntTarget (self);
		return;
	}
	if(self->monsterinfo.aiflags & AI_MEDIC)
		abortHeal(self,false);
}
コード例 #5
0
ファイル: g_thing.c プロジェクト: Nephatrine/nephq2-game
void thing_think (edict_t *self)
{
	vec3_t	vec;
	vec_t	dist;
	edict_t	*monster;

	monster = self->target_ent;
	if(level.time <= self->touch_debounce_time)
	{
		if(monster && monster->inuse)
		{
			if(monster->movetarget == self)
			{
				if(monster->health > 0)
				{
					VectorSubtract(monster->s.origin,self->s.origin,vec);
					vec[2] = 0;
					dist = VectorLength(vec);
					if(dist >= monster->size[0])
					{
						self->nextthink = level.time + FRAMETIME;
						return;
					}
				}
			}
		}
	}
	if(!monster || !monster->inuse || (monster->health <= 0))
	{
		G_FreeEdict(self);
		return;
	}
	if(monster->goalentity == self)
		monster->goalentity = NULL;
	if(monster->movetarget == self)
		monster->movetarget = NULL;
	if(monster->monsterinfo.aiflags & AI_FOLLOW_LEADER)
	{
		monster->monsterinfo.leader = NULL;
		if(monster->monsterinfo.old_leader && monster->monsterinfo.old_leader->inuse)
		{
			monster->monsterinfo.pausetime = level.time + 2;
			monster->monsterinfo.stand(monster);
			VectorCopy(monster->monsterinfo.old_leader->s.origin,self->move_origin);
			self->nextthink = level.time + 2;
			self->think     = thing_restore_leader;
			gi.linkentity(monster);
			return;
		}
		else
		{
			monster->monsterinfo.aiflags &= ~AI_FOLLOW_LEADER;
		}
	}
	if(monster->monsterinfo.aiflags & AI_CHICKEN)
	{
		monster->monsterinfo.stand(monster);
		monster->monsterinfo.aiflags |= AI_STAND_GROUND;
		monster->monsterinfo.pausetime = level.time + 100000;
	}
	monster->vehicle = NULL;
	monster->monsterinfo.aiflags &= ~(AI_CHASE_THING | AI_SEEK_COVER | AI_EVADE_GRENADE);

	G_FreeEdict(self);
	if (has_valid_enemy(monster))
	{
		monster->monsterinfo.pausetime = 0;
		monster->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND);
		monster->goalentity = monster->enemy;
		if (visible(monster, monster->enemy))
		{
			FoundTarget (monster);
			return;
		}
		HuntTarget (monster);
		return;
	}
	monster->enemy = NULL;
	monster->monsterinfo.pausetime = level.time + 100000000;
	monster->monsterinfo.stand (monster);
}
コード例 #6
0
ファイル: g_thing.c プロジェクト: Nephatrine/nephq2-game
void thing_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{
	if(self->target_ent != other)
		return;
	if(other->health <= 0)
	{
		G_FreeEdict(self);
		return;
	}
	self->touch = NULL;
	if( self->target_ent->monsterinfo.aiflags & AI_SEEK_COVER )
	{
		edict_t	*monster;
		// For monster/actor seeking cover after firing, 
		// pause a random bit before resuming attack
		self->touch_debounce_time = level.time + random()*6.;
		monster = self->target_ent;
		monster->monsterinfo.stand(monster);
		monster->monsterinfo.pausetime = self->touch_debounce_time;
		self->think = thing_think_pause;
		self->think(self);
		return;
	}
	if( self->target_ent->monsterinfo.aiflags & AI_EVADE_GRENADE )
	{
		edict_t	*grenade = other->next_grenade;

		if(other->goalentity == self)
			other->goalentity = NULL;
		if(other->movetarget == self)
			other->movetarget = NULL;
		other->vehicle = NULL;
		if(grenade)
		{
			// make sure this is still a grenade
			if(grenade->inuse)
			{
				if(Q_strcasecmp(grenade->classname,"grenade") && Q_strcasecmp(grenade->classname,"hgrenade"))
					other->next_grenade = grenade = NULL;
			}
			else
				other->next_grenade = grenade = NULL;
		}
		if(grenade)
		{
			if(self->touch_debounce_time > level.time)
			{
				other->monsterinfo.pausetime = self->touch_debounce_time + 0.1;
				other->monsterinfo.aiflags |= AI_STAND_GROUND;
				other->monsterinfo.stand(other);
			}
			else
				other->monsterinfo.pausetime = 0;

			other->enemy = grenade->owner;
			if (has_valid_enemy(other))
			{
				other->goalentity = other->enemy;
				if (visible(other, other->enemy))
					FoundTarget (other);
				else
					HuntTarget (other);
			}
			else
			{
				other->enemy = NULL;
				other->monsterinfo.stand (other);
			}
			if(other->monsterinfo.pausetime > 0)
			{
				self->think = thing_grenade_boom;
				self->nextthink = other->monsterinfo.pausetime;
				return;
			}
			other->monsterinfo.aiflags &= ~(AI_CHASE_THING | AI_EVADE_GRENADE);
		}
		else if (has_valid_enemy(other))
		{
			other->monsterinfo.aiflags &= ~(AI_CHASE_THING | AI_EVADE_GRENADE);
			other->goalentity = other->enemy;
			if (visible(other, other->enemy))
				FoundTarget (other);
			else
				HuntTarget (other);
		}
		else
		{
			other->enemy = NULL;
			other->monsterinfo.pausetime = level.time + 100000000;
			other->monsterinfo.aiflags &= ~(AI_CHASE_THING | AI_EVADE_GRENADE);
			other->monsterinfo.stand (other);
		}
		G_FreeEdict(self);
		return;
	}
	self->touch_debounce_time = 0;
	thing_think(self);
}
コード例 #7
0
ファイル: m_medic.c プロジェクト: qbism/qbq2
qboolean medic_checkattack (edict_t *self)
{
	if (!(self->monsterinfo.aiflags & AI_MEDIC))
	{
		if( medic_FindDeadMonster(self) )
			return false;
	}

	if (self->monsterinfo.aiflags & AI_MEDIC)
	{
		float	r;
		vec3_t	forward, right, offset, start;
		trace_t	tr;

		// if we have 5 seconds or less before a timeout,
		// look for a hint_path to the target
		if ( (self->timestamp < level.time + 5) &&
			 (self->monsterinfo.last_hint_time + 5 < level.time) )
		{
			// check for hint_paths.
			self->monsterinfo.last_hint_time = level.time;
			if (hintcheck_monsterlost(self))
			{
				if(developer->value)
					gi.dprintf("medic at %s using hint_paths to find %s\n",
					vtos(self->s.origin), self->enemy->classname);
				self->timestamp = level.time + MEDIC_TRY_TIME;
				return false;
			}
		}

		// if we ran out of time, give up
		if (self->timestamp < level.time)
		{
			//if(developer->value)
			//	gi.dprintf("medic at %s timed out, abort heal\n",vtos(self->s.origin));
			abortHeal (self, true);
			self->timestamp = 0;
			return false;
		}
		
		// if our target went away
		if ((!self->enemy) || (!self->enemy->inuse)) {
			abortHeal (self,false);
			return false;
		}
		// if target is embedded in a solid
		if (embedded(self->enemy))
		{
			abortHeal (self,false);
			return false;
		}
		r = realrange(self,self->enemy);
		if (r > MEDIC_MAX_HEAL_DISTANCE+10) {
			self->monsterinfo.attack_state = AS_STRAIGHT;
			//abortHeal(self,false);
			return false;
		} else if(r < MEDIC_MIN_DISTANCE) {
			abortHeal(self,false);
			return false;
		}
		// Lazarus 1.6.2.3: if point-to-point vector from cable to
		// target is blocked by a solid
		AngleVectors (self->s.angles, forward, right, NULL);
		// Offset [8] has the largest displacement to the left... not a sure
		// thing but this one should be the most severe test.
		VectorCopy (medic_cable_offsets[8], offset);
		G_ProjectSource (self->s.origin, offset, forward, right, start);
		tr = gi.trace(start,NULL,NULL,self->enemy->s.origin,self,MASK_SHOT|MASK_WATER);
		if (tr.fraction < 1.0 && tr.ent != self->enemy)
			return false;
		medic_attack(self);
		return true;
	}

	// Lazarus: NEVER attack other monsters
	if ((self->enemy) && (self->enemy->svflags & SVF_MONSTER))
	{
		self->enemy = self->oldenemy;
		self->oldenemy = NULL;
		if(self->enemy && self->enemy->inuse)
		{
			if(visible(self,self->enemy))
				FoundTarget(self);
			else
				HuntTarget(self);
		}
		return false;
	}

	return M_CheckAttack (self);
}
コード例 #8
0
ファイル: sp_ai.c プロジェクト: JosephPecoraro/ktx
/*
=============
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...
}
コード例 #9
0
ファイル: g_monsterai.cpp プロジェクト: Picmip/qfusion
/*
=============
ai_checkattack

Decides if we're going to attack or do something else
used by ai_run and ai_stand
=============
*/
bool ai_checkattack (edict_t *self, float dist)
{
	vec3_t		temp;
	bool	hesDeadJim;

// this causes monsters to run blindly to the combat point w/o firing
	if (self->goalentity)
	{
		if (self->monsterinfo.aiflags & AI_COMBAT_POINT)
			return false;

		if (self->monsterinfo.aiflags & AI_SOUND_TARGET)
		{
			if (level.time - self->enemy->teleport_time > 5000)
			{
				if (self->goalentity == self->enemy) {
					if (self->movetarget)
						self->goalentity = self->movetarget;
					else
						self->goalentity = NULL;
				}
				self->monsterinfo.aiflags &= ~AI_SOUND_TARGET;
				if (self->monsterinfo.aiflags & AI_TEMP_STAND_GROUND)
					self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND);
			}
			else
			{
				self->show_hostile = level.time + 1000;
				return false;
			}
		}
	}

	enemy_vis = false;

// see if the enemy is dead
	hesDeadJim = false;
	if ((!self->enemy) || (!self->enemy->r.inuse))
	{
		hesDeadJim = true;
	}
	else if (self->monsterinfo.aiflags & AI_MEDIC)
	{
		if (self->enemy->health > 0)
		{
			hesDeadJim = true;
			self->monsterinfo.aiflags &= ~AI_MEDIC;
		}
	}
	else
	{
		if (self->monsterinfo.aiflags & AI_BRUTAL)
		{
			if (self->enemy->health <= -80)
				hesDeadJim = true;
		}
		else
		{
			if (self->enemy->health <= 0)
				hesDeadJim = true;
		}
	}

	if (hesDeadJim)
	{
		self->enemy = NULL;
	// FIXME: look all around for other targets
		if (self->oldenemy && self->oldenemy->health > 0)
		{
			self->enemy = self->oldenemy;
			self->oldenemy = NULL;
			HuntTarget (self);
		}
		else
		{
			if (self->movetarget)
			{
				self->goalentity = self->movetarget;
				self->monsterinfo.walk (self);
			}
			else
			{
				// we need the pausetime otherwise the stand code
				// will just revert to walking with no target and
				// the monsters will wonder around aimlessly trying
				// to hunt the world entity
				self->monsterinfo.pausetime = level.time + 100000000;
				self->monsterinfo.stand (self);
			}
			return true;
		}
	}

	self->show_hostile = level.time + 1000;		// wake up other monsters

// check knowledge of enemy
	enemy_vis = G_Visible(self, self->enemy);
	if (enemy_vis)
	{
		self->monsterinfo.search_time = level.time + 5000;
		VectorCopy (self->enemy->s.origin, self->monsterinfo.last_sighting);
	}

// look for other coop players here
//	if (coop && self->monsterinfo.search_time < level.time)
//	{
//		if (FindTarget (self))
//			return true;
//	}

	enemy_infront = G_InFront(self, self->enemy);
	enemy_range = range(self, self->enemy);
	VectorSubtract (self->enemy->s.origin, self->s.origin, temp);
	enemy_yaw = vectoyaw(temp);


	// JDC self->ideal_yaw = enemy_yaw;

	if (self->monsterinfo.attack_state == AS_MISSILE)
	{
		ai_run_missile (self);
		return true;
	}
	if (self->monsterinfo.attack_state == AS_MELEE)
	{
		ai_run_melee (self);
		return true;
	}

	// if enemy is not currently visible, we will never attack
	if (!enemy_vis)
		return false;

	return self->monsterinfo.checkattack (self);
}