void Update(float elapsed) { float maxTime = GetPortFloat(&m_actInfo, EIP_Duration); float percent = maxTime > FLT_EPSILON ? elapsed / maxTime : 1.0f; if(percent >= 1.0f) { m_actInfo.pGraph->SetRegularlyUpdated(m_actInfo.myID, false); m_triggered = false; return; } Vec3 N = GetPortVec3(&m_actInfo, EIP_Normal); float rangeMin = GetPortFloat(&m_actInfo, EIP_RangeMin); float rangeMax = GetPortFloat(&m_actInfo, EIP_RangeMax); const float range = rangeMax - rangeMin; Vec3 boxDim(rangeMax, rangeMax, rangeMax); Vec3 ptmin = m_effectCenter - boxDim; Vec3 ptmax = m_effectCenter + boxDim; float speed = GetPortFloat(&m_actInfo, EIP_Speed); float waveFront = elapsed * speed; float decay = GetPortFloat(&m_actInfo, EIP_Decay); if(decay > FLT_EPSILON) decay = 1.0f / decay; float force = GetPortFloat(&m_actInfo, EIP_Force); force = pow_tpl(force * (1-percent), decay); float amplitude = GetPortFloat(&m_actInfo, EIP_Amplitude); amplitude = pow_tpl(amplitude * (1-percent), decay); if (gEnv->bMultiplayer) // Turned off for performance and network issues { return; } IPhysicalEntity** pEntityList = NULL; static const int iObjTypes = ent_rigid | ent_sleeping_rigid | ent_living;// | ent_allocate_list; int numEntities = gEnv->pPhysicalWorld->GetEntitiesInBox(ptmin, ptmax, pEntityList, iObjTypes); AABB bounds; for(int i=0; i<numEntities; ++i) { IPhysicalEntity* pPhysicalEntity = pEntityList[i]; IEntity* pEntity = static_cast<IEntity*>(pPhysicalEntity->GetForeignData(PHYS_FOREIGN_ID_ENTITY)); // Has the entity already been affected? if(pEntity) { bool affected = stl::find(m_entitiesAffected, pEntity->GetId()); if(!affected) { IEntityPhysicalProxy* pPhysicalProxy = static_cast<IEntityPhysicalProxy*>(pEntity->GetProxy(ENTITY_PROXY_PHYSICS)); if(pPhysicalProxy) { pPhysicalProxy->GetWorldBounds(bounds); Vec3 p = bounds.GetCenter(); Vec3 v = p - m_effectCenter; float distFromCenter = v.GetLength() + FLT_EPSILON; if(distFromCenter < rangeMax) { if(waveFront > distFromCenter) // has the wavefront passed the entity? { //pPhysicalEntity->GetStatus(&dyn); // normalize v, cheaper than another sqrt v /= distFromCenter; Vec3 dir = N + v * force; static bool usePos = false; float impulse = 1.0f - (max(0.0f, distFromCenter - rangeMin) / range); impulse = impulse * amplitude;// / dyn.mass; if(impulse > FLT_EPSILON) { pPhysicalProxy->AddImpulse(-1, p, dir * impulse, usePos, 1.0f); m_entitiesAffected.push_back(pEntity->GetId()); } } } } } } } }
void CVehicleDamageBehaviorBlowTire::DamagePlayers() { // check for the nasty case when the player is shooting at the vehicle tires while prone // under or behind the car, In that case the player should get killed by the vehicle, // otherwise he gets stuck forever. Note that he should only get killed when the tier // is actually destroyed and not by collision resulting by the impulse added by just // shooting at the tiers. Unfortunately using physics for doing this check is not reliable // enough so we have to check it explicitly IEntityPhysicalProxy *pPhysicsProxy = (IEntityPhysicalProxy*)m_pVehicle->GetEntity()->GetProxy(ENTITY_PROXY_PHYSICS); if (!pPhysicsProxy) return; AABB bbox; pPhysicsProxy->GetWorldBounds( bbox ); IPhysicalWorld *pWorld = gEnv->pSystem->GetIPhysicalWorld(); IPhysicalEntity **ppColliders; // check entities in collision with the car int cnt = pWorld->GetEntitiesInBox( bbox.min,bbox.max, ppColliders,ent_living); for (int i = 0; i < cnt; i++) { IEntity *pEntity = gEnv->pEntitySystem->GetEntityFromPhysics( ppColliders[i] ); if (!pEntity) continue; // skip the vehicle itself if (pEntity==m_pVehicle->GetEntity()) continue; IPhysicalEntity *pPhysEnt = pEntity->GetPhysics(); if (!pPhysEnt) continue; IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId()); if(!pActor) continue; //Jan M.: the player is killed when he entered the vehicle while prone although he is still passenger! if(m_pVehicle == pActor->GetLinkedVehicle()) continue; //the player must be prone under the vehicle IAnimatedCharacter * animatedCharacter=pActor->GetAnimatedCharacter(); if (!animatedCharacter) continue; int stance = animatedCharacter->GetCurrentStance(); if (stance!=STANCE_PRONE) continue; pe_player_dimensions dim; if (!pPhysEnt->GetParams(&dim)) continue; // position returned is at entity's feet, add head position from physics Vec3 vPos1=pEntity->GetPos(); vPos1.z = vPos1.z + dim.heightHead; float fZ=bbox.GetCenter().z; if (vPos1.z>fZ) continue; // not under the vehicle // at this point we have a collision with the car moving down and the guy prone under the car, it is safe // to assume he has been squished so let's kill him. if (gEnv->bServer && pActor->GetHealth()>0) { // adding a server hit to make it working in MP IGameRules *pGameRules = gEnv->pGame->GetIGameFramework()->GetIGameRulesSystem()->GetCurrentGameRules(); if (pGameRules) { HitInfo hit; EntityId shooterId=m_pVehicle->GetEntityId(); if (m_pVehicle->GetDriver()) shooterId=m_pVehicle->GetDriver()->GetEntityId(); hit.targetId = pEntity->GetId(); hit.shooterId = shooterId; hit.weaponId = m_pVehicle->GetEntityId(); hit.damage = 1000.f; hit.type = 0; hit.pos = pActor->GetEntity()->GetWorldPos(); pGameRules->ServerHit(hit); } } } //i }
//--------------------------------------------------------------------------- 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; }