Ejemplo n.º 1
0
bool CAIWeaponAbstract::DefaultFire(CAI* pAI, const LTVector& vTargetPos, bool bAnimatesReload)
{
	if( !( m_pWeapon && m_pAIWeaponRecord ) )
	{
		return false;
	}

	HOBJECT hTarget = pAI->GetAIBlackBoard()->GetBBTargetObject();

	// Get our fire position

	LTVector vFirePos = GetFirePosition(pAI);

	// Get our firing vector

	LTVector vDir = vTargetPos - vFirePos;
	vDir.Normalize();

	// Now fire the weapon

	WeaponFireInfo weaponFireInfo;
	static uint8 s_nCount = GetRandom( 0, 255 );
	s_nCount++;

	weaponFireInfo.hFiredFrom  = pAI->GetHOBJECT();
	weaponFireInfo.vPath       = vDir;
	weaponFireInfo.vFirePos    = vFirePos;
	weaponFireInfo.vFlashPos   = vFirePos;
	weaponFireInfo.hTestObj    = hTarget;
	weaponFireInfo.hFiringWeapon = m_pWeapon->GetModelObject();
	weaponFireInfo.nSeed		= (uint8)GetRandom( 2, 255 );
	weaponFireInfo.nPerturbCount = s_nCount;
	weaponFireInfo.nFireTimestamp = g_pLTServer->GetRealTimeMS( );
	weaponFireInfo.bLeftHandWeapon = ( LTStrIEquals( m_szFireSocketName.c_str( ), "LEFTHAND" ) );

	if( pAI->GetAIBlackBoard()->GetBBPerfectAccuracy() )
	{
		weaponFireInfo.fPerturb = 0.0f;
	}
	else 
	{
		weaponFireInfo.fPerturb = 1.f;
	}

	WeaponState eWeaponState = m_pWeapon->UpdateWeapon( weaponFireInfo, true );

	if( eWeaponState == W_FIRED )
	{
		UpdateWeaponAnimation( pAI );
	}

	if( m_pWeapon->GetAmmoInClip() == 0 )
	{
		// Automatically reload if:
		// 1) The AI has more ammo for this weapon and
		// 2) Either the AI is flagged to autoreload, or the weapon is flagged to not animation reloads.
		if( AIWeaponUtils::HasAmmo(pAI, m_pAIWeaponRecord->eAIWeaponType, !AIWEAP_CHECK_HOLSTER) 
			&& ( ( pAI->GetAIBlackBoard()->GetBBAutoReload() && m_pAIWeaponRecord->bAllowAutoReload ) || !bAnimatesReload) )
		{
			Reload(pAI);
		}
		else 
		{
			pAI->GetAIWorldState()->SetWSProp( kWSK_WeaponLoaded, pAI->GetHOBJECT(), kWST_bool, false );
		}
	}
	else 
	{
		pAI->GetAIWorldState()->SetWSProp( kWSK_WeaponLoaded, pAI->GetHOBJECT(), kWST_bool, true );
	}

	// If the primary weapon is now out of ammo, set the WeaponArmed 
	// worldstate to false.

	if( pAI->GetAIBlackBoard()->GetBBPrimaryWeaponType() == m_pAIWeaponRecord->eAIWeaponType
		&& !AIWeaponUtils::HasAmmo(pAI, m_pAIWeaponRecord->eAIWeaponType, !AIWEAP_CHECK_HOLSTER))
	{
		pAI->GetAIBlackBoard()->SetBBSelectAction(true);
	}

	return true;
}
Ejemplo n.º 2
0
bool CAIWeaponAbstract::DefaultThrow(CAI* pAI)
{
	// Make sure the basic pointers are valid.
	ASSERT(m_pWeapon);
	ASSERT(pAI);
	if (!pAI || !m_pWeapon || !m_pAIWeaponRecord)
	{
		return false;
	}

	// Don't fire if AI has no target.

	if( !pAI->HasTarget( kTarget_Character | kTarget_Object ) )
	{
		return false;
	}

	HOBJECT hTarget = pAI->GetAIBlackBoard()->GetBBTargetObject();

	// Throw at the last known position.

	LTVector vTargetPos;
	CAIWMFact factTargetQuery;
	factTargetQuery.SetFactType( kFact_Character );
	factTargetQuery.SetTargetObject( hTarget );
	CAIWMFact* pFact = pAI->GetAIWorkingMemory()->FindWMFact( factTargetQuery );
	if( pFact )
	{
		vTargetPos = pFact->GetPos();
	}
	else {
		g_pLTServer->GetObjectPos(hTarget, &vTargetPos);
	}


	// Offset the target pos a little so projectile lands in front of the target.

	LTVector vOffsetDir;
	vOffsetDir = pAI->GetPosition() - vTargetPos;
	vOffsetDir.y = 0.f;
	vOffsetDir.Normalize();
	vTargetPos += vOffsetDir * 384.f; 

	// Get our fire position

	LTVector vFirePos = GetFirePosition(pAI);

	// Velocity Vo

	LTVector vGravity;
	g_pPhysicsLT->GetGlobalForce( vGravity );

	// Vo = (S - R - 1/2*G*t^2) / t         
	// Vo = initial velocity
	// S = destination
	// R = origin
	// G = gravity
	// t = hangtime

	float fHangtime = 0.5f;
	LTVector vVelocity = ( vTargetPos - vFirePos - vGravity * .5f * fHangtime * fHangtime ) / fHangtime;
	float fVelocity = vVelocity.Mag();
	LTVector vDir( vVelocity / fVelocity );

	// Now fire the weapon

	WeaponFireInfo weaponFireInfo;
	static uint8 s_nCount = GetRandom( 0, 255 );
	s_nCount++;

	weaponFireInfo.hFiredFrom = pAI->GetHOBJECT();
	weaponFireInfo.vPath = vDir;
	weaponFireInfo.bOverrideVelocity = LTTRUE;
	weaponFireInfo.fOverrideVelocity = fVelocity;
	weaponFireInfo.vFirePos	= vFirePos;
	weaponFireInfo.vFlashPos = vFirePos;
	weaponFireInfo.hTestObj	= hTarget;
	weaponFireInfo.fPerturb = 1.0f * (1.0f - pAI->GetAccuracy() );
	weaponFireInfo.nSeed = (uint8)GetRandom( 2, 255 );
	weaponFireInfo.nPerturbCount = s_nCount;
	weaponFireInfo.nFireTimestamp = g_pLTServer->GetRealTimeMS( );

	m_pWeapon->ReloadClip( LTFALSE );

	if (m_pAIWeaponRecord->bAllowAmmoGeneration)
	{
		m_pWeapon->GetArsenal()->AddAmmo( m_pWeapon->GetAmmoRecord(), 999999 );
	}

	m_pWeapon->UpdateWeapon( weaponFireInfo, LTTRUE );

	return true;
}
//----------------------------------------------------------------------------
//              
//	ROUTINE:	CAIHumanStrategyShootStream::UpdateFiring()
//              
//	PURPOSE:	Updates the firing state, first allowing the base class to
//				handle the basics, then extending it to check the animation 
//				lock state for handling progression from eFireStateStart to 
//				eFireStateFiring.
//              
//----------------------------------------------------------------------------
/*virtual*/ void CAIHumanStrategyShootStream::UpdateFiring(HOBJECT hTarget,const LTVector& vTargetPos, CWeapon* pWeapon)
{
	AIASSERT( LTTRUE == m_bFired, GetAI()->GetHOBJECT(), "Expected Fired to be true.  Check logic.");

	switch ( m_eFireState )
	{
		case eFireStateStart:
		{
			if ( !GetAI()->GetAnimationContext()->IsLocked() )
			{
				m_eFireState = eFireStateFiring;
			}
		}
		break;

		case eFireStateFiring:
		{
			// Get our fire position

			AIASSERT( GetAI()->GetCurrentWeapon(), GetAI()->m_hObject, "UpdateFiring without a weapon" );
			LTVector vFirePos = GetFirePosition(GetAI()->GetCurrentWeapon());

			// Now fire the weapon

			WeaponFireInfo weaponFireInfo;

			weaponFireInfo.nDiscTrackingType = MPROJ_DISC_TRACKING_STEADY;
			weaponFireInfo.hSocket		= m_hFiringSocket!=INVALID_MODEL_SOCKET ? m_hFiringSocket : GetAI()->GetWeaponSocket(GetAI()->GetCurrentWeapon());
			weaponFireInfo.hFiredFrom  = GetAI()->GetObject();
			weaponFireInfo.vPath       = vTargetPos - vFirePos;
			weaponFireInfo.vFirePos    = vFirePos;
			weaponFireInfo.vFlashPos   = vFirePos;
			weaponFireInfo.hTestObj    = hTarget;
			weaponFireInfo.fPerturbR	= LOWER_BY_DIFFICULTY(s_fPerturbScale)*(1.0f - GetAI()->GetAccuracy());
			weaponFireInfo.fPerturbU	= LOWER_BY_DIFFICULTY(s_fPerturbScale)*(1.0f - GetAI()->GetAccuracy());

			pWeapon->UpdateWeapon(weaponFireInfo, LTTRUE);

			Fire();
			
			// Check to see our fire timer expired
			if ( m_flStreamTime < g_pLTServer->GetTime() || !GetAI()->GetAnimationContext()->IsLocked())
			{
				m_eFireState = eFireStateEnding;
			}
		}
		break;

		case eFireStateEnding:
		{
			if ( !GetAI()->GetAnimationContext()->IsLocked() )
			{
				m_eFireState = eFireStateInvalid;
				m_bFiringStream = LTFALSE;
				m_eState = eStateAiming;
				return;
			}
		}
		break;
	
		default:
		{
			AIASSERT( 0, m_pAIHuman->GetHOBJECT(), "CAIHumanStrategyShootStream::UpdateAnimation: Unexpected m_eFireState");
		}
		break;
	}
}