Exemple #1
0
float target_angle (edict_t *self)
{
	vec3_t target;
	float enemy_yaw;

	VectorSubtract (self->s.origin, self->enemy->s.origin, target);
	enemy_yaw = self->s.angles[YAW] - vectoyaw2(target);
	if (enemy_yaw < 0)
		enemy_yaw += 360.0;

	// this gets me 0 degrees = forward
	enemy_yaw -= 180.0;
	// positive is to right, negative to left

	return enemy_yaw;
}
Exemple #2
0
void
carrier_start_spawn(edict_t *self)
{
	int mytime;
	float enemy_yaw;
	vec3_t temp;

	if (!self)
	{
		return;
	}

	CarrierCoopCheck(self);

	if (!orig_yaw_speed)
	{
		orig_yaw_speed = self->yaw_speed;
	}

	if (!self->enemy)
	{
		return;
	}

	mytime = (int)((level.time - self->timestamp) / 0.5);

	VectorSubtract(self->enemy->s.origin, self->s.origin, temp);
	enemy_yaw = vectoyaw2(temp);

	/* note that the offsets are based on a forward of 105 from the end angle */
	if (mytime == 0)
	{
		self->ideal_yaw = anglemod(enemy_yaw - 30);
	}
	else if (mytime == 1)
	{
		self->ideal_yaw = anglemod(enemy_yaw);
	}
	else if (mytime == 2)
	{
		self->ideal_yaw = anglemod(enemy_yaw + 30);
	}

	CarrierMachineGun(self);
}
Exemple #3
0
float
target_angle(edict_t *self)
{
	vec3_t target;
	float enemy_yaw;

	if (!self)
	{
		return 0.0;
	}

	VectorSubtract(self->s.origin, self->enemy->s.origin, target);
	enemy_yaw = self->s.angles[YAW] - vectoyaw2(target);

	if (enemy_yaw < 0)
	{
		enemy_yaw += 360.0;
	}

	enemy_yaw -= 180.0;

	return enemy_yaw;
}
Exemple #4
0
qboolean
Carrier_CheckAttack(edict_t *self)
{
	vec3_t spot1, spot2;
	vec3_t temp;
	float chance = 0;
	trace_t tr;
	qboolean enemy_infront, enemy_inback, enemy_below;
	int enemy_range;
	float enemy_yaw;

	if (!self)
	{
		return false;
	}

	if (self->enemy->health > 0)
	{
		/* see if any entities are in the way of the shot */
		VectorCopy(self->s.origin, spot1);
		spot1[2] += self->viewheight;
		VectorCopy(self->enemy->s.origin, spot2);
		spot2[2] += self->enemy->viewheight;

		tr = gi.trace(spot1, NULL, NULL, spot2, self,
				CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME |
				CONTENTS_LAVA);

		/* do we have a clear shot? */
		if (tr.ent != self->enemy)
		{
			/* go ahead and spawn stuff if we're mad a a client */
			if (self->enemy->client && (self->monsterinfo.monster_slots > 2))
			{
				self->monsterinfo.attack_state = AS_BLIND;
				return true;
			}

			/* we want them to go ahead and shoot at info_notnulls if they can. */
			if ((self->enemy->solid != SOLID_NOT) || (tr.fraction < 1.0))
			{
				return false;
			}
		}
	}

	enemy_infront = infront(self, self->enemy);
	enemy_inback = inback(self, self->enemy);
	enemy_below = below(self, self->enemy);

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

	self->ideal_yaw = enemy_yaw;

	/* shoot out the back if appropriate */
	if ((enemy_inback) || (!enemy_infront && enemy_below))
	{
		/* this is using wait because the attack is supposed to be independent */
		if (level.time >= self->wait)
		{
			self->wait = level.time + CARRIER_ROCKET_TIME;
			self->monsterinfo.attack(self);

			if (random() < 0.6)
			{
				self->monsterinfo.attack_state = AS_SLIDING;
			}
			else
			{
				self->monsterinfo.attack_state = AS_STRAIGHT;
			}

			return true;
		}
	}

	/* melee attack */
	if (enemy_range == RANGE_MELEE)
	{
		self->monsterinfo.attack_state = AS_MISSILE;
		return true;
	}

	if (self->monsterinfo.aiflags & AI_STAND_GROUND)
	{
		chance = 0.4;
	}
	else if (enemy_range == RANGE_MELEE)
	{
		chance = 0.8;
	}
	else if (enemy_range == RANGE_NEAR)
	{
		chance = 0.8;
	}
	else if (enemy_range == RANGE_MID)
	{
		chance = 0.8;
	}
	else if (enemy_range == RANGE_FAR)
	{
		chance = 0.5;
	}

	/* go ahead and shoot every time if it's a info_notnull */
	if ((random() < chance) || (self->enemy->solid == SOLID_NOT))
	{
		self->monsterinfo.attack_state = AS_MISSILE;
		return true;
	}

	if (self->flags & FL_FLY)
	{
		if (random() < 0.6)
		{
			self->monsterinfo.attack_state = AS_SLIDING;
		}
		else
		{
			self->monsterinfo.attack_state = AS_STRAIGHT;
		}
	}

	return false;
}
Exemple #5
0
qboolean Widow_CheckAttack (edict_t *self)
{
	vec3_t	spot1, spot2;
	vec3_t	temp;
	float	chance = 0;
	trace_t	tr;
	int			enemy_range;
	float		enemy_yaw;
	float		real_enemy_range;

	if (!self->enemy)
		return false;

	WidowPowerups(self);

	if (self->monsterinfo.currentmove == &widow_move_run)
	{
		// if we're in run, make sure we're in a good frame for attacking before doing anything else
		// frames 1,2,3,9,10,11,13 good to fire
		switch (self->s.frame)
		{
			case FRAME_walk04:
			case FRAME_walk05:
			case FRAME_walk06:
			case FRAME_walk07:
			case FRAME_walk08:
			case FRAME_walk12:
				{
					return false;
				}
			default:
				break;
		}
	}

	// give a LARGE bias to spawning things when we have room
	// use AI_BLOCKED as a signal to attack to spawn
	if ((random() < 0.8) && (SELF_SLOTS_LEFT >= 2) && (realrange(self, self->enemy) > 150))
	{
		self->monsterinfo.aiflags |= AI_BLOCKED;
		self->monsterinfo.attack_state = AS_MISSILE;
		return true;
	}

	if (self->enemy->health > 0)
	{
		// see if any entities are in the way of the shot
		VectorCopy (self->s.origin, spot1);
		spot1[2] += self->viewheight;
		VectorCopy (self->enemy->s.origin, spot2);
		spot2[2] += self->enemy->viewheight;

		tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA);

		// do we have a clear shot?
		if (tr.ent != self->enemy)
		{	
			// go ahead and spawn stuff if we're mad a a client
			if (self->enemy->client && SELF_SLOTS_LEFT >= 2)
			{
				self->monsterinfo.attack_state = AS_BLIND;
				return true;
			}
				
			// PGM - we want them to go ahead and shoot at info_notnulls if they can.
			if(self->enemy->solid != SOLID_NOT || tr.fraction < 1.0)		//PGM
				return false;
		}
	}
	
	enemy_range = range(self, self->enemy);
	VectorSubtract (self->enemy->s.origin, self->s.origin, temp);
	enemy_yaw = vectoyaw2(temp);

	self->ideal_yaw = enemy_yaw;

	real_enemy_range = realrange (self, self->enemy);

	if (real_enemy_range <= (MELEE_DISTANCE+20))
	{
		// don't always melee in easy mode
		if (skill->value == 0 && (rand()&3) )
			return false;
		if (self->monsterinfo.melee)
			self->monsterinfo.attack_state = AS_MELEE;
		else
			self->monsterinfo.attack_state = AS_MISSILE;
		return true;
	}

	if (level.time < self->monsterinfo.attack_finished)
		return false;
		
	if (self->monsterinfo.aiflags & AI_STAND_GROUND)
	{
		chance = 0.4;
	}
	else if (enemy_range == RANGE_MELEE)
	{
		chance = 0.8;
	}
	else if (enemy_range == RANGE_NEAR)
	{
		chance = 0.7;
	}
	else if (enemy_range == RANGE_MID)
	{
		chance = 0.6;
	}
	else if (enemy_range == RANGE_FAR)
	{
		chance = 0.5;
	}

	// PGM - go ahead and shoot every time if it's a info_notnull
	if ((random () < chance) || (self->enemy->solid == SOLID_NOT))
	{
		self->monsterinfo.attack_state = AS_MISSILE;
		return true;
	}

	return false;
}
Exemple #6
0
qboolean
Widow2_CheckAttack(edict_t *self)
{
	vec3_t spot1, spot2;
	vec3_t temp;
	float chance = 0;
	trace_t tr;
	int enemy_range;
	float enemy_yaw;
	float real_enemy_range;
	vec3_t f, r, u;

	if (!self)
	{
		return false;
	}

	if (!self->enemy)
	{
		return false;
	}

	WidowPowerups(self);

	if ((random() < 0.8) && (SELF_SLOTS_LEFT >= 2) &&
		(realrange(self, self->enemy) > 150))
	{
		self->monsterinfo.aiflags |= AI_BLOCKED;
		self->monsterinfo.attack_state = AS_MISSILE;
		return true;
	}

	if (self->enemy->health > 0)
	{
		/* see if any entities are in the way of the shot */
		VectorCopy(self->s.origin, spot1);
		spot1[2] += self->viewheight;
		VectorCopy(self->enemy->s.origin, spot2);
		spot2[2] += self->enemy->viewheight;

		tr = gi.trace(spot1, NULL, NULL, spot2, self,
				CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_SLIME |
				CONTENTS_LAVA);

		/* do we have a clear shot? */
		if (tr.ent != self->enemy)
		{
			/* go ahead and spawn stuff if we're mad a a client */
			if (self->enemy->client && (SELF_SLOTS_LEFT >= 2))
			{
				self->monsterinfo.attack_state = AS_BLIND;
				return true;
			}

			if ((self->enemy->solid != SOLID_NOT) || (tr.fraction < 1.0))
			{
				return false;
			}
		}
	}

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

	self->ideal_yaw = enemy_yaw;

	/* melee attack */
	if (self->timestamp < level.time)
	{
		real_enemy_range = realrange(self, self->enemy);

		if (real_enemy_range < 300)
		{
			AngleVectors(self->s.angles, f, r, u);
			G_ProjectSource2(self->s.origin, offsets[0], f, r, u, spot1);
			VectorCopy(self->enemy->s.origin, spot2);

			if (widow2_tongue_attack_ok(spot1, spot2, 256))
			{
				/* be nice in easy mode */
				if ((skill->value == 0) && (rand() & 3))
				{
					return false;
				}

				if (self->monsterinfo.melee)
				{
					self->monsterinfo.attack_state = AS_MELEE;
				}
				else
				{
					self->monsterinfo.attack_state = AS_MISSILE;
				}

				return true;
			}
		}
	}

	if (level.time < self->monsterinfo.attack_finished)
	{
		return false;
	}

	if (self->monsterinfo.aiflags & AI_STAND_GROUND)
	{
		chance = 0.4;
	}
	else if (enemy_range == RANGE_NEAR)
	{
		chance = 0.8;
	}
	else if (enemy_range == RANGE_MID)
	{
		chance = 0.8;
	}
	else if (enemy_range == RANGE_FAR)
	{
		chance = 0.5;
	}

	if ((random() < chance) || (self->enemy->solid == SOLID_NOT))
	{
		self->monsterinfo.attack_state = AS_MISSILE;
		return true;
	}

	return false;
}