Example #1
0
void Mark2_BlasterAttack( qboolean advance ) {
	if ( TIMER_Done( NPC, "attackDelay" ) )	// Attack?
	{
		if ( NPCInfo->localState == LSTATE_NONE )	// He's up so shoot less often.
		{
			TIMER_Set( NPC, "attackDelay", Q_irand( 500, 2000 ) );
		}
		else {
			TIMER_Set( NPC, "attackDelay", Q_irand( 100, 500 ) );
		}
		Mark2_FireBlaster( advance );
		return;
	}
	else if ( advance ) {
		Mark2_Hunt();
	}
}
/*
-------------------------
Mark2_AttackDecision
-------------------------
*/
void Mark2_AttackDecision( void )
{
	float		distance;
	qboolean	visible;
	qboolean	advance;

	NPC_FaceEnemy( qtrue );

	distance	= (int) DistanceHorizontalSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin );	
	visible		= NPC_ClearLOS4( NPC->enemy );
	advance		= (qboolean)(distance > MIN_DISTANCE_SQR);

	// He's been ordered to get up
	if (NPCInfo->localState == LSTATE_RISINGUP)
	{
		NPC->flags &= ~FL_SHIELDED;
		NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1START, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE );
		if ((NPC->client->ps.legsTimer<=0) && 
			NPC->client->ps.torsoAnim == BOTH_RUN1START )
		{
			NPCInfo->localState = LSTATE_NONE;	// He's up again.
		}
		return;
	}

	// If we cannot see our target, move to see it
	if ((!visible) || (!NPC_FaceEnemy(qtrue)))
	{
		// If he's going down or is down, make him get up
		if ((NPCInfo->localState == LSTATE_DOWN) || (NPCInfo->localState == LSTATE_DROPPINGDOWN))
		{
			if ( TIMER_Done( NPC, "downTime" ) )	// Down being down?? (The delay is so he doesn't pop up and down when the player goes in and out of range)
			{
				NPCInfo->localState = LSTATE_RISINGUP;
				NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1STOP, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE );
				TIMER_Set( NPC, "runTime", Q_irand( 3000, 8000) );	// So he runs for a while before testing to see if he should drop down.
			}
		}
		else
		{
			Mark2_Hunt();
		}
		return;
	}

	// He's down but he could advance if he wants to.
	if ((advance) && (TIMER_Done( NPC, "downTime" )) && (NPCInfo->localState == LSTATE_DOWN))
	{
		NPCInfo->localState = LSTATE_RISINGUP;
		NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1STOP, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE );
		TIMER_Set( NPC, "runTime", Q_irand( 3000, 8000) );	// So he runs for a while before testing to see if he should drop down.
	}

	NPC_FaceEnemy( qtrue );

	// Dropping down to shoot
	if (NPCInfo->localState == LSTATE_DROPPINGDOWN)
	{
		NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_RUN1STOP, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE );
		TIMER_Set( NPC, "downTime", Q_irand( 3000, 9000) );

		if ((NPC->client->ps.legsTimer<=0) && NPC->client->ps.torsoAnim == BOTH_RUN1STOP )
		{
			NPC->flags |= FL_SHIELDED;
			NPCInfo->localState = LSTATE_DOWN;
		}
	}
	// He's down and shooting
	else if (NPCInfo->localState == LSTATE_DOWN)
	{
		NPC->flags |= FL_SHIELDED;//only damagable by lightsabers and missiles

		Mark2_BlasterAttack(qfalse);
	}
	else if (TIMER_Done( NPC, "runTime" ))	// Lowering down to attack. But only if he's done running at you.
	{
		NPCInfo->localState = LSTATE_DROPPINGDOWN;
	}
	else if (advance)
	{
		// We can see enemy so shoot him if timer lets you.
		Mark2_BlasterAttack(advance);
	}
}