Example #1
0
int CWeaponCrowbar::WeaponMeleeAttack1Condition( float flDot, float flDist )
{
	// Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!)
	CAI_BaseNPC *pNPC	= GetOwner()->MyNPCPointer();
	CBaseEntity *pEnemy = pNPC->GetEnemy();
	if (!pEnemy)
		return COND_NONE;

	Vector vecVelocity;
	vecVelocity = pEnemy->GetSmoothedVelocity( );

	// Project where the enemy will be in a little while
	float dt = sk_crowbar_lead_time.GetFloat();
	dt += random->RandomFloat( -0.3f, 0.2f );
	if ( dt < 0.0f )
		dt = 0.0f;

	Vector vecExtrapolatedPos;
	VectorMA( pEnemy->WorldSpaceCenter(), dt, vecVelocity, vecExtrapolatedPos );

	Vector vecDelta;
	VectorSubtract( vecExtrapolatedPos, pNPC->WorldSpaceCenter(), vecDelta );

	if ( fabs( vecDelta.z ) > 70 )
	{
		return COND_TOO_FAR_TO_ATTACK;
	}

	Vector vecForward = pNPC->BodyDirection2D( );
	vecDelta.z = 0.0f;
	float flExtrapolatedDist = Vector2DNormalize( vecDelta.AsVector2D() );
	if ((flDist > 64) && (flExtrapolatedDist > 64))
	{
		return COND_TOO_FAR_TO_ATTACK;
	}

	float flExtrapolatedDot = DotProduct2D( vecDelta.AsVector2D(), vecForward.AsVector2D() );
	if ((flDot < 0.7) && (flExtrapolatedDot < 0.7))
	{
		return COND_NOT_FACING_ATTACK;
	}

	return COND_CAN_MELEE_ATTACK1;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CAI_LeadBehavior::GatherConditions( void )
{
	BaseClass::GatherConditions();

	if ( HasGoal() )
	{
		// Fix for bad transition case (to investigate)
		if ( ( WorldSpaceCenter() - m_goal ).LengthSqr() > (64*64) && IsCurSchedule( SCHED_LEAD_AWAIT_SUCCESS, false)  )
		{
			GetOuter()->ClearSchedule( "Lead behavior - bad transition?" );
		}

		// We have to collect data about the person we're leading around.
		CBaseEntity *pFollower = AI_GetSinglePlayer();

		if( pFollower )
		{
			ClearCondition( COND_LEAD_FOLLOWER_VERY_CLOSE );
			ClearCondition( COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME );

			// Check distance to the follower
			float flFollowerDist = ( WorldSpaceCenter() - pFollower->WorldSpaceCenter() ).Length();
			bool bLagging = flFollowerDist > (m_leaddistance*4);
			if ( bLagging )
			{
				if ( PlayerIsAheadOfMe() )
				{
					bLagging = false;
				}
			}

			// Player heading towards me?
			// Only factor this in if you're not too far from them
			if ( flFollowerDist < (m_leaddistance*4) )
			{
				Vector vecVelocity = pFollower->GetSmoothedVelocity();
				if ( VectorNormalize(vecVelocity) > 50 )
				{
					Vector vecToPlayer = (GetAbsOrigin() - pFollower->GetAbsOrigin());
					VectorNormalize( vecToPlayer );
					if ( DotProduct( vecVelocity, vecToPlayer ) > 0.5 )
					{
						SetCondition( COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME );
						bLagging = false;
					}
				}
			}

			// If he's outside our lag range, consider him lagging
			if ( bLagging )
			{
				SetCondition( COND_LEAD_FOLLOWER_LAGGING );
				ClearCondition( COND_LEAD_FOLLOWER_NOT_LAGGING );
			}
			else
			{
				ClearCondition( COND_LEAD_FOLLOWER_LAGGING );
				SetCondition( COND_LEAD_FOLLOWER_NOT_LAGGING );

				// If he's really close, note that
				if ( flFollowerDist < m_leaddistance )
				{
					SetCondition( COND_LEAD_FOLLOWER_VERY_CLOSE );
				}
			}

			// To be considered not lagging, the follower must be visible, and within the lead distance
			if ( GetOuter()->FVisible( pFollower ) && GetOuter()->GetSenses()->ShouldSeeEntity( pFollower ) )
			{
				SetCondition( COND_LEAD_HAVE_FOLLOWER_LOS );
				m_LostLOSTimer.Stop();
			}
			else
			{
				ClearCondition( COND_LEAD_HAVE_FOLLOWER_LOS );

				// We don't have a LOS. But if we did have LOS, don't clear it until the timer is up.
				if ( m_LostLOSTimer.IsRunning() )
				{
					if ( m_LostLOSTimer.Expired() )
					{
						SetCondition( COND_LEAD_FOLLOWER_LAGGING );
						ClearCondition( COND_LEAD_FOLLOWER_NOT_LAGGING );
					}
				}
				else
				{
					m_LostLOSTimer.Start();
				}
			}

			// Now we want to see if the follower is lost. Being lost means being (far away || out of LOS ) 
			// && some time has passed. Also, lagging players are considered lost if the NPC's never delivered
			// the start speech, because it means the NPC should run to the player to start the lead.
			if( HasCondition( COND_LEAD_FOLLOWER_LAGGING ) )
			{
				if ( !m_hasspokenstart )
				{
					SetCondition( COND_LEAD_FOLLOWER_LOST );
				}
				else
				{
					if ( m_args.bStopScenesWhenPlayerLost )
					{
						// Try and stop me speaking my monolog, if I am
						if ( !m_hasPausedScenes && IsRunningScriptedScene( GetOuter() ) )
						{
							//Msg("Stopping scenes.\n");
							PauseActorsScriptedScenes( GetOuter(), false );
							m_hasPausedScenes = true;
						}
					}

					if( m_LostTimer.IsRunning() )
					{
						if( m_LostTimer.Expired() )
						{
							SetCondition( COND_LEAD_FOLLOWER_LOST );
						}
					}
					else
					{
						m_LostTimer.Start();
					}
				}
			}
			else
			{
				// If I was speaking a monolog, resume it
				if ( m_args.bStopScenesWhenPlayerLost && m_hasPausedScenes )
				{
					if ( IsRunningScriptedScene( GetOuter() ) )
					{
						//Msg("Resuming scenes.\n");
						ResumeActorsScriptedScenes( GetOuter(), false );
					}

					m_hasPausedScenes = false;
				}

				m_LostTimer.Stop();
				ClearCondition( COND_LEAD_FOLLOWER_LOST );
			}

			// Evaluate for success
			// Success right now means being stationary, close to the goal, and having the player close by
			if ( !( m_args.flags & AILF_NO_DEF_SUCCESS ) )
			{
				ClearCondition( COND_LEAD_SUCCESS );

				// Check Z first, and only check 2d if we're within that
				bool bWithinZ = fabs(GetLocalOrigin().z - m_goal.z) < 64;
				if ( bWithinZ && (GetLocalOrigin() - m_goal).Length2D() <= 64 )
				{
					if ( HasCondition( COND_LEAD_FOLLOWER_VERY_CLOSE ) )
					{
						SetCondition( COND_LEAD_SUCCESS );
					}
					else if ( m_successdistance )
					{
						float flDistSqr = (pFollower->GetAbsOrigin() - GetLocalOrigin()).Length2DSqr();
						if ( flDistSqr < (m_successdistance*m_successdistance) )
						{
							SetCondition( COND_LEAD_SUCCESS );
						}
					}
				}
			}
			if ( m_MoveMonitor.IsMarkSet() && m_MoveMonitor.TargetMoved( pFollower ) )
				SetCondition( COND_LEAD_FOLLOWER_MOVED_FROM_MARK );
			else
				ClearCondition( COND_LEAD_FOLLOWER_MOVED_FROM_MARK );
		}
	}

	if( m_args.bLeadDuringCombat )
	{
		ClearCondition( COND_LIGHT_DAMAGE );
		ClearCondition( COND_HEAVY_DAMAGE );
	}
}