//----------------------------------------------------------------------- bool CSpectacularKill::CanExecuteOnTarget(const CActor* pTarget, const SSpectacularKillAnimation& anim) const { CRY_ASSERT(pTarget); // can't spectacular kill actors in vehicles if(pTarget->GetLinkedVehicle()) return false; // can't spectacular kill when in a hit/death reaction if (pTarget->GetActorClass() == CPlayer::GetActorClassType()) { CHitDeathReactionsConstPtr pHitDeathReactions = static_cast<const CPlayer*>(pTarget)->GetHitDeathReactions(); if (pHitDeathReactions && pHitDeathReactions->IsInReaction() && pHitDeathReactions->AreReactionsForbidden()) { SK_DEBUG_LOG("Can't start from %s to %s: the target is playing an uninterruptible hit/death reaction", m_pOwner->GetEntity()->GetName(), pTarget->GetEntity()->GetName()); return false; } } if (!CanSpectacularKillOn(pTarget)) return false; // Can't start if they are taking part on other cooperative animation ICooperativeAnimationManager* pCooperativeAnimationManager = gEnv->pGame->GetIGameFramework()->GetICooperativeAnimationManager(); if (pCooperativeAnimationManager->IsActorBusy(m_pOwner->GetEntityId()) || pCooperativeAnimationManager->IsActorBusy(m_targetId)) { SK_DEBUG_LOG("Can't start from %s to %s: some of them are taking part in a cooperative animation already", m_pOwner->GetEntity()->GetName(), pTarget->GetEntity()->GetName()); return false; } const Vec3 vKillerPos = m_pOwner->GetEntity()->GetWorldPos(); const Vec3 vTargetPos = pTarget->GetEntity()->GetWorldPos(); // The height distance between killer and victim needs to be acceptably small (simple check for terrain flatness) // [11/08/2010 davidr] ToDo: Use deferred primitive world intersection checks with asset-dependant dimensions for height // and obstacles detection if (fabs_tpl(vKillerPos.z - vTargetPos.z) > g_pGameCVars->g_spectacularKill.maxHeightBetweenActors) { SK_DEBUG_LOG("Can't start from %s to %s: Ground between killer and target is not flat (height distance is %f)", m_pOwner->GetEntity()->GetName(), pTarget->GetEntity()->GetName(), fabs_tpl(vKillerPos.z - vTargetPos.z)); return false; } // Obstacle check if (ObstacleCheck(vKillerPos, vTargetPos, anim)) { SK_DEBUG_LOG("Can't start from %s to %s: Obstacles have been found between the actors", m_pOwner->GetEntity()->GetName(), pTarget->GetEntity()->GetName()); return false; } return true; }
//------------------------------------------------------------------------ void CGameRules::KnockActorDown( EntityId actorEntityId ) { // Forbid fall and play if the actor is playing a hit/death reaction CActor* pHitActor = static_cast<CActor*>(gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor( actorEntityId )); if (pHitActor) { if (pHitActor->GetActorClass() == CPlayer::GetActorClassType()) { // Don't trigger Fall and Play if the actor is playing a hit reaction CPlayer* pHitPlayer = static_cast<CPlayer*>(pHitActor); CHitDeathReactionsConstPtr pHitDeathReactions = pHitPlayer->GetHitDeathReactions(); if (!pHitDeathReactions || !pHitDeathReactions->IsInReaction()) pHitActor->Fall(); } else pHitActor->Fall(); } }