Пример #1
0
//void NPC_Rancor_Pain( gentity_t *self, gentity_t *inflictor, gentity_t *other, const vec3_t point, int damage, int mod,int hitLoc ) 
void NPC_Rancor_Pain( gentity_t *self, gentity_t *attacker, int damage ) 
{
	qboolean hitByRancor = qfalse;
	if ( attacker&&attacker->client&&attacker->client->NPC_class==CLASS_RANCOR )
	{
		hitByRancor = qtrue;
	}
	if ( attacker 
		&& attacker->inuse 
		&& attacker != self->enemy
		&& !(attacker->flags&FL_NOTARGET) )
	{
		if ( !self->count )
		{
			if ( (G_IsPlayer(attacker) &&!Q_irand(0,3))
				|| !self->enemy
				|| self->enemy->health == 0
				|| (self->enemy->client&&self->enemy->client->NPC_class == CLASS_RANCOR)
				|| (self->NPC && self->NPC->consecutiveBlockedMoves>=10 && DistanceSquared( attacker->r.currentOrigin, self->r.currentOrigin ) < DistanceSquared( self->enemy->r.currentOrigin, self->r.currentOrigin )) ) 
			{//if my enemy is dead (or attacked by player) and I'm not still holding/eating someone, turn on the attacker
				//FIXME: if can't nav to my enemy, take this guy if I can nav to him
				G_SetEnemy( self, attacker );
				TIMER_Set( self, "lookForNewEnemy", Q_irand( 5000, 15000 ) );
				if ( hitByRancor )
				{//stay mad at this Rancor for 2-5 secs before looking for attacker enemies
					TIMER_Set( self, "rancorInfight", Q_irand( 2000, 5000 ) );
				}

			}
		}
	}
	if ( (hitByRancor|| (self->count==1&&self->activator&&!Q_irand(0,4)) || Q_irand( 0, 200 ) < damage )//hit by rancor, hit while holding live victim, or took a lot of damage
		&& self->client->ps.legsAnim != BOTH_STAND1TO2
		&& TIMER_Done( self, "takingPain" ) )
	{
		if ( !Rancor_CheckRoar( self ) )
		{
			if ( self->client->ps.legsAnim != BOTH_MELEE1
				&& self->client->ps.legsAnim != BOTH_MELEE2
				&& self->client->ps.legsAnim != BOTH_ATTACK2 )
			{//cant interrupt one of the big attack anims
				/*
				if ( self->count != 1 
					|| attacker == self->activator
					|| (self->client->ps.legsAnim != BOTH_ATTACK1&&self->client->ps.legsAnim != BOTH_ATTACK3) )
				*/
				{//if going to bite our victim, only victim can interrupt that anim
					if ( self->health > 100 || hitByRancor )
					{
						TIMER_Remove( self, "attacking" );

						VectorCopy( self->NPC->lastPathAngles, self->s.angles );

						if ( self->count == 1 )
						{
							NPC_SetAnim( self, SETANIM_BOTH, BOTH_PAIN2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
						}
						else
						{
							NPC_SetAnim( self, SETANIM_BOTH, BOTH_PAIN1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
						}
						TIMER_Set( self, "takingPain", self->client->ps.legsTimer+Q_irand(0, 500) );

						if ( self->NPC )
						{
							self->NPC->localState = LSTATE_WAITING;
						}
					}
				}
			}
		}
	}
}
Пример #2
0
/*
-------------------------
NAVNEW_PushBlocker
-------------------------
*/
void NAVNEW_PushBlocker( gentity_t *self, gentity_t *blocker, vec3_t right, qboolean setBlockedInfo )
{//try pushing blocker to one side
	trace_t	tr;
	vec3_t	mins, end;
	float	rightSucc, leftSucc, moveamt;

	if ( self->NPC->shoveCount > 30 )
	{//don't push for more than 3 seconds;
		return;
	}

	if ( G_IsPlayer(blocker) )
	{//never push the player
		return;
	}

	if ( !blocker->client || !VectorCompare( blocker->client->pushVec, vec3_origin ) )
	{//someone else is pushing him, wait until they give up?
		return;
	}

	VectorCopy( blocker->r.mins, mins );
	mins[2] += STEPSIZE;

	moveamt = (self->r.maxs[1] + blocker->r.maxs[1]) * 1.2;//yes, magic number

	VectorMA( blocker->r.currentOrigin, -moveamt, right, end );
	trap_Trace( &tr, blocker->r.currentOrigin, mins, blocker->r.maxs, end, blocker->s.number, blocker->clipmask|CONTENTS_BOTCLIP);
	if ( !tr.startsolid && !tr.allsolid )
	{
		leftSucc = tr.fraction;
	}
	else
	{
		leftSucc = 0.0f;
	}
	
	if ( leftSucc >= 1.0f )
	{//it's clear, shove him that way
		VectorScale( right, -moveamt, blocker->client->pushVec );
		blocker->client->pushVecTime = level.time + 2000;
	}
	else
	{
		VectorMA( blocker->r.currentOrigin, moveamt, right, end );
		trap_Trace( &tr, blocker->r.currentOrigin, mins, blocker->r.maxs, end, blocker->s.number, blocker->clipmask|CONTENTS_BOTCLIP );
		if ( !tr.startsolid && !tr.allsolid )
		{
			rightSucc = tr.fraction;
		}
		else
		{
			rightSucc = 0.0f;
		}
		
		if ( leftSucc == 0.0f && rightSucc == 0.0f )
		{//both sides failed
			if ( d_patched.integer )
			{//use patch-style navigation
				blocker->client->pushVecTime = 0;
			}
			return;
		}

		if ( rightSucc >= 1.0f )
		{//it's clear, shove him that way
			VectorScale( right, moveamt, blocker->client->pushVec );
			blocker->client->pushVecTime = level.time + 2000;
		}
		//if neither are enough, we probably can't get around him, but keep trying
		else if ( leftSucc >= rightSucc )
		{//favor the left, all things being equal
			VectorScale( right, -moveamt, blocker->client->pushVec );
			blocker->client->pushVecTime = level.time + 2000;
		}
		else
		{
			VectorScale( right, moveamt, blocker->client->pushVec );
			blocker->client->pushVecTime = level.time + 2000;
		}
	}

	if ( setBlockedInfo )
	{
		//we tried pushing
		self->NPC->shoveCount++;
	}
}