IAIObject* CTacticalPointLanguageExtender::GetBattleFrontObject() const { IAIObjectManager* pAIObjMgr = gEnv->pAISystem->GetAIObjectManager(); IAIObject *pObj = pAIObjMgr->GetAIObject(m_battlefrontAIObject); if (!pObj) { // Not created or has been removed (by reset, etc), so create one ITacticalPointSystem& tacticalPointSystem = *gEnv->pAISystem->GetTacticalPointSystem(); pObj = tacticalPointSystem.CreateExtenderDummyObject("Game_BattleFront"); assert(pObj); m_battlefrontAIObject = pObj ? pObj->GetAIObjectID() : 0; } return pObj; }
//------------------------------------------------------------------------ int CMelee::Hit(const Vec3 &pt, const Vec3 &dir, const Vec3 &normal, IPhysicalEntity *pCollider, EntityId collidedEntityId, int partId, int ipart, int surfaceIdx, bool remote) { MeleeDebugLog ("CMelee<%p> HitPointDirNormal(remote=%s)", this, remote ? "true" : "false"); int hitTypeID = 0; CActor *pOwnerActor = m_pWeapon->GetOwnerActor(); if (pOwnerActor) { IActor* pTargetActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(collidedEntityId); IEntity* pTarget = pTargetActor ? pTargetActor->GetEntity() : gEnv->pEntitySystem->GetEntity(collidedEntityId); IEntity* pOwnerEntity = pOwnerActor->GetEntity(); IAIObject* pOwnerAI = pOwnerEntity->GetAI(); float damageScale = 1.0f; bool silentHit = false; if(pTargetActor) { IAnimatedCharacter* pTargetAC = pTargetActor->GetAnimatedCharacter(); IAnimatedCharacter* pOwnerAC = pOwnerActor->GetAnimatedCharacter(); if(pTargetAC && pOwnerAC) { Vec3 targetFacing(pTargetAC->GetAnimLocation().GetColumn1()); Vec3 ownerFacing(pOwnerAC->GetAnimLocation().GetColumn1()); float ownerFacingDot = ownerFacing.Dot(targetFacing); float fromBehindDot = cos_tpl(DEG2RAD(g_pGameCVars->pl_melee.angle_limit_from_behind)); if(ownerFacingDot > fromBehindDot) { #ifndef _RELEASE if (g_pGameCVars->g_LogDamage) { CryLog ("[DAMAGE] %s '%s' is%s meleeing %s '%s' from behind (because %f > %f)", pOwnerActor->GetEntity()->GetClass()->GetName(), pOwnerActor->GetEntity()->GetName(), silentHit ? " silently" : "", pTargetActor->GetEntity()->GetClass()->GetName(), pTargetActor->GetEntity()->GetName(), ownerFacingDot, fromBehindDot); } #endif damageScale *= g_pGameCVars->pl_melee.damage_multiplier_from_behind; } } } // Send target stimuli if (!gEnv->bMultiplayer) { IAISystem *pAISystem = gEnv->pAISystem; ITargetTrackManager *pTargetTrackManager = pAISystem ? pAISystem->GetTargetTrackManager() : NULL; if (pTargetTrackManager && pOwnerAI) { IAIObject *pTargetAI = pTarget ? pTarget->GetAI() : NULL; if (pTargetAI) { const tAIObjectID aiOwnerId = pOwnerAI->GetAIObjectID(); const tAIObjectID aiTargetId = pTargetAI->GetAIObjectID(); TargetTrackHelpers::SStimulusEvent eventInfo; eventInfo.vPos = pt; eventInfo.eStimulusType = TargetTrackHelpers::eEST_Generic; eventInfo.eTargetThreat = AITHREAT_AGGRESSIVE; pTargetTrackManager->HandleStimulusEventForAgent(aiTargetId, aiOwnerId, "MeleeHit",eventInfo); pTargetTrackManager->HandleStimulusEventInRange(aiOwnerId, "MeleeHitNear", eventInfo, 5.0f); } } } //Check if is a friendly hit, in that case FX and Hit will be skipped bool isFriendlyHit = (pOwnerEntity && pTarget) ? IsFriendlyHit(pOwnerEntity, pTarget) : false; if(!isFriendlyHit) { CPlayer * pAttackerPlayer = pOwnerActor->IsPlayer() ? static_cast<CPlayer*>(pOwnerActor) : NULL; float damage = m_pMeleeParams->meleeparams.damage_ai; if(pOwnerActor->IsPlayer()) { damage = m_slideKick ? m_pMeleeParams->meleeparams.slide_damage : GetMeleeDamage(); } #ifndef _RELEASE if (pTargetActor && g_pGameCVars->g_LogDamage) { CryLog ("[DAMAGE] %s '%s' is%s meleeing %s '%s' applying damage = %.3f x %.3f = %.3f", pOwnerActor->GetEntity()->GetClass()->GetName(), pOwnerActor->GetEntity()->GetName(), silentHit ? " silently" : "", pTargetActor->GetEntity()->GetClass()->GetName(), pTargetActor->GetEntity()->GetName(), damage, damageScale, damage * damageScale); } #endif //Generate Hit if(pTarget) { CGameRules *pGameRules = g_pGame->GetGameRules(); CRY_ASSERT_MESSAGE(pGameRules, "No game rules! Melee can not apply hit damage"); if (pGameRules) { hitTypeID = silentHit ? CGameRules::EHitType::SilentMelee : m_hitTypeID; HitInfo info(m_pWeapon->GetOwnerId(), pTarget->GetId(), m_pWeapon->GetEntityId(), damage * damageScale, 0.0f, surfaceIdx, partId, hitTypeID, pt, dir, normal); if (m_pMeleeParams->meleeparams.knockdown_chance>0 && Random(100) < m_pMeleeParams->meleeparams.knockdown_chance) info.knocksDown = true; info.remote = remote; pGameRules->ClientHit(info); } if (pAttackerPlayer && pAttackerPlayer->IsClient()) { const Vec3 posOffset = (pt - pTarget->GetWorldPos()); SMeleeHitParams params; params.m_boostedMelee = false; params.m_hitNormal = normal; params.m_hitOffset = posOffset; params.m_surfaceIdx = surfaceIdx; params.m_targetId = pTarget->GetId(); pAttackerPlayer->OnMeleeHit(params); } } else { //Play Material FX PlayHitMaterialEffect(pt, normal, false, surfaceIdx); } } if (pTarget) { CActor *pCTargetActor = static_cast<CActor*>(pTargetActor); CPlayer* pTargetPlayer = (pTargetActor && pTargetActor->IsPlayer()) ? static_cast<CPlayer*>(pTargetActor) : NULL; if(pTargetPlayer && pTargetPlayer->IsClient()) { if(m_pMeleeParams->meleeparams.trigger_client_reaction) { pTargetPlayer->TriggerMeleeReaction(); } } } } return hitTypeID; }