void CDestructibleModel::RegisterDestroyedStimulus() { // Register audio and visual stimulus if specified. if( (m_nDestroyAlarmLevel > 0) && (m_fStimRadius > 0.f) ) { LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); // Extract who caused an explosion. HOBJECT hDamager = m_hLastDamager; if( IsExplosion( hDamager ) ) { Explosion* pExplosion = (Explosion*)g_pLTServer->HandleToObject(m_hLastDamager); hDamager = pExplosion->GetFiredFrom(); } // If damager is still not a character (possibly because an explosion was triggered), assume player. // Better solution - set the alignment of the damager on the explosion? if( !IsCharacter( hDamager ) ) { CPlayerObj *pPlayer = g_pCharacterMgr->FindPlayer(); if ( pPlayer ) { hDamager = pPlayer->m_hObject; } } if ( IsCharacter(hDamager) ) { CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(hDamager); if ( pCharacter ) { // Register the disturbance sound. StimulusRecordCreateStruct DisturbanceSoundSCS( kStim_DisturbanceSound, pCharacter->GetAlignment(), vPos, hDamager ); DisturbanceSoundSCS.m_hStimulusTarget = m_hObject; DisturbanceSoundSCS.m_flAlarmScalar = (float)m_nDestroyAlarmLevel; DisturbanceSoundSCS.m_flRadiusScalar = m_fStimRadius; g_pAIStimulusMgr->RegisterStimulus( DisturbanceSoundSCS ); // Register the visible disturbance. StimulusRecordCreateStruct DisturbanceVisibleSCS( kStim_DisturbanceVisible, pCharacter->GetAlignment(), vPos, hDamager ); DisturbanceVisibleSCS.m_hStimulusTarget = m_hObject; DisturbanceVisibleSCS.m_flAlarmScalar = (float)(m_nDestroyAlarmLevel + 1); DisturbanceVisibleSCS.m_flRadiusScalar = m_fStimRadius; m_eStimID = g_pAIStimulusMgr->RegisterStimulus( DisturbanceVisibleSCS ); } } } }
void CAIActionReactToDanger::ActivateAction( CAI* pAI, CAIWorldState& wsWorldStateGoal ) { super::ActivateAction( pAI, wsWorldStateGoal ); // Bail if we are not aware of danger. CAIWMFact factQuery; factQuery.SetFactType( kFact_Danger ); CAIWMFact* pFact = pAI->GetAIWorkingMemory()->FindWMFact( factQuery ); if( !pFact ) { return; } // Set animate state. pAI->SetState( kState_Animate ); // Set flinch animation. CAnimationProps animProps; animProps.Set( kAPG_Posture, kAP_POS_Crouch ); animProps.Set( kAPG_Weapon, pAI->GetAIBlackBoard()->GetBBPrimaryWeaponProp() ); animProps.Set( kAPG_WeaponPosition, kAP_WPOS_Up ); animProps.Set( kAPG_Activity, kAP_ATVT_Distress ); animProps.Set( kAPG_Action, kAP_ACT_Idle ); CAIStateAnimate* pStateAnimate = (CAIStateAnimate*)( pAI->GetState() ); pStateAnimate->SetAnimation( animProps, !LOOP ); // Do NOT play a threat sound if threatened by a Turret. // Instead, allow turret targeting to play something appropriate. if( IsPlayer( pFact->GetSourceObject() ) ) { CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject( pFact->GetSourceObject() ); if( pPlayer && pPlayer->GetTurret() ) { return; } } // Play threat sound. // "Fire!" if( IsAINode( pFact->GetSourceObject() ) ) { EnumAISoundType eAISound = kAIS_Danger; AINode* pNode = (AINode*)g_pLTServer->HandleToObject( pFact->GetSourceObject() ); if( pNode && pNode->GetType() == kNode_Stimulus ) { AINodeStimulus* pNodeStim = (AINodeStimulus*)pNode; if( pNodeStim ) { eAISound = pNodeStim->GetAISoundType(); } } g_pAISoundMgr->RequestAISound( pAI->m_hObject, eAISound, kAISndCat_Event, NULL, 0.f ); } // "Watch out grenade!" // "Shit!" else if( IsKindOf( pFact->GetSourceObject(), "CProjectile" ) ) { // Don't say anything if ally threw grenade. CProjectile* pProjectile = (CProjectile*)g_pLTServer->HandleToObject( pFact->GetSourceObject() ); if( pProjectile && IsCharacter( pProjectile->GetFiredFrom() ) ) { CCharacter *pChar = (CCharacter*)g_pLTServer->HandleToObject( pProjectile->GetFiredFrom() ); if( pChar && kCharStance_Like != g_pCharacterDB->GetStance( pAI->GetAlignment(), pChar->GetAlignment() ) ) { ENUM_AI_SQUAD_ID eSquad = g_pAICoordinator->GetSquadID( pAI->m_hObject ); CAISquad* pSquad = g_pAICoordinator->FindSquad( eSquad ); if( pSquad && pSquad->GetNumSquadMembers() > 1 ) { g_pAISoundMgr->RequestAISound( pAI->m_hObject, kAIS_GrenadeThreat, kAISndCat_Event, NULL, 0.f ); } else { g_pAISoundMgr->RequestAISound( pAI->m_hObject, kAIS_GrenadeThreatAlone, kAISndCat_Event, NULL, 0.f ); } } } } // "Shit" else { g_pAISoundMgr->RequestAISound( pAI->m_hObject, kAIS_GrenadeThreatAlone, kAISndCat_Event, NULL, 0.f ); } // Search for the source of the danger. LTVector vDangerPos = pFact->GetPos(); SearchForDangerOrigin( pAI, vDangerPos ); }