LTBOOL CAIGoalFollowFootprint::HandleGoalSenseTrigger(AISenseRecord* pSenseRecord) { if( super::HandleGoalSenseTrigger(pSenseRecord) ) { // Do not investigate without a weapon. CAIHuman* pAIHuman = (CAIHuman*)m_pAI; if( !( m_pAI->GetPrimaryWeapon() || pAIHuman->HasHolsterString() ) ) { return LTFALSE; } // Record whatever triggered this goal. m_vStimulusPos = pSenseRecord->vLastStimulusPos; m_fStimulationTime = pSenseRecord->fLastStimulationTime; m_pAI->Target(m_hStimulusSource); // Update the alarm level with this investigation. m_pAI->IncrementAlarmLevel( pSenseRecord->nLastStimulusAlarmLevel ); return LTTRUE; } return LTFALSE; }
HMODELANIM CAIGoalAbstractUseObject::GetAlternateDeathAnimation() { // Were killed in the middle of an activity? // jrg - 7/29/02 - don't count the activity if we haven't fully transitioned yet. if( ( m_pAI->GetState()->GetStateType() == kState_HumanUseObject ) && ( m_pAI->GetState()->GetStateStatus() == kSStat_PathComplete ) && (!m_pAI->GetAnimationContext()->IsTransitioning()) ) { CAIHumanStateUseObject* pStateUseObject = (CAIHumanStateUseObject*)m_pAI->GetState(); EnumAnimProp eActivity = pStateUseObject->GetActivity(); CAIHuman* pAIHuman = (CAIHuman*)m_pAI; CAnimationProps animProps; animProps.Set( kAPG_Posture, pStateUseObject->GetPose() ); animProps.Set( kAPG_Weapon, pAIHuman->GetCurrentWeaponProp() ); animProps.Set( kAPG_WeaponPosition, kAP_Lower ); animProps.Set( kAPG_Awareness, eActivity ); animProps.Set( kAPG_Action, kAP_Death ); // Find a death animation for this activity. if( m_pAI->GetAnimationContext()->AnimationExists( animProps )) { m_bPlayedSpecialDeathAnim = LTTRUE; return m_pAI->GetAnimationContext()->GetAni( animProps ); } } // No alternate. return INVALID_ANI; }
LTBOOL CAIGoalDrawWeapon::HandleDamage(const DamageStruct& damage) { super::HandleDamage( damage ); // Activate the goal. CAIHuman* pAIHuman = (CAIHuman*)m_pAI; if( pAIHuman->HasHolsterString() && !pAIHuman->GetPrimaryWeapon() ) { m_bRequiresImmediateResponse = LTTRUE; SetCurToBaseImportance(); } // HACK: for TO2 AI with grenades. else if( ( m_pAI->GetPrimaryWeaponType() == kAIWeap_Thrown ) && pAIHuman->HasHolsterString() ) { m_bRequiresImmediateResponse = LTTRUE; SetCurToBaseImportance(); } // END HACK // Always return false to allow normal damage handling. return LTFALSE; }
AINode* CAIGoalMenace::HandleGoalAttractors() { // Do not search for attractors if AI has no weapon. CAIHuman* pAIHuman = (CAIHuman*)m_pAI; if( ( !m_pAI->GetPrimaryWeapon() ) && ( !pAIHuman->HasHolsterString() ) ) { return LTNULL; } return super::HandleGoalAttractors(); }
void CAIGoalDisappearReappearEvasive::RecalcImportance() { // If we're unarmed, disappear and reappear with a weapon. CAIHuman* pAIHuman = (CAIHuman*)m_pAI; if( ( !m_pAI->GetPrimaryWeapon() ) && ( !pAIHuman->HasHolsterString() ) && m_pAI->HasBackupHolsterString() ) { m_bForceDisappear = LTTRUE; m_fNextUpdateTime = 0.f; SetCurToBaseImportance(); } }
void CAIGoalAbstractSearch::SetStateSearch() { // Reset default senses, except for SeeAllyDisturbance. m_pAI->SetCurSenseFlags( 0xffffffff & ~kSense_SeeAllyDisturbance ); // Cannot search without a weapon. CAIHuman* pAIHuman = (CAIHuman*)m_pAI; if( !pAIHuman->GetCurrentWeapon() ) { m_pGoalMgr->LockGoal(this); m_pAI->SetState( kState_HumanDraw ); return; } // Start searching. m_pAI->SetState( kState_HumanSearch ); if( IsCharacter( m_hStimulusSource ) ) { m_pAI->Target(m_hStimulusSource); } m_pGoalMgr->LockGoal(this); CAIHumanStateSearch* pSearchState = (CAIHumanStateSearch*)m_pAI->GetState(); if( pSearchState ) { pSearchState->SetPause(LTTRUE); pSearchState->SetEngage(m_bEngageSearch); pSearchState->SetFace(m_bFaceSearch); // If any optional search regions have been specified, search them. // Otherwise, search the AIs current region. if( !m_lstRegions.empty() ) { AIRegion* pRegion = (AIRegion*)g_pLTServer->HandleToObject( m_lstRegions.front() ); if( pRegion ) { AITRACE( AIShowGoals, ( m_pAI->m_hObject, "Searching region %s", pRegion->GetName() ) ); } pSearchState->SetDestRegion( m_lstRegions.front() ); m_lstRegions.erase( m_lstRegions.begin() ); } } }
void CAIGoalDisappearReappearEvasive::HandleStateDisappearReappear() { // Always reappear with a weapon. CAIHuman* pAIHuman = (CAIHuman*)m_pAI; if( ( m_pAI->GetState()->GetStateStatus() == kSStat_Moving ) && ( !m_pAI->GetPrimaryWeapon() ) && ( !pAIHuman->HasHolsterString() ) && m_pAI->HasBackupHolsterString() ) { m_pAI->SetHolsterString( m_pAI->GetBackupHolsterString() ); } super::HandleStateDisappearReappear(); }
LTBOOL CAIGoalRespondToBackup::HandleGoalSenseTrigger(AISenseRecord* pSenseRecord) { if(super::HandleGoalSenseTrigger(pSenseRecord)) { // Do not respond without a weapon. CAIHuman* pAIHuman = (CAIHuman*)m_pAI; if( !( m_pAI->GetPrimaryWeapon() || pAIHuman->HasHolsterString() ) ) { return LTFALSE; } // Reset the response counter if the enemy is actually seen. if( pSenseRecord->eSenseType == kSense_SeeEnemy ) { m_cResponses = 0; m_fCurImportance = 0.f; if( m_hNodeBackup ) { m_hNodeBackup = LTNULL; m_pAI->ResetBaseSenseFlags(); m_bRequiresUpdates = LTFALSE; } } else if( !m_pGoalMgr->IsCurGoal( this ) ) { m_hNodeBackup = pSenseRecord->hLastStimulusTarget; AINodeBackup* pNodeBackup = (AINodeBackup*)g_pLTServer->HandleToObject( m_hNodeBackup ); if( pNodeBackup ) { m_cArrivalCount = pNodeBackup->GetArrivalCount(); } m_pAI->SetCurSenseFlags( kSense_SeeEnemy | kSense_SeeDangerousProjectile | kSense_SeeCatchableProjectile ); m_bRequiresUpdates = LTTRUE; } } // Always return false. Only activate once the backup node is unlocked. return LTFALSE; }
AINode* CAIGoalAttackProp::HandleGoalAttractors() { // Check if already attacking a prop. if( m_pAI->GetState()->GetStateType() != kState_HumanAttackProp ) { CAIHuman* pAIHuman = (CAIHuman*)m_pAI; if( pAIHuman->HasHolsterString() || pAIHuman->GetPrimaryWeapon()) { AIGBM_GoalTemplate* pTemplate = g_pAIGoalButeMgr->GetTemplate( GetGoalType() ); AIASSERT(pTemplate->cAttractors > 0, m_pAI->m_hObject, "CAIGoalAbstract::HandleGoalAttractors: Goal has no attractors."); // Check if attractors are triggering activateability. AINode* pNode; for(uint32 iAttractor=0; iAttractor < pTemplate->cAttractors; ++iAttractor) { pNode = g_pAINodeMgr->FindNearestNodeInRadius(m_pAI, pTemplate->aAttractors[iAttractor], m_pAI->GetPosition(), pTemplate->fAttractorDistSqr * m_fBaseImportance, LTTRUE); if(pNode != LTNULL) { HOBJECT hObject; if ( LT_OK == FindNamedObject(pNode->GetObject(), hObject) ) { Prop* pProp = (Prop*)g_pLTServer->HandleToObject(hObject); if(pProp->GetState() != kState_PropDestroyed) { AIASSERT(pNode->GetType() == kNode_UseObject, m_pAI->m_hObject, "CAIGoalAttackProp::HandleGoalAttractors: AINode is not of type UseObject."); m_hNode = pNode->m_hObject; SetCurToBaseImportance(); return pNode; } } // Disable node if prop has been destroyed. pNode->Disable(); } } } m_hNode = LTNULL; } return LTNULL; }
LTBOOL CAIGoalDistress::HandleGoalSenseTrigger(AISenseRecord* pSenseRecord) { if( super::HandleGoalSenseTrigger(pSenseRecord) ) { // Do not distress if we are armed. CAIHuman* pAIHuman = (CAIHuman*)m_pAI; if( m_pAI->GetPrimaryWeapon() || pAIHuman->HasHolsterString() ) { return LTFALSE; } // Only distress if see a character with a dangerous weapon aimed at me. m_pAI->Target( m_hStimulusSource ); if( m_pAI->GetBrain()->TargetIsAimingAtMe() ) { return LTTRUE; } } return LTFALSE; }
LTBOOL CAIGoalDrawWeapon::HandleGoalSenseTrigger(AISenseRecord* pSenseRecord) { if( super::HandleGoalSenseTrigger(pSenseRecord) ) { CAIHuman* pAIHuman = (CAIHuman*)m_pAI; if( pAIHuman->HasHolsterString() && !pAIHuman->GetPrimaryWeapon() ) { return LTTRUE; } // HACK: for TO2 AI with grenades. if( ( m_pAI->GetPrimaryWeaponType() == kAIWeap_Thrown ) && pAIHuman->HasHolsterString() ) { return LTTRUE; } // END HACK } return LTFALSE; }
void CNudge::Update(LTBOOL bMoving) { m_eState = eStateNoNudge; // If we're moving or high priority, then we don't need to worry about nudging if ( bMoving || (m_ePriority == ePriorityHigh) ) { return; } LTVector vPos = m_pAI->GetPosition(); LTFLOAT fRadius = m_pAI->GetRadius(); /* // If we're not inside our volume, don't nudge if ( !m_pAI->GetLastVolume() || !m_pAI->GetLastVolume()->Inside2d(vPos, fRadius) ) { return; } */ HOBJECT hPlayer = LTNULL; CAIHuman* apAIs[64]; uint32 cAIs = 0; static HCLASS hClass = g_pLTServer->GetClass("CAIHuman"); ObjectList* pObjectList = g_pLTServer->FindObjectsTouchingSphere(&vPos, fRadius); ObjectLink* pObject = pObjectList ? pObjectList->m_pFirstLink : LTNULL; while ( pObject && cAIs < 64 ) { HOBJECT hObject = pObject->m_hObject; if ( hObject != m_pAI->m_hObject ) { if ( IsPlayer(hObject) ) { hPlayer = hObject; } else if ( g_pLTServer->IsKindOf(g_pLTServer->GetObjectClass(hObject), hClass) ) { apAIs[cAIs++] = (CAIHuman*)g_pLTServer->HandleToObject(hObject); } } pObject = pObject->m_pNext; } if ( pObjectList ) { g_pLTServer->RelinquishList(pObjectList); } if ( cAIs == 0 ) return; m_eState = eStateNudge; m_vNudge = LTVector(0,0,0); if ( hPlayer ) { LTVector vPlayerPosition; g_pLTServer->GetObjectPos(hPlayer, &vPlayerPosition); LTVector vNudgeDir = m_pAI->GetPosition()-vPlayerPosition; vNudgeDir.y = 0.0f; vNudgeDir.Norm(); m_vNudge += vNudgeDir*64.0f*g_pLTServer->GetFrameTime(); } for ( uint32 iAI = 0 ; iAI < cAIs ; iAI++ ) { CAIHuman* pAI = apAIs[iAI]; CNudge* pNudge = pAI->GetNudge(); LTVector vNudgeDir; LTFLOAT fNudgeAmount; if ( pNudge->GetPriority() == ePriorityLow ) { fNudgeAmount = 24.0f; vNudgeDir = m_pAI->GetPosition()-pAI->GetPosition(); vNudgeDir.y = 0.0f; vNudgeDir.Norm(); } else // if ( pNudge->GetPriority() == ePriorityHigh ) { fNudgeAmount = 48.0f; vNudgeDir = m_pAI->GetPosition()-pAI->GetPosition(); vNudgeDir.y = 0.0f; vNudgeDir.Norm(); } m_vNudge += vNudgeDir*fNudgeAmount*g_pLTServer->GetFrameTime(); } _ASSERT((LTFLOAT)fabs(m_vNudge.y < MATH_EPSILON)); }