bool CSmokeManager::IsPointInSmoke(const Vec3& vPos, float& outInsideFactor) const { const int kNumActiveSmokeInstances = m_numActiveSmokeInstances; PrefetchLine(m_smokeInstances, 0); PrefetchLine(m_smokeInstances, 128); outInsideFactor = 0.0f; for(int i = 0; i < kNumActiveSmokeInstances; i++) { const SSmokeInstance& smokeInstance = m_smokeInstances[i]; PrefetchLine(&smokeInstance, 128); const float fDistanceSq = Distance::Point_PointSq(vPos, smokeInstance.vPositon); const float fCurrentRadiusSq = sqr(smokeInstance.fCurrentRadius); if(fDistanceSq < fCurrentRadiusSq) { outInsideFactor = 1.0f - ((float)cry_sqrtf_fast(fDistanceSq) * (float)__fres(cry_sqrtf_fast(fCurrentRadiusSq))); return true; } } return false; }
//------------------------------------------------------------------------ void CGameRules::ServerHit(const HitInfo &hitInfo) { HitInfo info(hitInfo); if (IItem *pItem=gEnv->pGame->GetIGameFramework()->GetIItemSystem()->GetItem(info.weaponId)) { if (CWeapon *pWeapon=static_cast<CWeapon *>(pItem->GetIWeapon())) { float distance=0.0f; if (IEntity *pEntity=gEnv->pEntitySystem->GetEntity(info.shooterId?info.shooterId:info.weaponId)) { distance=(pEntity->GetWorldPos()-info.pos).len2(); if (distance>0.0f) distance=cry_sqrtf_fast(distance); } info.damage=pWeapon->GetDamage(info.fmId, distance); if (info.type!=GetHitTypeId(pWeapon->GetDamageType(info.fmId))) { info.damage=0; } } } if (m_processingHit) { m_queuedHits.push(info); return; } ++m_processingHit; ProcessServerHit(info); while (!m_queuedHits.empty()) { HitInfo qinfo(m_queuedHits.front()); ProcessServerHit(qinfo); m_queuedHits.pop(); } --m_processingHit; }
//--------------------------------------------------------------------------- IEntity* CFireModePlugin_AutoAim::CalculateBestProjectileAutoAimTarget(const Vec3& attackerPos, const Vec3& attackerDir, const bool bCurrentlyZoomed, const EntityId ownerId) const { #if ALLOW_PROJECTILEHELPER_DEBUGGING static const ColorB red(127,0,0); static const ColorB green(0,127,0); static const ColorB brightGreen(0,255,0); static const float s_sphereDebugRad = 0.15f; #endif IEntity* pBestTarget = NULL; float fBestScore = 0.0f; const TAutoaimTargets& players = g_pGame->GetAutoAimManager().GetAutoAimTargets(); // Cache commonly required constants for scoring const ConeParams& aimConeSettings = GetAimConeSettings(bCurrentlyZoomed); const float minAutoAimDistSqrd = cry_sqr(aimConeSettings.m_minDistance); const float maxAutoAimDistSqrd = cry_sqr(aimConeSettings.m_maxDistance); const float coneSizeRads = aimConeSettings.m_outerConeRads; IEntitySystem* pEntitySystem = gEnv->pEntitySystem; CPlayerVisTable* pVisTable = g_pGame->GetPlayerVisTable(); const float distanceConstant = __fres(max(aimConeSettings.m_maxDistance, FLT_EPSILON)); const float coneAngleConstant = __fres(max(coneSizeRads*0.5f, FLT_EPSILON)); // For each potential target we do a dist + cone check TAutoaimTargets::const_iterator endIter = players.end(); for(TAutoaimTargets::const_iterator iter = players.begin(); iter != endIter; ++iter) { // If entity exists and we are allowed to target them EntityId targetEntityId = iter->entityId; IEntity* pEntity = pEntitySystem->GetEntity(targetEntityId); if(pEntity && AllowedToTargetPlayer(ownerId,targetEntityId)) { // If further than allowed dist, discard Vec3 targetTestPos; // Test against primary Auto aim position const SAutoaimTarget* pAutoAimInfo = g_pGame->GetAutoAimManager().GetTargetInfo(targetEntityId); if(pAutoAimInfo) { targetTestPos = pAutoAimInfo->primaryAimPosition; } else { // Then ABBB centre as backup IEntityPhysicalProxy* pPhysProxy = static_cast<IEntityPhysicalProxy*>(pEntity->GetProxy(ENTITY_PROXY_PHYSICS)); if(pPhysProxy) { AABB aabb; pPhysProxy->GetWorldBounds(aabb); targetTestPos = aabb.GetCenter(); } else { targetTestPos = pEntity->GetWorldPos(); } } Vec3 toTarget = targetTestPos - attackerPos; float distSqrd = toTarget.GetLengthSquared(); if( distSqrd >= minAutoAimDistSqrd && distSqrd <= maxAutoAimDistSqrd ) { // If not within cone.. discard float theta = 0.0f; if(TargetPositionWithinFrontalCone(attackerPos,targetTestPos, attackerDir,coneSizeRads, theta)) { // If cant see them .. next if(!pVisTable->CanLocalPlayerSee(targetEntityId, 5)) { #if ALLOW_PROJECTILEHELPER_DEBUGGING m_lastTargetRejectionReason.append("VISION BLOCKED"); #endif // #if ALLOW_PROJECTILEHELPER_DEBUGGING continue; } // For each candidate, generate their Auto Aim score. // 1) [0.0f,1.0f] score comprised of DISTANCE based score (closer is better) float targetDistScore = 1.0f - ( sqrtf(distSqrd) * distanceConstant ); // Lets try squaring this to make candidates with only small gaps between them reflect distance scoring better and reduce the importance of distance at super long ranges targetDistScore *= targetDistScore; // 2) + [0.0f,1.0f] cone based score (central is better) const float targetConeScore = 1.0f - ( theta * coneAngleConstant ); // Factor in designer controlled multipliers const float finalScore = (targetDistScore * g_pGameCVars->pl_pickAndThrow.chargedThrowAutoAimDistanceHeuristicWeighting) + // TODO - move these weightings into params (targetConeScore * g_pGameCVars->pl_pickAndThrow.chargedThrowAutoAimAngleHeuristicWeighting); if(finalScore > fBestScore) { fBestScore = finalScore; pBestTarget = pEntity; } // Debug rendering! #if ALLOW_PROJECTILEHELPER_DEBUGGING if(g_pGameCVars->pl_debug_projectileAimHelper) { CryWatch("Entity [%s - %d] DistScore [%.2f] , ConeScore[%.2f], totalScore [%.3f]", pEntity->GetName(), pEntity->GetId(), targetDistScore, targetConeScore, finalScore); // Draw a green sphere to indicate valid gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(targetTestPos, s_sphereDebugRad,green); } #endif //#if ALLOW_PROJECTILEHELPER_DEBUGGING } #if ALLOW_PROJECTILEHELPER_DEBUGGING else { m_lastTargetRejectionReason.Format("OUTSIDE CONE [%.3f]",RAD2DEG(theta)); if(g_pGameCVars->pl_debug_projectileAimHelper) { // Draw a red sphere to indicate not valid gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(targetTestPos, s_sphereDebugRad, red); } } #endif //#if ALLOW_PROJECTILEHELPER_DEBUGGING } #if ALLOW_PROJECTILEHELPER_DEBUGGING else { if(distSqrd >= minAutoAimDistSqrd) { m_lastTargetRejectionReason.Format("TOO CLOSE [%.3f]", cry_sqrtf_fast(distSqrd)); } else { m_lastTargetRejectionReason.Format("TOO FAR [%.3f]",cry_sqrtf_fast(distSqrd)); } } #endif //#if ALLOW_PROJECTILEHELPER_DEBUGGING } } // Draw a Really bright sphere on BEST target #if ALLOW_PROJECTILEHELPER_DEBUGGING if(pBestTarget && g_pGameCVars->pl_debug_projectileAimHelper) { // If further than allowed dist, discard Vec3 targetTestPos = pBestTarget->GetPos(); // We use aabb centre to reduce error IEntityPhysicalProxy* pPhysProxy = static_cast<IEntityPhysicalProxy*>(pBestTarget->GetProxy(ENTITY_PROXY_PHYSICS)); if(pPhysProxy) { AABB aabb; pPhysProxy->GetWorldBounds(aabb); targetTestPos = aabb.GetCenter(); } // Draw a bright green sphere to indicate target chosen gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(targetTestPos, s_sphereDebugRad*1.05f, brightGreen); } #endif //#if ALLOW_PROJECTILEHELPER_DEBUGGING return pBestTarget; }