CBurnEffectManager::TBurnPoints::iterator CBurnEffectManager::FindClosestBurnPoint(const Vec3& point, int surfaceType, const uint8 shooterFactionID) { if (m_burnPoints.empty()) return m_burnPoints.end(); float minDist = m_burnPoints[0].m_position.GetSquaredDistance(point); TBurnPoints::iterator best = m_burnPoints.end(); if (minDist <= cry_sqr(m_burnPoints[0].m_radius)) best = m_burnPoints.begin(); for (TBurnPoints::iterator it = m_burnPoints.begin()+1; it != m_burnPoints.end(); ++it) { float dist = it->m_position.GetSquaredDistance(point); if (dist < minDist && dist <= cry_sqr(it->m_radius) && (it->m_surfaceType == surfaceType) && (it->m_shooterFactionID == shooterFactionID)) { minDist = dist; best = it; } } return best; }
void CMelee::OnFailedHit() { const SCollisionTestParams& collisionParams = m_collisionHelper.GetCollisionTestParams(); bool collided = PerformCylinderTest(collisionParams.m_pos, collisionParams.m_dir, collisionParams.m_remote); CActor* pOwner = m_pWeapon->GetOwnerActor(); if(pOwner && pOwner->IsClient()) { if(!collided && s_meleeSnapTargetId) { Vec3 ownerpos = pOwner->GetEntity()->GetWorldPos(); IEntity* pTarget = gEnv->pEntitySystem->GetEntity(s_meleeSnapTargetId); if(pTarget && ownerpos.GetSquaredDistance(pTarget->GetWorldPos()) < cry_sqr(GetRange() * m_pMeleeParams->meleeparams.target_range_mult)) { collided = m_collisionHelper.PerformMeleeOnAutoTarget(s_meleeSnapTargetId); } } s_meleeSnapTargetId = 0; CHANGED_NETWORK_STATE(pOwner, CPlayer::ASPECT_SNAP_TARGET); if(g_pGameCVars->pl_melee.mp_melee_system_camera_lock_and_turn) { pOwner->GetActorParams().viewLimits.ClearViewLimit(SViewLimitParams::eVLS_Item); } } if(m_pMeleeAction) { if(pOwner) { m_pMeleeAction->OnHitResult(pOwner, collided); } else { //Owner has dropped weapon (Likely from being killed) so we can stop and release the action m_pMeleeAction->ForceFinish(); SAFE_RELEASE(m_pMeleeAction); } } ApplyMeleeEffects(collided); }
//--------------------------------------------------------------------------- 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; }