void CAIBrain::Init(CAIHuman* pAIHuman, const char* szName) { m_pAIHuman = pAIHuman; strcpy(m_szName, szName); int32 iBrain = g_pAIButeMgr->GetBrainIDByName(szName); if ( -1 != iBrain ) { m_pBrain = g_pAIButeMgr->GetBrain(iBrain); } else { g_pLTServer->CPrint("DANGER!!!! AI had no brain, but settled for default!!!!"); m_pBrain = g_pAIButeMgr->GetBrain(0); } if ( !m_pBrain ) { g_pLTServer->CPrint("DANGER!!!! AI has no brain!!!!"); return; } m_eDodgeStatusLast = eDodgeStatusOk; m_fDodgeStatusCheckTimeVector = g_pLTServer->GetTime() + LOWER_BY_DIFFICULTY(m_pBrain->fDodgeVectorCheckTime); m_fDodgeStatusCheckTimeProjectile = g_pLTServer->GetTime() + LOWER_BY_DIFFICULTY(m_pBrain->fDodgeProjectileCheckTime); m_fGrenadeStatusCheckTime = g_pLTServer->GetTime() + LOWER_BY_DIFFICULTY(m_pBrain->fAttackGrenadeThrowTime); }
void CAIActionAttackGrenade::SetNextThrowTime( CAI* pAI ) { // Coordinate frequency of grenade attacks across all AIs. if( !pAI->HasTarget( kTarget_Character | kTarget_Object ) ) { return; } float fDelay = GetRandom( pAI->GetBrain()->GetAttackGrenadeThrowTimeMin(), pAI->GetBrain()->GetAttackGrenadeThrowTimeMax() ); double fTime = g_pLTServer->GetTime() + LOWER_BY_DIFFICULTY( fDelay ); AITRACE( AIShowGoals, ( pAI->m_hObject, "NOW: %.2f NEXT: %.2f", g_pLTServer->GetTime(), fTime ) ); // Update the global fact tracking grenade throwing frequency, or create // it if it does not yet exist. CAIWMFact factQuery; factQuery.SetFactType(kFact_Knowledge); factQuery.SetKnowledgeType(kKnowledge_NextGrenadeTime); CAIWMFact* pFact = g_pAIWorkingMemoryCentral->FindWMFact(factQuery); if (!pFact) { pFact = g_pAIWorkingMemoryCentral->CreateWMFact(kFact_Knowledge); pFact->SetKnowledgeType( kKnowledge_NextGrenadeTime, 1.f ); } if (pFact) { pFact->SetTime( fTime ); } }
GrenadeStatus CAIBrain::GetGrenadeStatus() { if ( g_pLTServer->GetTime() >= m_fGrenadeStatusCheckTime ) { m_fGrenadeStatusCheckTime = g_pLTServer->GetTime() + LOWER_BY_DIFFICULTY(m_pBrain->fAttackGrenadeThrowTime); if ( GetRandom(0.0f, 1.0f) <= RAISE_BY_DIFFICULTY(m_pBrain->fAttackGrenadeThrowChance) ) { LTFLOAT fRangeMinSqr = m_pBrain->fAttackProjectileRangeMin*m_pBrain->fAttackProjectileRangeMin; LTFLOAT fRangeMaxSqr = m_pBrain->fAttackProjectileRangeMax*m_pBrain->fAttackProjectileRangeMax; LTFLOAT fDistanceSqr = GetAI()->GetPosition().DistSqr(GetAI()->GetTarget()->GetPosition()); if ( (fDistanceSqr > fRangeMinSqr) && (fDistanceSqr < fRangeMaxSqr) ) { return eGrenadeStatusThrow; } } } return eGrenadeStatusDontThrow; }
void CAIBrain::GetDodgeStatus(DodgeStatus* peDodgeStatus, Direction* peDirection, DodgeAction* peDodgeAction, uint32* pdwNode) { if ( !GetAI()->HasTarget() || !GetAI()->HasLastVolume() ) { *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusOk; return; } if ( g_pLTServer->GetTime() >= m_fDodgeStatusCheckTimeVector ) { m_fDodgeStatusCheckTimeVector = g_pLTServer->GetTime() + LOWER_BY_DIFFICULTY(m_pBrain->fDodgeVectorCheckTime); if ( GetRandom(0.0f, 1.0f) <= RAISE_BY_DIFFICULTY(m_pBrain->fDodgeVectorCheckChance) ) { if ( GetAI()->GetTarget()->IsVisiblePartially() ) { CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(GetAI()->GetTarget()->GetObject()); if ( pCharacter->HasDangerousWeapon() ) { LTRotation rRot; LTVector vNull, vForward; g_pLTServer->GetObjectRotation(GetAI()->GetTarget()->GetObject(), &rRot); g_pMathLT->GetRotationVectors(rRot, vNull, vNull, vForward); LTVector vDir; vDir = GetAI()->GetPosition() - GetAI()->GetTarget()->GetPosition(); vDir.y = 0; vDir.Norm(); // TODO: bute this const static LTFLOAT fThreshhold = 0.95f; if ( (vDir.Dot(vForward) > fThreshhold) && (GetAI()->GetForwardVector().Dot(vForward) < -fThreshhold) ) { LTFLOAT fCheckDistance; LTFLOAT fRandom = GetRandom(0.0f, 1.0f); if ( fRandom > m_pBrain->fDodgeVectorCoverChance ) { if ( fRandom > (m_pBrain->fDodgeVectorCoverChance + m_pBrain->fDodgeVectorRollChance) ) { *peDodgeAction = eDodgeActionShuffle; fCheckDistance = 109.0f; } else { *peDodgeAction = eDodgeActionRoll; fCheckDistance = 140.0f; } // MAKE SURE WE WON'T DODGE OUT OF THE VOLUME if ( GetAI()->GetLastVolume()->Inside2d(GetAI()->GetPosition()+GetAI()->GetRightVector()*fCheckDistance, GetAI()->GetRadius()) ) { *peDirection = eDirectionRight; *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusVector; return; } else if ( GetAI()->GetLastVolume()->Inside2d(GetAI()->GetPosition()-GetAI()->GetRightVector()*fCheckDistance, GetAI()->GetRadius()) ) { *peDirection = eDirectionLeft; *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusVector; return; } else { *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusOk; return; } } else { CAINode* pNode = g_pAINodeMgr->FindNearestCoverFromThreat(GetAI()->GetPosition(), GetAI()->GetTarget()->GetObject()); if ( pNode ) { *peDodgeAction = eDodgeActionCover; *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusVector; *pdwNode = pNode->GetID(); } else { *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusOk; } return; } } } } } } if ( g_pLTServer->GetTime() >= m_fDodgeStatusCheckTimeProjectile ) { m_fDodgeStatusCheckTimeProjectile = g_pLTServer->GetTime() + RAISE_BY_DIFFICULTY(m_pBrain->fDodgeProjectileCheckTime); if ( GetRandom(0.0f, 1.0f) <= RAISE_BY_DIFFICULTY(m_pBrain->fDodgeProjectileCheckChance) ) { CGrenade* pGrenade; if ( FindGrenadeDangerPosition(GetAI()->GetPosition(), 40000.0f, &m_vDodgeProjectilePosition, &pGrenade) ) { FREE_HSTRING(m_hstrDodgeProjectileName); // $STRING m_hstrDodgeProjectileName = g_pLTServer->CreateString(g_pLTServer->GetObjectName(pGrenade->m_hObject)); *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusProjectile; *peDodgeAction = eDodgeActionFlee; return; } } } *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusOk; return; }
void CAIBrain::DodgeDelay() { m_fDodgeStatusCheckTimeVector = g_pLTServer->GetTime() + LOWER_BY_DIFFICULTY(m_pBrain->fDodgeVectorDelayTime); m_fDodgeStatusCheckTimeProjectile = g_pLTServer->GetTime() + LOWER_BY_DIFFICULTY(m_pBrain->fDodgeProjectileDelayTime); }
//---------------------------------------------------------------------------- // // 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; } }