Beispiel #1
0
void stalker_pain (edict_t *self, edict_t *other, float kick, int damage)
{
	if (self->deadflag == DEAD_DEAD)
		return;

	if (self->health < (self->max_health / 2)) 
	{
		self->s.skinnum = 1;
	}

	if (skill->value == 3)
		return;		// no pain anims in nightmare

//	if (self->monsterinfo.aiflags & AI_DODGING)
//		monster_done_dodge (self);

	if (self->groundentity == NULL)
		return;

	// if we're reactivating or false dying, ignore the pain.
	if (self->monsterinfo.currentmove == &stalker_move_false_death_end ||
		self->monsterinfo.currentmove == &stalker_move_false_death_start )
		return;

	if (self->monsterinfo.currentmove == &stalker_move_false_death)
	{
		stalker_reactivate(self);
		return;
	}

	if ((self->health > 0) && (self->health < (self->max_health / 4)))
	{
		if(random() < (0.2 * skill->value))
		{
			if( !STALKER_ON_CEILING(self) || stalker_ok_to_transition(self) )
			{
//				gi.dprintf("starting false death sequence\n");
				stalker_false_death_start(self);
				return;
			}
		}	
	}

	if (level.time < self->pain_debounce_time)
		return;

	self->pain_debounce_time = level.time + 3;

//	gi.dprintf("stalker_pain\n");
	if (damage > 10)		// don't react unless the damage was significant
	{
		// stalker should dodge jump periodically to help avoid damage.
		if(self->groundentity && (random() < 0.5))
			stalker_dodge_jump(self);
		else
			self->monsterinfo.currentmove = &stalker_move_pain;

		gi.sound (self, CHAN_WEAPON, sound_pain, 1, ATTN_NORM, 0);
	}
}
Beispiel #2
0
//===================
// stalker_jump_straightup
//===================
void stalker_jump_straightup (edict_t *self)
{
	if (self->deadflag == DEAD_DEAD)
		return;

	if(STALKER_ON_CEILING(self))
	{
		if(stalker_ok_to_transition(self))
		{
//			gi.dprintf("falling off ceiling %d\n", self->health);
			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;
		}
	}
	else if(self->groundentity)	// make sure we're standing on SOMETHING...
	{
		self->velocity[0] += ((random() * 10) - 5);
		self->velocity[1] += ((random() * 10) - 5);
		self->velocity[2] += -400 * self->gravityVector[2];
		if(stalker_ok_to_transition(self))
		{
//			gi.dprintf("falling TO ceiling %d\n", self->health);
			self->gravityVector[2] = 1;
			self->s.angles[2] = 180.0;
			self->groundentity = NULL;
		}
	}
}
Beispiel #3
0
void
stalker_jump_straightup(edict_t *self)
{
	if (!self)
	{
		return;
	}

	if (self->deadflag == DEAD_DEAD)
	{
		return;
	}

	if (STALKER_ON_CEILING(self))
	{
		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;
		}
	}
	else if (self->groundentity) /* make sure we're standing on SOMETHING... */
	{
		self->velocity[0] += ((random() * 10) - 5);
		self->velocity[1] += ((random() * 10) - 5);
		self->velocity[2] += -400 * self->gravityVector[2];

		if (stalker_ok_to_transition(self))
		{
			self->gravityVector[2] = 1;
			self->s.angles[2] = 180.0;
			self->groundentity = NULL;
		}
	}
}
Beispiel #4
0
// ====================
// ====================
int stalker_do_pounce(edict_t *self, vec3_t dest)
{
	vec3_t	forward, right;
	vec3_t	dist;
	vec_t	length;
	vec3_t	jumpAngles;
	vec3_t	jumpLZ;
	float	velocity = 400.1;
	trace_t	trace;
	int		preferHighJump;

	// don't pounce when we're on the ceiling
	if(STALKER_ON_CEILING(self))
		return false;

	if(!stalker_check_lz (self, self->enemy, dest))
		return false;

	VectorSubtract(dest, self->s.origin, dist);
	
	// make sure we're pointing in that direction 15deg margin of error.
	vectoangles2 (dist, jumpAngles);
	if(abs(jumpAngles[YAW] - self->s.angles[YAW]) > 45)
		return false;			// not facing the player...

	self->ideal_yaw = jumpAngles[YAW];
	M_ChangeYaw(self);

	length = VectorLength(dist);
	if(length > 450)
		return false;			// can't jump that far...

	VectorCopy(dest, jumpLZ);

	preferHighJump = 0;

	// if we're having to jump up a distance, jump a little too high to compensate.
	if(dist[2] >= 32.0)
	{
		preferHighJump = 1;
		jumpLZ[2] += 32;
	}

	trace = gi.trace (self->s.origin, vec3_origin, vec3_origin, dest, self, MASK_MONSTERSOLID);
	if((trace.fraction < 1) && (trace.ent != self->enemy))
	{
//		gi.dprintf("prefer high jump angle\n");
		preferHighJump = 1; 
	}

	// find a valid angle/velocity combination
	while(velocity <= 800)
	{
		calcJumpAngle(self->s.origin, jumpLZ, velocity, jumpAngles);
		if((!_isnan(jumpAngles[0]))  || (!_isnan(jumpAngles[1])))
			break;
		
		velocity+=200;
	};

	if(!preferHighJump && (!_isnan(jumpAngles[0])) )
	{
		AngleVectors (self->s.angles, forward, right, NULL);
		VectorNormalize ( forward ) ;

		VectorScale( forward, velocity * cos(DEG2RAD(jumpAngles[0])), self->velocity);
		self->velocity[2] = velocity * sin(DEG2RAD(jumpAngles[0])) + (0.5 * sv_gravity->value * FRAMETIME);
//		gi.dprintf("  pouncing! %0.1f,%0.1f (%0.1f)  --> %0.1f, %0.1f, %0.1f\n", 
//				jumpAngles[0], jumpAngles[1], jumpAngles[0],
//				self->velocity[0], self->velocity[1], self->velocity[2]);
		return 1;
	}

	if(!_isnan(jumpAngles[1]))
	{
		AngleVectors (self->s.angles, forward, right, NULL);
		VectorNormalize ( forward ) ;

		VectorScale( forward, velocity * cos(DEG2RAD(jumpAngles[1])), self->velocity);
		self->velocity[2] = velocity * sin(DEG2RAD(jumpAngles[1])) + (0.5 * sv_gravity->value * FRAMETIME);
//		gi.dprintf("  pouncing! %0.1f,%0.1f (%0.1f)  --> %0.1f, %0.1f, %0.1f\n", 
//				jumpAngles[0], jumpAngles[1], jumpAngles[1],
//				self->velocity[0], self->velocity[1], self->velocity[2]);
		return 1;
	}

//	gi.dprintf("  nan\n");
	return 0;
}
Beispiel #5
0
//=========================
//=========================
qboolean stalker_ok_to_transition (edict_t *self)
{
	trace_t		trace;
	vec3_t		pt, start;
	float		max_dist;
	float		margin;
	float		end_height;

	if(STALKER_ON_CEILING(self))
	{
		max_dist = -384;
		margin = self->mins[2] - 8;
	}	
	else
	{
		// her stalkers are just better
		if (self->monsterinfo.aiflags & AI_SPAWNED_WIDOW)
			max_dist = 256;
		else
			max_dist = 180;
		margin = self->maxs[2] + 8;
	}

	VectorCopy(self->s.origin, pt);
	pt[2] += max_dist;
	trace = gi.trace (self->s.origin, self->mins, self->maxs, pt, self, MASK_MONSTERSOLID);

	if(trace.fraction == 1.0 || 
	   !(trace.contents & CONTENTS_SOLID) ||
	   (trace.ent != world))
	{
		if(STALKER_ON_CEILING(self))
		{
			if(trace.plane.normal[2] < 0.9)
				return false;
		}
		else
		{
			if(trace.plane.normal[2] > -0.9)
				return false;
		}
	}
//	gi.dprintf("stalker_check_pt: main check ok\n");

	end_height = trace.endpos[2];

	// check the four corners, tracing only to the endpoint of the center trace (vertically).
	pt[0] = self->absmin[0];
	pt[1] = self->absmin[1];
	pt[2] = trace.endpos[2] + margin;	// give a little margin of error to allow slight inclines
	VectorCopy(pt, start);
	start[2] = self->s.origin[2];
	trace = gi.trace( start, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID);
	if(trace.fraction == 1.0 || !(trace.contents & CONTENTS_SOLID) || (trace.ent != world))
	{
//		gi.dprintf("stalker_check_pt: absmin/absmin failed\n");
		return false;
	}
	if(abs(end_height + margin - trace.endpos[2]) > 8)
		return false;

	pt[0] = self->absmax[0];
	pt[1] = self->absmin[1];
	VectorCopy(pt, start);
	start[2] = self->s.origin[2];
	trace = gi.trace( start, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID);
	if(trace.fraction == 1.0 || !(trace.contents & CONTENTS_SOLID) || (trace.ent != world))
	{
//		gi.dprintf("stalker_check_pt: absmax/absmin failed\n");
		return false;
	}
	if(abs(end_height + margin - trace.endpos[2]) > 8)
		return false;

	pt[0] = self->absmax[0];
	pt[1] = self->absmax[1];
	VectorCopy(pt, start);
	start[2] = self->s.origin[2];
	trace = gi.trace( start, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID);
	if(trace.fraction == 1.0 || !(trace.contents & CONTENTS_SOLID) || (trace.ent != world))
	{
//		gi.dprintf("stalker_check_pt: absmax/absmax failed\n");
		return false;
	}
	if(abs(end_height + margin - trace.endpos[2]) > 8)
		return false;

	pt[0] = self->absmin[0];
	pt[1] = self->absmax[1];
	VectorCopy(pt, start);
	start[2] = self->s.origin[2];
	trace = gi.trace( start, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID);
	if(trace.fraction == 1.0 || !(trace.contents & CONTENTS_SOLID) || (trace.ent != world))
	{
//		gi.dprintf("stalker_check_pt: absmin/absmax failed\n");
		return false;
	}
	if(abs(end_height + margin - trace.endpos[2]) > 8)
		return false;

	return true;
}
Beispiel #6
0
void
stalker_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage)
{
	if (!self)
	{
		return;
	}

	if (self->deadflag == DEAD_DEAD)
	{
		return;
	}

	if (self->health < (self->max_health / 2))
	{
		self->s.skinnum = 1;
	}

	if (skill->value == 3)
	{
		return; /* no pain anims in nightmare */
	}

	if (self->groundentity == NULL)
	{
		return;
	}

	/* if we're reactivating or false dying, ignore the pain. */
	if ((self->monsterinfo.currentmove == &stalker_move_false_death_end) ||
		(self->monsterinfo.currentmove == &stalker_move_false_death_start))
	{
		return;
	}

	if (self->monsterinfo.currentmove == &stalker_move_false_death)
	{
		stalker_reactivate(self);
		return;
	}

	if ((self->health > 0) && (self->health < (self->max_health / 4)))
	{
		if (random() < (0.2 * skill->value))
		{
			if (!STALKER_ON_CEILING(self) || stalker_ok_to_transition(self))
			{
				stalker_false_death_start(self);
				return;
			}
		}
	}

	if (level.time < self->pain_debounce_time)
	{
		return;
	}

	self->pain_debounce_time = level.time + 3;

	if (damage > 10) /* don't react unless the damage was significant */
	{
		/* stalker should dodge jump periodically to help avoid damage. */
		if (self->groundentity && (random() < 0.5))
		{
			stalker_dodge_jump(self);
		}
		else
		{
			self->monsterinfo.currentmove = &stalker_move_pain;
		}

		gi.sound(self, CHAN_WEAPON, sound_pain, 1, ATTN_NORM, 0);
	}
}
Beispiel #7
0
qboolean
stalker_ok_to_transition(edict_t *self)
{
	trace_t trace;
	vec3_t pt, start;
	float max_dist;
	float margin;
	float end_height;

	if (!self)
	{
		return false;
	}

	if (STALKER_ON_CEILING(self))
	{
		max_dist = -384;
		margin = self->mins[2] - 8;
	}
	else
	{
		// ace - (because, reasons) make give them some randomness (and FIXME: add another way to differentiate Widow spawns)
		max_dist = 180 + (rand() & 76);

		/* her stalkers are just better */
/*		if (self->monsterinfo.aiflags & AI_SPAWNED_WIDOW)
		{
			max_dist = 256;
		}
		else
		{
			max_dist = 180;
		}*/

		margin = self->maxs[2] + 8;
	}

	VectorCopy(self->s.origin, pt);
	pt[2] += max_dist;
	trace = gi.trace(self->s.origin, self->mins, self->maxs,
			pt, self, MASK_MONSTERSOLID);

	if ((trace.fraction == 1.0) ||
		!(trace.contents & CONTENTS_SOLID) ||
		(trace.ent != world))
	{
		if (STALKER_ON_CEILING(self))
		{
			if (trace.plane.normal[2] < 0.9)
			{
				return false;
			}
		}
		else
		{
			if (trace.plane.normal[2] > -0.9)
			{
				return false;
			}
		}
	}

	end_height = trace.endpos[2];

	/* check the four corners, tracing only to the
	   endpoint of the center trace (vertically). */
	pt[0] = self->absmin[0];
	pt[1] = self->absmin[1];
	pt[2] = trace.endpos[2] + margin; /* give a little margin of error to allow slight inclines */
	VectorCopy(pt, start);
	start[2] = self->s.origin[2];
	trace = gi.trace(start, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID);

	if ((trace.fraction == 1.0) || !(trace.contents & CONTENTS_SOLID) ||
		(trace.ent != world))
	{
		return false;
	}

	if (fabsf(end_height + margin - trace.endpos[2]) > 8)
	{
		return false;
	}

	pt[0] = self->absmax[0];
	pt[1] = self->absmin[1];
	VectorCopy(pt, start);
	start[2] = self->s.origin[2];
	trace = gi.trace(start, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID);

	if ((trace.fraction == 1.0) || !(trace.contents & CONTENTS_SOLID) ||
		(trace.ent != world))
	{
		return false;
	}

	if (fabsf(end_height + margin - trace.endpos[2]) > 8)
	{
		return false;
	}

	pt[0] = self->absmax[0];
	pt[1] = self->absmax[1];
	VectorCopy(pt, start);
	start[2] = self->s.origin[2];
	trace = gi.trace(start, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID);

	if ((trace.fraction == 1.0) || !(trace.contents & CONTENTS_SOLID) || (trace.ent != world))
	{
		return false;
	}

	if (fabsf(end_height + margin - trace.endpos[2]) > 8)
	{
		return false;
	}

	pt[0] = self->absmin[0];
	pt[1] = self->absmax[1];
	VectorCopy(pt, start);
	start[2] = self->s.origin[2];
	trace = gi.trace(start, vec3_origin, vec3_origin, pt, self, MASK_MONSTERSOLID);

	if ((trace.fraction == 1.0) || !(trace.contents & CONTENTS_SOLID) || (trace.ent != world))
	{
		return false;
	}

	if (fabsf(end_height + margin - trace.endpos[2]) > 8)
	{
		return false;
	}

	return true;
}