void CProjectile::HandleTouch(HOBJECT hObj) { if (m_bObjectRemoved) return; // Don't process any touches until this has been cleared... if (m_bProcessInvImpact) return; // Let it get out of our bounding box... if (hObj == m_hFiredFrom) return; CCharacterHitBox* pHitBox = LTNULL; // If we've hit a character (or body), let its hit box take control... if (IsCharacter(hObj)) { CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hObj); if (pChar) { hObj = pChar->GetHitBox(); } } else if (IsBody(hObj)) { Body* pBody = (Body*)g_pLTServer->HandleToObject(hObj); if (pBody) { hObj = pBody->GetHitBox(); } } if (IsCharacterHitBox(hObj)) { pHitBox = (CCharacterHitBox*)g_pLTServer->HandleToObject(hObj); if (!pHitBox) return; if (pHitBox->GetModelObject() == m_hFiredFrom) return; } // Don't hit our own type of projectiles (for multi-projectile weapons // and projectiles that stick to objects)... if (IsKindOf(hObj, m_hObject)) { CProjectile* pObj = (CProjectile*)g_pLTServer->HandleToObject(hObj); if (pObj) { if (pObj->GetFiredFrom() == m_hFiredFrom) { return; } } } // See if we want to impact on this object... uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(hObj); if (dwUsrFlags & USRFLG_IGNORE_PROJECTILES) return; LTBOOL bIsWorld = IsMainWorld(hObj); // Don't impact on non-solid objects...unless it is a CharacterHitBox // object... uint32 dwFlags = g_pLTServer->GetObjectFlags(hObj); if (!bIsWorld && !(dwFlags & FLAG_SOLID)) { if (pHitBox) { // See if we really impacted on the box... if (pHitBox->DidProjectileImpact(this)) { // This is the object that we really hit... hObj = pHitBox->GetModelObject(); } else { return; } } else if (!(dwFlags & FLAG_RAYHIT)) { // If we have ray hit set to true, projectiles should // impact on us too... return; } } // See if we hit the sky... if (bIsWorld || (OT_WORLDMODEL == g_pLTServer->GetObjectType(hObj))) { CollisionInfo info; g_pLTServer->GetLastCollision(&info); SurfaceType eType = GetSurfaceType(info); if (eType == ST_SKY) { RemoveObject(); return; } else if (eType == ST_INVISIBLE) { // Update 1.002 [KLS] - If multiplayer and we hit an invisible // surface, just treat it like a normal surface... if (!IsMultiplayerGame()) { m_bProcessInvImpact = LTTRUE; g_pLTServer->GetObjectPos(m_hObject, &m_vInvisNewPos); g_pLTServer->GetVelocity(m_hObject, &m_vInvisVel); m_vInvisNewPos += (m_vInvisVel * g_pLTServer->GetFrameTime()); // Make sure this new position is inside the world...else // just blow up... if (LT_INSIDE == g_pLTServer->Common()->GetPointStatus(&m_vInvisNewPos)) { return; } } } } HandleImpact(hObj); }
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 ); }