Beispiel #1
0
void thing_think_pause(edict_t *self)
{
	edict_t	*monster;
	if(level.time > self->touch_debounce_time)
	{
		thing_think(self);
		return;
	}
	monster = self->target_ent;
	if(!monster || !monster->inuse)
	{
		G_FreeEdict(self);
		return;
	}
	if(has_valid_enemy(monster))
	{
		vec3_t	dir;
		vec3_t	angles;

		if(visible(monster->enemy,monster))
		{
			self->touch_debounce_time = 0;
			thing_think(self);
			return;
		}
		VectorSubtract(monster->enemy->s.origin,monster->s.origin,dir);
		VectorNormalize(dir);
		vectoangles(dir,angles);
		monster->ideal_yaw = angles[YAW];
		M_ChangeYaw(monster);
	}
	self->nextthink = level.time + FRAMETIME;
}
Beispiel #2
0
void
stalker_attack_ranged(edict_t *self)
{
	if (!self)
	{
		return;
	}

	if (!has_valid_enemy(self))
	{
		return;
	}

	/* circle strafe stuff */
	if (random() > (1.0 - (0.5 / (float)(skill->value))))
	{
		self->monsterinfo.attack_state = AS_STRAIGHT;
	}
	else
	{
		if (random() <= 0.5) /* switch directions */
		{
			self->monsterinfo.lefty = 1 - self->monsterinfo.lefty;
		}

		self->monsterinfo.attack_state = AS_SLIDING;
	}

	self->monsterinfo.currentmove = &stalker_move_shoot;
}
Beispiel #3
0
void
stalker_shoot_attack(edict_t *self)
{
	vec3_t offset, start, f, r, dir;
	vec3_t end;
	float time, dist;
	trace_t trace;

	if (!self)
	{
		return;
	}

	if (!has_valid_enemy(self))
	{
		return;
	}

	if (self->groundentity && (random() < 0.33))
	{
		VectorSubtract(self->enemy->s.origin, self->s.origin, dir);
		dist = VectorLength(dir);

		if ((dist > 256) || (random() < 0.5))
		{
			stalker_do_pounce(self, self->enemy->s.origin);
		}
		else
		{
			stalker_jump_straightup(self);
		}
	}

	AngleVectors(self->s.angles, f, r, NULL);
	VectorSet(offset, 24, 0, 6);
	G_ProjectSource(self->s.origin, offset, f, r, start);

	VectorSubtract(self->enemy->s.origin, start, dir);

	if (random() < (0.20 + 0.1 * skill->value))
	{
		dist = VectorLength(dir);
		time = dist / 1000;
		VectorMA(self->enemy->s.origin, time, self->enemy->velocity, end);
		VectorSubtract(end, start, dir);
	}
	else
	{
		VectorCopy(self->enemy->s.origin, end);
	}

	trace = gi.trace(start, vec3_origin, vec3_origin, end, self, MASK_SHOT);

	if ((trace.ent == self->enemy) || (trace.ent == world))
	{
		monster_fire_blaster2(self, start, dir, 15, 800, MZ2_STALKER_BLASTER, EF_BLASTER);
	}
}
Beispiel #4
0
qboolean stalker_blocked (edict_t *self, float dist)
{
	qboolean	onCeiling;

	if(!has_valid_enemy(self))
		return false;

	onCeiling = false;
	if(self->gravityVector[2] > 0)
		onCeiling = true;

	if(!onCeiling)
	{
		if(blocked_checkshot(self, 0.25 + (0.05 * skill->value) ))
		{
			return true;
		}

		if(visible (self, self->enemy))
		{
			stalker_do_pounce(self, self->enemy->s.origin);
			return true;
		}

		if(blocked_checkjump (self, dist, 256, 68))
		{
			stalker_jump (self);
			return true;
		}

		if(blocked_checkplat (self, dist))
			return true;
	}
	else
	{
		if(blocked_checkshot(self, 0.25 + (0.05 * skill->value) ))
		{
			return true;
		}	
		else if(stalker_ok_to_transition(self))
		{
			self->gravityVector[2] = -1;
			self->s.angles[2] += 180.0;
			if(self->s.angles[2] > 360.0)
				self->s.angles[2] -= 360.0;
			self->groundentity = NULL;
			
			return true;
		}
	}

	return false;
}
Beispiel #5
0
void stalker_attack_melee (edict_t *self)
{
	if(!has_valid_enemy(self))
		return;

	if(random() < 0.5)
	{
		self->monsterinfo.currentmove = &stalker_move_swing_l;
	}
	else
	{
		self->monsterinfo.currentmove = &stalker_move_swing_r;
	}
}
Beispiel #6
0
void stalker_shoot_attack (edict_t *self)
{
	vec3_t	offset, start, f, r, dir;
	vec3_t	end;
	float	time, dist;
	trace_t	trace;

	if(!has_valid_enemy(self))
		return;

	if(self->groundentity && random() < 0.33)
	{
		VectorSubtract (self->enemy->s.origin, self->s.origin, dir);
		dist = VectorLength (dir);

		if((dist > 256) || (random() < 0.5))
			stalker_do_pounce(self, self->enemy->s.origin);
		else
			stalker_jump_straightup (self);
	}

	// FIXME -- keep this but use a custom one
//	if (!infront(self, self->enemy))
//		return;

	AngleVectors (self->s.angles, f, r, NULL);
	VectorSet (offset, 24, 0, 6);
	G_ProjectSource (self->s.origin, offset, f, r, start);

	VectorSubtract(self->enemy->s.origin, start, dir);
	if(random() < (0.20 + 0.1 * skill->value))
	{
		dist = VectorLength(dir);
		time = dist / 1000;
		VectorMA(self->enemy->s.origin, time, self->enemy->velocity, end);
		VectorSubtract(end, start, dir);
	}
	else
		VectorCopy(self->enemy->s.origin, end);

	trace = gi.trace(start, vec3_origin, vec3_origin, end, self, MASK_SHOT);
	if(trace.ent == self->enemy || trace.ent == world)
		monster_fire_blaster2(self, start, dir, 15, 800, MZ2_STALKER_BLASTER, EF_BLASTER);
//	else
//		gi.dprintf("blocked by entity %s\n", trace.ent->classname);
}
/*
=====================
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);
}
Beispiel #8
0
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);
}
Beispiel #9
0
qboolean stalker_blocked (edict_t *self, float dist)
{
	qboolean	onCeiling;

//	gi.dprintf("stalker_blocked\n");
	if(!has_valid_enemy(self))
		return false;

	onCeiling = false;
	if(self->gravityVector[2] > 0)
		onCeiling = true;

	if(!onCeiling)
	{
		if(blocked_checkshot(self, 0.25 + (0.05 * skill->value) ))
		{
//			gi.dprintf("blocked: shooting\n");
			return true;
		}

		if(visible (self, self->enemy))
		{
//			gi.dprintf("blocked: jumping at player!\n");
			stalker_do_pounce(self, self->enemy->s.origin);
			return true;
		}

		if(blocked_checkjump (self, dist, 256, 68))
		{
//			gi.dprintf("blocked: jumping up/down\n");
			stalker_jump (self);
			return true;
		}

		if(blocked_checkplat (self, dist))
			return true;
	}
	else
	{
		if(blocked_checkshot(self, 0.25 + (0.05 * skill->value) ))
		{
//			gi.dprintf("blocked: shooting\n");
			return true;
		}	
		else if(stalker_ok_to_transition(self))
		{
			self->gravityVector[2] = -1;
			self->s.angles[2] += 180.0;
			if(self->s.angles[2] > 360.0)
				self->s.angles[2] -= 360.0;
			self->groundentity = NULL;
			
//			gi.dprintf("falling off ceiling\n");
			return true;
		}
//		else
//			gi.dprintf("Not OK to fall!\n");
	}

	return false;
}
Beispiel #10
0
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);
}
Beispiel #11
0
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);
}