Esempio n. 1
0
qboolean SandCreature_Move( void )
{
	qboolean moved = qfalse;
	//FIXME should ignore doors..?
	vec3_t dest;
	VectorCopy( NPCInfo->goalEntity->currentOrigin, dest );
	//Sand Creatures look silly using waypoints when they can go straight to the goal
	if ( SandCreature_CheckAhead( dest ) )
	{//use our temp move straight to goal check
		VectorSubtract( dest, NPC->currentOrigin, NPC->client->ps.moveDir );
		NPC->client->ps.speed = VectorNormalize( NPC->client->ps.moveDir );
		if ( (ucmd.buttons&BUTTON_WALKING) && NPC->client->ps.speed > NPCInfo->stats.walkSpeed )
		{
			NPC->client->ps.speed = NPCInfo->stats.walkSpeed;
		}
		else
		{
			if ( NPC->client->ps.speed < NPCInfo->stats.walkSpeed )
			{
				NPC->client->ps.speed = NPCInfo->stats.walkSpeed;
			}
			if ( !(ucmd.buttons&BUTTON_WALKING) && NPC->client->ps.speed < NPCInfo->stats.runSpeed )
			{
				NPC->client->ps.speed = NPCInfo->stats.runSpeed;
			}
			else if ( NPC->client->ps.speed > NPCInfo->stats.runSpeed )
			{
				NPC->client->ps.speed = NPCInfo->stats.runSpeed;
			}
		}
		moved = qtrue;
	}
	else
	{
		moved = NPC_MoveToGoal( qtrue );
	}
	if ( moved && NPC->radius )
	{
		vec3_t	newPos;
		float curTurfRange, newTurfRange;
		curTurfRange = DistanceHorizontal( NPC->currentOrigin, NPC->s.origin );
		VectorMA( NPC->currentOrigin, NPC->client->ps.speed/100.0f, NPC->client->ps.moveDir, newPos );
		newTurfRange = DistanceHorizontal( newPos, NPC->s.origin );
		if ( newTurfRange > NPC->radius && newTurfRange > curTurfRange )
		{//would leave our range
			//stop
			NPC->client->ps.speed = 0.0f;
			VectorClear( NPC->client->ps.moveDir );
			ucmd.forwardmove = ucmd.rightmove = 0;
			moved = qfalse;
		}
	}
	return (moved);
	//often erroneously returns false ???  something wrong with NAV...?
}
Esempio n. 2
0
void RT_Flying_MaintainHeight( void )
{	
	float	dif = 0;

	// Update our angles regardless
	NPC_UpdateAngles( qtrue, qtrue );

	if ( NPC->forcePushTime > level.time )
	{//if being pushed, we don't have control over our movement
		return;
	}

	if ( (NPC->client->ps.pm_flags&PMF_TIME_KNOCKBACK) )
	{//don't slow down for a bit
		if ( NPC->client->ps.pm_time > 0 )
		{
			VectorScale( NPC->client->ps.velocity, 0.9f, NPC->client->ps.velocity );
			return;
		}
	}

	/*
	if ( (NPC->client->ps.eFlags&EF_FORCE_GRIPPED) )
	{
		RT_Flying_ApplyFriction( 3.0f );
		return;
	}
	*/
	// If we have an enemy, we should try to hover at or a little below enemy eye level
	if ( NPC->enemy 
		&& (!Q3_TaskIDPending( NPC, TID_MOVE_NAV ) || !NPCInfo->goalEntity ) )
	{
		if (TIMER_Done( NPC, "heightChange" ))
		{
			TIMER_Set( NPC,"heightChange",Q_irand( 1000, 3000 ));
			
			float enemyZHeight = NPC->enemy->currentOrigin[2];
			if ( NPC->enemy->client 
				&& NPC->enemy->client->ps.groundEntityNum == ENTITYNUM_NONE
				&& (NPC->enemy->client->ps.forcePowersActive&(1<<FP_LEVITATION)) )
			{//so we don't go up when they force jump up at us
				enemyZHeight = NPC->enemy->client->ps.forceJumpZStart;
			}

			// Find the height difference
			dif = (enemyZHeight +  Q_flrand( NPC->enemy->maxs[2]/2, NPC->enemy->maxs[2]+8 )) - NPC->currentOrigin[2]; 

			float	difFactor = 10.0f;

			// cap to prevent dramatic height shifts
			if ( fabs( dif ) > 2*difFactor )
			{
				if ( fabs( dif ) > 20*difFactor )
				{
					dif = ( dif < 0 ? -20*difFactor : 20*difFactor );
				}

				NPC->client->ps.velocity[2] = (NPC->client->ps.velocity[2]+dif)/2;
			}
			NPC->client->ps.velocity[2] *= Q_flrand( 0.85f, 1.25f );
		}
		else
		{//don't get too far away from height of enemy...
			float enemyZHeight = NPC->enemy->currentOrigin[2];
			if ( NPC->enemy->client 
				&& NPC->enemy->client->ps.groundEntityNum == ENTITYNUM_NONE
				&& (NPC->enemy->client->ps.forcePowersActive&(1<<FP_LEVITATION)) )
			{//so we don't go up when they force jump up at us
				enemyZHeight = NPC->enemy->client->ps.forceJumpZStart;
			}
			dif = NPC->currentOrigin[2] - (enemyZHeight+64);
			float maxHeight = 200;
			float hDist = DistanceHorizontal( NPC->enemy->currentOrigin, NPC->currentOrigin );
			if ( hDist < 512 )
			{
				maxHeight *= hDist/512;
			}
			if ( dif > maxHeight )
			{
				if ( NPC->client->ps.velocity[2] > 0 )//FIXME: or: we can't see him anymore
				{//slow down
					if ( NPC->client->ps.velocity[2] )
					{
						NPC->client->ps.velocity[2] *= VELOCITY_DECAY;

						if ( fabs( NPC->client->ps.velocity[2] ) < 2 )
						{
							NPC->client->ps.velocity[2] = 0;
						}
					}
				}
				else
				{//start coming back down
					NPC->client->ps.velocity[2] -= 4;
				}
			}
			else if ( dif < -200 && NPC->client->ps.velocity[2] < 0 )//we're way below him
			{
				if ( NPC->client->ps.velocity[2] < 0 )//FIXME: or: we can't see him anymore
				{//slow down
					if ( NPC->client->ps.velocity[2] )
					{
						NPC->client->ps.velocity[2] *= VELOCITY_DECAY;

						if ( fabs( NPC->client->ps.velocity[2] ) > -2 )
						{
							NPC->client->ps.velocity[2] = 0;
						}
					}
				}
				else
				{//start going back up
					NPC->client->ps.velocity[2] += 4;
				}
			}
		}
	}
	else
	{
		gentity_t *goal = NULL;

		if ( NPCInfo->goalEntity )	// Is there a goal?
		{
			goal = NPCInfo->goalEntity;
		}
		else
		{
			goal = NPCInfo->lastGoalEntity;
		}
		if ( goal )
		{
			dif = goal->currentOrigin[2] - NPC->currentOrigin[2];
		}
		else if ( VectorCompare( NPC->pos1, vec3_origin ) )
		{//have a starting position as a reference point
			dif = NPC->pos1[2] - NPC->currentOrigin[2];
		}

		if ( fabs( dif ) > 24 )
		{
			ucmd.upmove = ( ucmd.upmove < 0 ? -4 : 4 );
		}
		else
		{
			if ( NPC->client->ps.velocity[2] )
			{
				NPC->client->ps.velocity[2] *= VELOCITY_DECAY;

				if ( fabs( NPC->client->ps.velocity[2] ) < 2 )
				{
					NPC->client->ps.velocity[2] = 0;
				}
			}
		}
	}

	// Apply friction
	RT_Flying_ApplyFriction( 1.0f );
}
Esempio n. 3
0
//----------------------------------
//replaced with SP version.
static void Howler_Combat( void )
{
	qboolean	faced = qfalse;
	float		distance;	
	qboolean	advance = qfalse;
	if ( NPC->client->ps.groundEntityNum == ENTITYNUM_NONE )
	{//not on the ground
		if ( NPC->client->ps.legsAnim == BOTH_JUMP1
			|| NPC->client->ps.legsAnim == BOTH_INAIR1 )
		{//flying through the air with the greatest of ease, etc
			Howler_TryDamage( 10, qfalse, qfalse );
		}
	}
	else
	{//not in air, see if we should attack or advance
		// If we cannot see our target or we have somewhere to go, then do that
		if ( !NPC_ClearLOS4( NPC->enemy ) )//|| UpdateGoal( ))
		{
			NPCInfo->goalEntity = NPC->enemy;
			NPCInfo->goalRadius = MAX_DISTANCE;	// just get us within combat range

			if ( NPCInfo->localState == LSTATE_BERZERK )
			{
				NPC_Howler_Move( 3 );
			}
			else
			{
				NPC_Howler_Move( 10 );
			}
			NPC_UpdateAngles( qfalse, qtrue );
			return;
		}

		distance = DistanceHorizontal( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin );	

		if ( NPC->enemy && NPC->enemy->client && PM_InKnockDown( &NPC->enemy->client->ps ) )
		{//get really close to knocked down enemies
			advance = (qboolean)( distance > MIN_DISTANCE ? qtrue : qfalse  );
		}
		else
		{
			advance = (qboolean)( distance > MAX_DISTANCE ? qtrue : qfalse  );//MIN_DISTANCE
		}

		if (( advance || NPCInfo->localState == LSTATE_WAITING ) && TIMER_Done( NPC, "attacking" )) // waiting monsters can't attack
		{
			if ( TIMER_Done2( NPC, "takingPain", qtrue ))
			{
				NPCInfo->localState = LSTATE_CLEAR;
			}
			else if ( TIMER_Done( NPC, "standing" ) )
			{
				faced = Howler_Move( qtrue );
			}
		}
		else
		{
			Howler_Attack( distance, qfalse );
		}
	}

	if ( !faced )
	{
		if ( //TIMER_Done( NPC, "standing" ) //not just standing there
			//!advance //not moving
			TIMER_Done( NPC, "attacking" ) )// not attacking
		{//not standing around
			// Sometimes I have problems with facing the enemy I'm attacking, so force the issue so I don't look dumb
			NPC_FaceEnemy( qtrue );
		}
		else
		{
			NPC_UpdateAngles( qfalse, qtrue );
		}
	}
}