float CGameRulesMPDamageHandling::CalculateFriendlyFireRatio(EntityId entityId1, EntityId entityId2) { CGameRules *pGameRules = m_pGameRules; if (entityId1 != entityId2 && pGameRules->GetTeamCount() > 1) { int team1 = pGameRules->GetTeam(entityId1); if( team1 == pGameRules->GetTeam(entityId2) ) { return pGameRules->GetFriendlyFireRatio(); } } //Not on same team so full damage return 1.f; }
bool CHUDCrosshair::IsFriendlyEntity(IEntity *pEntity) { IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor(); CGameRules *pGameRules = g_pGame->GetGameRules(); if(!pEntity || !pClientActor || !pGameRules) return false; // Less than 2 teams means we are in a FFA based game. if(pGameRules->GetTeamCount() < 2) return false; bool bFriendly = false; int iClientTeam = pGameRules->GetTeam(pClientActor->GetEntityId()); // First, check if entity is a player IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId()); if(pActor && pActor->IsPlayer()) { if(iClientTeam && (pGameRules->GetTeam(pActor->GetEntityId()) == iClientTeam)) { bFriendly = true; } } else { // Then, check if entity is a vehicle IVehicle *pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(pEntity->GetId()); if(pVehicle && pGameRules->GetTeam(pVehicle->GetEntityId()) == iClientTeam && pVehicle->GetStatus().passengerCount) { IActor *pDriver = pVehicle->GetDriver(); /*if(pDriver && pGameRules->GetTeam(pDriver->GetEntityId()) == iClientTeam) bFriendly = true; else bFriendly = false;*/ bFriendly = true; //fix for bad raycast if(pDriver && pDriver == pClientActor) bFriendly = false; } } return bFriendly; }
bool CHUDTagNames::IsFriendlyToClient(EntityId uiEntityId) { IActor *client = g_pGame->GetIGameFramework()->GetClientActor(); CGameRules *pGameRules = g_pGame->GetGameRules(); if(!client || !pGameRules) return false; int playerTeam = pGameRules->GetTeam(client->GetEntityId()); // if this actor is spectating, use the team of the player they are spectating instead... if(static_cast<CActor*>(client)->GetSpectatorMode() == CActor::eASM_Follow) { playerTeam = pGameRules->GetTeam(static_cast<CActor*>(client)->GetSpectatorTarget()); } // Less than 2 teams means we are in a FFA based game. if(pGameRules->GetTeam(uiEntityId) == playerTeam && pGameRules->GetTeamCount() > 1) return true; return false; }
void CClaymore::Update(SEntityUpdateContext &ctx, int updateSlot) { CProjectile::Update(ctx, updateSlot); bool debug = (g_pGameCVars->g_debugMines != 0); if(gEnv->bServer) { if(m_armed) { CGameRules* pGR = g_pGame->GetGameRules(); if(pGR) { for(std::list<EntityId>::iterator it = m_targetList.begin(); it != m_targetList.end(); ++it) { IEntity* pEntity = gEnv->pEntitySystem->GetEntity(*it); if(!pEntity) continue; // if this is a team game, claymores aren't set off by their own team... if(pGR->GetTeamCount() > 0 && (m_teamId != 0 && pGR->GetTeam(pEntity->GetId()) == m_teamId)) continue; // otherwise, not set off by the player who dropped them. if(pGR->GetTeamCount() == 0 && m_ownerId == pEntity->GetId()) continue; IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus) && physStatus.v.GetLengthSquared() > 0.01f) { // now check angle between this claymore and approaching object // to see if it is within the angular range m_triggerAngle. // If it is, then check distance is less than m_triggerRange, // and also check line-of-sight between the two entities. IRenderAuxGeom * pRAG = gEnv->pRenderer->GetIRenderAuxGeom(); pRAG->SetRenderFlags( e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeNone ); AABB entityBBox; pEntity->GetWorldBounds(entityBBox); if(debug) { pRAG->DrawAABB( entityBBox, true, ColorF(1,0,0,0.4f), eBBD_Faceted ); } Vec3 enemyDir = entityBBox.GetCenter() - GetEntity()->GetPos(); Vec3 checkDir = enemyDir; checkDir.z = 0; float distanceSq = enemyDir.GetLengthSquared(); // for players a simple distance check is fine, but for vehicles use a better intersection check // so any corner of the vehicle going inside the zone sets off the claymore. static float playerRadius = 2.5f; bool inside = false; if(entityBBox.GetRadius() < playerRadius) { inside = (distanceSq < (m_triggerRadius * m_triggerRadius)); } else { static ray_hit hit; if(gEnv->pPhysicalWorld->CollideEntityWithBeam(pEntity->GetPhysics(), GetEntity()->GetWorldPos(), enemyDir, m_triggerRadius, &hit)) { inside = true; enemyDir = hit.pt - GetEntity()->GetWorldPos(); } } if(inside) { enemyDir.NormalizeSafe(); checkDir.NormalizeSafe(); float dotProd = checkDir.Dot(m_triggerDirection); if(debug) { pRAG->DrawLine(GetEntity()->GetPos(), ColorF(1,0,0,1), GetEntity()->GetPos() + Matrix33::CreateRotationZ(m_triggerAngle/2.0f)*m_triggerDirection*m_triggerRadius, ColorF(1,0,0,1), 5.0f); pRAG->DrawLine(GetEntity()->GetPos(), ColorF(1,0,0,1), GetEntity()->GetPos() + Matrix33::CreateRotationZ(-m_triggerAngle/2.0f)*m_triggerDirection*m_triggerRadius, ColorF(1,0,0,1), 5.0f); ColorF clr; clr.a = 0.3f; clr.b = 0.4f; clr.g = 0.1f; clr.r = 1.0f; pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + (enemyDir * m_triggerRadius), clr, 5.0f); } if(dotProd > cry_cosf(m_triggerAngle/2.0f)) { static const int objTypes = ent_all&(~ent_terrain); static const unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any; ray_hit hit; int col = gEnv->pPhysicalWorld->RayWorldIntersection(GetEntity()->GetPos(), (enemyDir * m_triggerRadius * 1.5f), objTypes, flags, &hit, 1, GetEntity()->GetPhysics()); bool bang = false; if (!col) bang = true; else if (entityBBox.IsContainPoint(hit.pt)) bang = true; else if (hit.pt.GetSquaredDistance(GetEntity()->GetWorldPos()) >= distanceSq) bang = true; if (bang) { // pass in the explosion normal, which is -m_triggerDirection Explode(true, false, Vec3(0,0,0), -m_triggerDirection); if(debug) { ColorF clr; clr.a = 0.3f; clr.g = 0.1f; clr.r = 1.0f; clr.b = 1.0f; pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + (enemyDir * m_triggerRadius), clr, 5.0f); } } } } } } } } } else { m_timeToArm -= gEnv->pTimer->GetFrameTime(); if(m_timeToArm <= 0.0f) { m_armed = true; IEntityTriggerProxy *pTriggerProxy = (IEntityTriggerProxy*)(GetEntity()->GetProxy(ENTITY_PROXY_TRIGGER)); if (!pTriggerProxy) { GetEntity()->CreateProxy(ENTITY_PROXY_TRIGGER); pTriggerProxy = (IEntityTriggerProxy*)GetEntity()->GetProxy(ENTITY_PROXY_TRIGGER); } if(pTriggerProxy) { // create a trigger volume a couple of metres bigger than we need, to ensure we catch vehicles. // Checks above will still make sure the entity is within the radius before detonating though. float radius = m_triggerRadius + 2.0f; AABB boundingBox = AABB(Vec3(-radius,-radius,-radius), Vec3(radius,radius,radius)); pTriggerProxy->SetTriggerBounds(boundingBox); } } } } if(debug && m_armed) { IRenderAuxGeom * pRAG = gEnv->pRenderer->GetIRenderAuxGeom(); ColorF clr; clr.a = 0.3f; clr.b = 0.4f; clr.g = 0.1f; clr.r = 1.0f; pRAG->SetRenderFlags( e_Mode3D | e_AlphaBlended | e_DrawInFrontOff | e_FillModeSolid | e_CullModeNone ); pRAG->DrawCylinder(GetEntity()->GetPos(), Vec3(0, 0, 1), m_triggerRadius, m_triggerRadius * 2.0f, clr); Vec3 size(m_triggerRadius + 2.0f, m_triggerRadius + 2.0f, m_triggerRadius + 2.0f); AABB box(GetEntity()->GetPos() - size, GetEntity()->GetPos() + size); pRAG->DrawAABB(box, false, ColorF(0.1f, 0.1f, 0.1f, 0.1f), eBBD_Faceted); pRAG->DrawLine(GetEntity()->GetPos(), clr, GetEntity()->GetPos() + m_triggerDirection, clr, 5.0f); } }
//------------------------------------------------------------------------ void CWeapon::OnShoot(EntityId shooterId, EntityId ammoId, IEntityClass* pAmmoType, const Vec3 &pos, const Vec3 &dir, const Vec3&vel) { BROADCAST_WEAPON_EVENT(OnShoot, (this, shooterId, ammoId, pAmmoType, pos, dir, vel)); //FIXME:quick temporary solution CActor *pActor = static_cast<CActor*> (g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(shooterId)); if (pActor) pActor->HandleEvent(SGameObjectEvent(eCGE_OnShoot,eGOEF_ToExtensions)); IActor *pClientActor=m_pGameFramework->GetClientActor(); if (pActor && pActor->GetActorClass() == CPlayer::GetActorClassType() && IsServer()) { if (pActor == pClientActor) { if (IAIObject *pAIObject=pActor->GetEntity()->GetAI()) gEnv->pAISystem->SendSignal(SIGNALFILTER_LEADER, 1, "OnEnableFire", pAIObject, 0); } CPlayer *pPlayer=static_cast<CPlayer *>(pActor); CNanoSuit *pSuit=pPlayer->GetNanoSuit(); if(m_fm && strcmp(m_fm->GetType(), "Repair")) { if(pSuit) { if (pSuit->GetMode() == NANOMODE_STRENGTH && !IsMounted()) pSuit->SetSuitEnergy(pSuit->GetSuitEnergy()-g_pGameCVars->g_suitRecoilEnergyCost); else if(pSuit->GetMode() == NANOMODE_CLOAK) pSuit->SetSuitEnergy(0.0f); } } if (gEnv->bServer && pSuit && pSuit->IsInvulnerable()) pSuit->SetInvulnerability(false); } if (pClientActor && m_fm && strcmp(m_fm->GetType(), "Thrown")) { // inform the HUDRadar about the sound event Vec3 vPlayerPos=pClientActor->GetEntity()->GetWorldPos(); float fDist2=(vPlayerPos-pos).len2(); if (fDist2<250.0f*250.0f) { //if (pClientActor->GetEntityId() != shooterId) // pHUD->ShowSoundOnRadar(pos); if(gEnv->bMultiplayer) { CGameRules *pGameRules = g_pGame->GetGameRules(); if(pGameRules->GetTeamCount() < 2 || (pGameRules->GetTeam(shooterId) != pGameRules->GetTeam(pClientActor->GetEntityId()))) { //Small workaround for patch2... IFireMode* pFM = GetFireMode(GetCurrentFireMode()); bool grenade = pFM?(pFM->GetAmmoType()==CItem::sScarGrenadeClass):false; //~... if (!IsSilencerAttached() || grenade) { SAFE_HUD_FUNC(GetRadar()->AddEntityTemporarily(shooterId, 5.0f)); } else if(fDist2<5.0f*5.0f) { //Silencer attached SAFE_HUD_FUNC(GetRadar()->AddEntityTemporarily(shooterId, 5.0f)); } } } if ((!IsSilencerAttached()) && fDist2<sqr(SAFE_HUD_FUNC_RET(GetBattleRange()))) SAFE_HUD_FUNC(TickBattleStatus(1.0f)); } } }
//------------------------------------------------------------------------ void CGameRulesMPDamageHandling::SvOnCollision(const IEntity *pVictimEntity, const CGameRules::SCollisionHitInfo& collisionHitInfo) { FUNCTION_PROFILER(gEnv->pSystem, PROFILE_GAME); CRY_ASSERT(gEnv->bMultiplayer); #if !defined(_RELEASE) if (g_pGameCVars->g_DisableCollisionDamage) return; #endif IGameFramework* gameFramwork = g_pGame->GetIGameFramework(); EntityId victimID = pVictimEntity->GetId(); EntityId offenderID = collisionHitInfo.targetId; const IEntity* pOffenderEntity = gEnv->pEntitySystem->GetEntity(offenderID); float currentTime = gEnv->pTimer->GetCurrTime(); CActor* victimActor = static_cast<CActor*>(gameFramwork->GetIActorSystem()->GetActor(victimID)); IVehicle* offenderVehicle = gameFramwork->GetIVehicleSystem()->GetVehicle(offenderID); IVehicle* victimVehicle = gameFramwork->GetIVehicleSystem()->GetVehicle(victimID); IActor* offenderActor = gameFramwork->GetIActorSystem()->GetActor(offenderID); if(pOffenderEntity && !offenderVehicle && !offenderActor) { if( IEntity* pParent = pOffenderEntity->GetParent() ) { offenderVehicle = gameFramwork->GetIVehicleSystem()->GetVehicle(pParent->GetId()); } } // Vehicles being flipped do no damage, for now if (offenderVehicle != NULL && offenderVehicle->GetStatus().beingFlipped) return; // Players can't damage vehicles if (victimVehicle && offenderActor) return; // Filter frequent collisions if (pOffenderEntity) { FRAME_PROFILER("Filter out recent collisions", gEnv->pSystem, PROFILE_GAME); EntityCollisionRecords::const_iterator collisionRecordIter = m_entityCollisionRecords.find(victimID); if (collisionRecordIter != m_entityCollisionRecords.end()) { const EntityCollisionRecord& record = collisionRecordIter->second; if (record.entityID == offenderID && record.time + EntityCollisionIgnoreTimeBetweenCollisions > currentTime) { return; } } } float offenderMass = collisionHitInfo.target_mass; enum { CollisionWithEntity, CollisionWithStaticWorld } collisionType = (pOffenderEntity || offenderMass > 0.0f) ? CollisionWithEntity : CollisionWithStaticWorld; const Vec3& victimVelocity = collisionHitInfo.velocity; const Vec3& offenderVelocity = collisionHitInfo.target_velocity; float relativeSpeedSq = 0.0f; float minSpeedToCareAboutCollisionSq = 0.0f; float contactMass = 0.0f; bool offenderIsBig = offenderMass > 1000.f; switch (collisionType) { case CollisionWithEntity: { Vec3 relativeVelocity = victimVelocity - offenderVelocity; relativeSpeedSq = relativeVelocity.GetLengthSquared(); minSpeedToCareAboutCollisionSq = sqr(10.0f); if (victimActor && offenderIsBig) { minSpeedToCareAboutCollisionSq = sqr(1.0f); } if (victimActor && offenderVehicle) { //Players won't be hurt by vehicles with a negative kill player speed if(offenderVehicle->GetDamageParams().aiKillPlayerSpeed < 0.f) { return; } minSpeedToCareAboutCollisionSq = sqr(2.0f); } const float offenderSpeedSq = offenderVelocity.GetLengthSquared(); if (offenderSpeedSq == 0.0f) // -- if collision target it not moving { minSpeedToCareAboutCollisionSq *= sqr(2.0f); } ////////////////////////////////////////////////////////////////////////// contactMass = offenderMass; break; } case CollisionWithStaticWorld: { // Actors don't take damage from running into walls! if (victimActor) { return; } relativeSpeedSq = victimVelocity.GetLengthSquared(); minSpeedToCareAboutCollisionSq = sqr(7.5f); contactMass = collisionHitInfo.mass; break; } } const bool contactMassIsTooLowToCare = contactMass < 0.01f; if (contactMassIsTooLowToCare) return; ////////////////////////////////////////////////////////////////////////// // Calculate the collision damage if (relativeSpeedSq >= minSpeedToCareAboutCollisionSq) { bool useDefaultCalculation = true; float fEnergy = 0.f; float damage = 0.f; EntityId kickerId = 0; // Calculate damage if (offenderVehicle && victimActor) { useDefaultCalculation = false; damage = ProcessActorVehicleCollision(victimActor, victimID, offenderVehicle, offenderID, damage, collisionHitInfo, kickerId); } else if (offenderIsBig && victimActor) // i.e. a kickable car { // Try to find the kicker CTimeValue time = gEnv->pTimer->GetAsyncTime(); IActorSystem* pActorSystem = gEnv->pGame->GetIGameFramework()->GetIActorSystem(); IActorIteratorPtr pActorIterator = pActorSystem->CreateActorIterator(); IActor* pActor = pActorIterator->Next(); float lowestTime = 5.f; while (pActor != NULL) { CPlayer* pPlayer = static_cast<CPlayer*>(pActor); EntityId kicked = pPlayer->GetLargeObjectInteraction().GetLastObjectId(); if (kicked==offenderID) { float timeSinceKick = (time - pPlayer->GetLargeObjectInteraction().GetLastObjectTime()).GetSeconds(); if (timeSinceKick < lowestTime) { // We found the kicker and the kicked kickerId = pActor->GetEntityId(); lowestTime = timeSinceKick; } } pActor = pActorIterator->Next(); } damage = ProcessActorKickedVehicle(victimActor, victimID, kickerId, offenderID, damage, collisionHitInfo); useDefaultCalculation = false; } if (useDefaultCalculation) { fEnergy = GetCollisionEnergy(pVictimEntity, collisionHitInfo); if (victimVehicle || offenderIsBig) { damage = 0.0005f * fEnergy; } else { damage = 0.0025f * fEnergy; } // Apply damage multipliers damage *= GetCollisionDamageMult(pVictimEntity, pOffenderEntity, collisionHitInfo); if (victimActor) { const bool victimIsPlayer = victimActor->IsPlayer(); if (victimIsPlayer) { damage = AdjustPlayerCollisionDamage(pVictimEntity, pOffenderEntity, collisionHitInfo, damage); } } } if (damage >= DAMAGE_THRESHOLD_COLLISIONS) { HitInfo hit; hit.damage = damage; hit.pos = collisionHitInfo.pos; if (collisionHitInfo.target_velocity.GetLengthSquared() > 1e-6) hit.dir = collisionHitInfo.target_velocity.GetNormalized(); hit.radius = 0.0f; hit.partId = collisionHitInfo.partId; hit.targetId = victimID; hit.weaponId = offenderID; hit.shooterId = kickerId != 0 ? kickerId : offenderID; hit.material = 0; hit.type = CGameRules::EHitType::Collision; hit.explosion = false; CGameRules *pGameRules = g_pGame->GetGameRules(); if (pGameRules->GetTeamCount() > 1) { int shooterTeamId = pGameRules->GetTeam(hit.shooterId); int targetTeamId = pGameRules->GetTeam(hit.targetId); if (shooterTeamId && (shooterTeamId == targetTeamId)) { damage = GetFriendlyFireDamage(damage, hit, victimActor); } } if (damage >= DAMAGE_THRESHOLD_COLLISIONS) { IScriptTable* pVictimScript = pVictimEntity ? pVictimEntity->GetScriptTable() : NULL; IScriptTable* pOffenderScript = pOffenderEntity ? pOffenderEntity->GetScriptTable() : NULL; if (!pOffenderEntity && pVictimEntity) { pOffenderEntity = pVictimEntity; offenderID = victimID; } m_entityCollisionRecords[victimID] = EntityCollisionRecord(offenderID, currentTime); if(victimVehicle) { victimVehicle->OnHit(hit); } else if (pVictimScript) { FRAME_PROFILER("Call to OnHit", gEnv->pSystem, PROFILE_GAME); if (!IsDead(victimActor, pVictimScript)) { if (IActor* offenderDriver = offenderVehicle ? offenderVehicle->GetDriver() : NULL) hit.shooterId = offenderDriver->GetEntityId(); DelegateServerHit(pVictimScript, hit, victimActor); } } } } } }
float CGameRulesMPDamageHandling::ProcessActorKickedVehicle(IActor* victimActor, EntityId victimId, EntityId kickerId, EntityId vehicleId, float damage, const CGameRules::SCollisionHitInfo& collisionHitInfo) { float angSpeedSq = 0.f; const IEntity* pVehicleEntity = gEnv->pEntitySystem->GetEntity(vehicleId); if (pVehicleEntity) { IPhysicalEntity* pent = pVehicleEntity->GetPhysics(); if (pent) { pe_status_dynamics psd; if (pent->GetStatus(&psd)) { angSpeedSq = psd.w.GetLengthSquared(); } } } const Vec3& actorVelocity = collisionHitInfo.velocity; const Vec3& vehicleVelocity = collisionHitInfo.target_velocity; const float vehicleSpeedSq = vehicleVelocity.GetLengthSquared() + angSpeedSq; if (vehicleSpeedSq < 1.5f) return 0.f; float damageScale = 1.f; if (g_pGameCVars->g_mpKickableCars) { if (kickerId==victimId || FindKickableCarRecord(vehicleId, victimId)) return 0.f; CGameRules *pGameRules = g_pGame->GetGameRules(); if (pGameRules->GetTeamCount() > 1) { int kickerTeamId = pGameRules->GetTeam(kickerId); int victimTeamId = pGameRules->GetTeam(victimId); if (kickerTeamId==victimTeamId) // Friendly fire { float friendlyFireRatio = pGameRules->GetFriendlyFireRatio(); if (friendlyFireRatio>0.f) { damageScale = friendlyFireRatio; } else { return 0.f; } } } InsertKickableCarRecord(vehicleId, victimId); } // Damage, for now, is based purely on vehicle speed const float vehicleKillSpeed = m_vehicleDamageSettings.killSpeed; const float invVehicleKillSpeed = 1.f/(vehicleKillSpeed+0.01f); const float maxActorHealth = victimActor->GetMaxHealth(); damage = 0.1f + sqrtf(vehicleSpeedSq+0.04f) * invVehicleKillSpeed; damage = min(damage, 1.f) * maxActorHealth * damageScale; return damage; }
void CPlayerRotation::TargetAimAssistance(CWeapon* pWeapon, float& followH, float& followV, float& scale, float& _fZoomAmount, const Vec3 playerView[4]) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); CRY_ASSERT(m_player.IsClient()); followH = 0.0f; followV = 0.0f; scale = 1.0f; float bestScale = 1.0f; const Vec3 playerFwd = playerView[1]; const Vec3 playerRgt = playerView[0]; const Vec3 playerUp = playerView[2]; const Vec3 playerPos = playerView[3]; Vec3 follow_target_pos(ZERO); float follow_vote_leader = 0.0f; float snap_vote_leader = 0.0f; Vec3 follow_target_dir(ZERO); Vec3 snap_target_dir(ZERO); EntityId follow_target_id = 0; EntityId snap_target_id = 0; CGameRules * pGameRules = g_pGame->GetGameRules(); float distance_follow_threshold_near = max(0.0f, g_pGameCVars->aim_assistMinDistance); float distance_follow_threshold_far = max(20.0f, g_pGameCVars->aim_assistMaxDistance); int playerTeam = pGameRules->GetTeam(m_player.GetEntity()->GetId()); float cloakedPlayerMultiplier = g_pGameCVars->pl_aim_cloaked_multiplier; const bool multipleTeams = pGameRules->GetTeamCount() > 0; const float fFollowFalloffDist = g_pGameCVars->aim_assistFalloffDistance + FLT_EPSILON*g_pGameCVars->aim_assistFalloffDistance; const bool playerIsScoped = m_player.GetActorStats()->isScoped; float minTurnScale, fAimAssistStrength, fMaxDistMult; if(pWeapon) { const float fZoomAmount = pWeapon->GetZoomTransition(); _fZoomAmount = fZoomAmount; const float fStrength = g_pGameCVars->aim_assistStrength; const float fStrengthIronSight = playerIsScoped ? g_pGameCVars->aim_assistStrength_SniperScope : g_pGameCVars->aim_assistStrength_IronSight; const float fDiff = fStrengthIronSight - fStrength; fAimAssistStrength = fStrength + (fZoomAmount * fDiff); const float fMinTurn = g_pGameCVars->aim_assistMinTurnScale; const float fMinTurnIronSight = playerIsScoped ? g_pGameCVars->aim_assistMinTurnScale_SniperScope : g_pGameCVars->aim_assistMinTurnScale_IronSight; const float fMinTurnDiff = fMinTurnIronSight - fMinTurn; minTurnScale = fMinTurn + (fZoomAmount * fMinTurnDiff); const float fMaxAssistDist = g_pGameCVars->aim_assistMaxDistance; const float fMaxAssistDist_Iron = playerIsScoped ? g_pGameCVars->aim_assistMaxDistance_SniperScope : g_pGameCVars->aim_assistMaxDistance_IronSight; const float fMaxAssistDistDiff = (fMaxAssistDist_Iron - fMaxAssistDist) * fZoomAmount; fMaxDistMult = (fMaxAssistDist + fMaxAssistDistDiff) * __fres(fMaxAssistDist); } else { _fZoomAmount = 0.0f; fMaxDistMult = 1.0f; fAimAssistStrength = g_pGameCVars->aim_assistStrength; minTurnScale = g_pGameCVars->aim_assistMinTurnScale; } const float falloffStartDistance = g_pGameCVars->aim_assistSlowFalloffStartDistance; const float falloffPerMeter = 1.0f / (g_pGameCVars->aim_assistSlowDisableDistance - falloffStartDistance); const TAutoaimTargets& aaTargets = g_pGame->GetAutoAimManager().GetAutoAimTargets(); const int targetCount = aaTargets.size(); float fBestTargetDistance = FLT_MAX; #if DBG_AUTO_AIM SAuxGeomRenderFlags oldFlags = gEnv->pRenderer->GetIRenderAuxGeom()->GetRenderFlags(); SAuxGeomRenderFlags newFlags = e_Def3DPublicRenderflags; newFlags.SetAlphaBlendMode(e_AlphaBlended); newFlags.SetDepthTestFlag(e_DepthTestOff); newFlags.SetCullMode(e_CullModeNone); gEnv->pRenderer->GetIRenderAuxGeom()->SetRenderFlags(newFlags); #endif for (int i = 0; i < targetCount; ++i) { const SAutoaimTarget& target = aaTargets[i]; CRY_ASSERT(target.entityId != m_player.GetEntityId()); //Skip friendly ai if(gEnv->bMultiplayer) { if(multipleTeams && (pGameRules->GetTeam(target.entityId) == playerTeam)) { continue; } } else { if (target.HasFlagSet(eAATF_AIHostile) == false) continue; distance_follow_threshold_far = fMaxDistMult * (target.HasFlagSet(eAATF_AIRadarTagged) ? g_pGameCVars->aim_assistMaxDistanceTagged : g_pGameCVars->aim_assistMaxDistance); } Vec3 targetPos = target.primaryAimPosition; Vec3 targetDistVec = (targetPos - playerPos); float distance = targetDistVec.GetLength(); if (distance <= 0.1f) continue; Vec3 dirToTarget = targetDistVec / distance; // fast reject everything behind player, too far away or too near from line of view // sort rest by angle to crosshair and distance from player float alignment = playerFwd * dirToTarget; if (alignment <= 0.0f) continue; if ((distance < distance_follow_threshold_near) || (distance > distance_follow_threshold_far)) continue; const int kAutoaimVisibilityLatency = 2; CPlayerVisTable::SVisibilityParams visParams(target.entityId); visParams.queryParams = eVQP_IgnoreGlass; if (!g_pGame->GetPlayerVisTable()->CanLocalPlayerSee(visParams, kAutoaimVisibilityLatency)) { // Since both player and target entities are ignored, and the ray still intersected something, there's something in the way. // Need to profile this and see if it's faster to do the below checks before doing the linetest. It's fairly expensive but // linetests generally are as well... - Richard continue; } #if DBG_AUTO_AIM const ColorB green(0,255,0,255); const ColorB darkgreen(0,155,0,225); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine( playerPos, darkgreen, targetPos, green); #endif const float angleDot = dirToTarget.dot(-playerRgt); const float angle = (RAD2DEG(acos_tpl(angleDot)) - 90.f); const float absAngle = fabsf(angle); const float angleDotV = playerUp.dot(dirToTarget); const float angleToTargetV = (RAD2DEG(acos_tpl(angleDotV)) - 90.f); const float absAngleV = fabsf(angleToTargetV); const float slowModifiedDistance = distance * g_pGameCVars->aim_assistSlowDistanceModifier; const float radius_slow_threshold_inner = 0.5f; const float radius_slow_threshold_outer = g_pGameCVars->aim_assistSlowThresholdOuter; const float angle_slow_threshold_inner = RAD2DEG(atan_tpl(radius_slow_threshold_inner / slowModifiedDistance)); const float angle_slow_threshold_outer = RAD2DEG(atan_tpl(radius_slow_threshold_outer / slowModifiedDistance)); float angle_slow_fractionH = clamp_tpl((absAngle - angle_slow_threshold_inner) / (angle_slow_threshold_outer - angle_slow_threshold_inner), 0.0f, 1.0f); float angle_slow_fractionV = clamp_tpl((absAngleV - angle_slow_threshold_inner) / (angle_slow_threshold_outer - angle_slow_threshold_inner), 0.0f, 1.0f); float angle_slow_fraction = max(angle_slow_fractionH, angle_slow_fractionV); const float distance_follow_fraction = clamp_tpl((distance - fFollowFalloffDist) / (distance_follow_threshold_far - fFollowFalloffDist), 0.0f, 1.0f); const float radius_follow_threshold_inner = target.innerRadius; const float radius_follow_threshold_outer = target.outerRadius; const float radius_snap = target.HasFlagSet(eAATF_AIRadarTagged) ? target.snapRadiusTagged * g_pGameCVars->aim_assistSnapRadiusTaggedScale : target.snapRadius * g_pGameCVars->aim_assistSnapRadiusScale; const float angle_follow_threshold_inner = RAD2DEG(atan_tpl(radius_follow_threshold_inner / distance)); const float angle_follow_threshold_outer = RAD2DEG(atan_tpl(radius_follow_threshold_outer / distance)); const float angle_follow_fraction = clamp_tpl((absAngle - angle_follow_threshold_inner) / (angle_follow_threshold_outer - angle_follow_threshold_inner), 0.0f, 1.0f); const float angle_follow_fractionV = clamp_tpl((absAngleV - angle_follow_threshold_inner) / (angle_follow_threshold_outer - angle_follow_threshold_inner), 0.0f, 1.0f); const float worst_follow_fraction = (float)__fsel(angle_follow_fraction - angle_follow_fractionV, angle_follow_fraction, angle_follow_fractionV); float follow_fraction = ((1.0f - worst_follow_fraction) * (1.0f - distance_follow_fraction)); float follow_vote = follow_fraction; //clamp the lower bound of the distance_slow_modifier so it can't be lower than the angle slow fraction // which prevents close but off-centre targets slowing us too much const float distance_slow_modifier = clamp_tpl( 1.0f - ((distance - falloffStartDistance) * falloffPerMeter), angle_slow_fraction, 1.0f); const float fCombinedModifier = angle_slow_fraction * distance_slow_modifier; fBestTargetDistance = (float)__fsel(fCombinedModifier - bestScale, fBestTargetDistance, distance); bestScale = min(fCombinedModifier, bestScale); if (follow_vote > follow_vote_leader) { follow_vote_leader = follow_vote; //m_follow_target_id only gets set after the loop -> this won't get hit when a target is selected // as a follow target for the first time. This doesn't need to be in the loop. if ( m_follow_target_id == target.entityId) { const Vec3 follow_target_dir_local = m_follow_target_dir; Vec3 target_rgt = playerRgt; Vec3 target_up = target_rgt.cross(follow_target_dir_local); target_rgt = follow_target_dir_local.cross(target_up); target_rgt.Normalize(); target_up.Normalize(); float alignH = dirToTarget * -target_rgt; float alignV = dirToTarget.z - follow_target_dir_local.z; float angleH = min(fabsf(alignH * fAimAssistStrength), fabsf(angleDot)); float angleV = min(fabsf(alignV * fAimAssistStrength), fabsf(angleDotV)); followH = follow_fraction * (float)__fsel(angleDot, angleH, -angleH); followV = follow_fraction * (float)__fsel(angleDotV, angleV, -angleV); follow_vote_leader += 0.05f; // anti oscillation between different targets follow_target_pos = targetPos; } follow_target_id = target.entityId; snap_target_id = target.entityId; follow_target_dir = dirToTarget; snap_target_dir = PickBestSnapDirection(playerPos, playerFwd, target); } else if (!follow_target_id && (radius_snap > 0.0f)) { Lineseg lineSegment; lineSegment.start = playerPos; lineSegment.end = playerPos + (playerFwd * (distance + radius_snap)); Sphere sphere; sphere.center = targetPos; sphere.radius = radius_snap; Vec3 intersectionPoint; if (Intersect::Lineseg_SphereFirst(lineSegment, sphere, intersectionPoint)) { float t = 0.0f; const float snap_fraction = 1.0f - (Distance::Point_Lineseg(targetPos, lineSegment, t) * (float)__fres(radius_snap)); if (snap_fraction > snap_vote_leader) { snap_vote_leader = snap_fraction; snap_target_id = target.entityId; snap_target_dir = PickBestSnapDirection(playerPos, playerFwd, target); } } } } #if DBG_AUTO_AIM if ((!follow_target_pos.IsZeroFast()) && (g_pGameCVars->pl_targeting_debug != 0)) { float radius_inner = 0.30f; float radius_outer = 0.33f; ColorB colorInner(255,255,0,0x40); ColorB colorOuter(255,255,0,0x40); DrawDisc(follow_target_pos, follow_target_dir, radius_inner, radius_outer, colorInner, colorOuter); } gEnv->pRenderer->GetIRenderAuxGeom()->SetRenderFlags(oldFlags); #endif m_follow_target_id = follow_target_id; m_follow_target_dir = follow_target_dir; //IMPORTANT: Apply the minimum-distance scaling of the slowdown _after_ calculating the slowdown for the best target // as we want to help the player aim at the nearest target, and modifying the slowdown multiplier prior to this // could result in a different target being selected const float fSlowDownProximityFadeInBand = (g_pGameCVars->aim_assistSlowStopFadeinDistance - g_pGameCVars->aim_assistSlowStartFadeinDistance) + FLT_EPSILON; float fSlowDownProximityScale = (fBestTargetDistance - g_pGameCVars->aim_assistSlowStartFadeinDistance) / fSlowDownProximityFadeInBand; Limit(fSlowDownProximityScale, 0.0f, 1.0f); float fInvBestScale = (1.0f - bestScale) * fSlowDownProximityScale; bestScale = 1.0f - fInvBestScale; scale = minTurnScale + ((1.0f - minTurnScale) * bestScale); UpdateCurrentSnapTarget(snap_target_id, snap_target_dir); }
static void GetTalosInput(CPlayerRotation * pPlayerRotation, const CPlayer& rPlayer, float& x, float& z, const Vec3 playerView[4], float fFrameTime) { //Do I need to reproject the view to actually get the positioning correct? Shouldn't be. const Vec3 playerFwd = playerView[1]; const Vec3 playerRgt = playerView[0]; const Vec3 playerUp = playerView[2]; const Vec3 playerViewPos = playerView[3]; Vec3 playerPos = playerViewPos; IPhysicalEntity * pPhysicalEntity = rPlayer.GetEntity()->GetPhysics(); if(pPhysicalEntity) { pe_status_dynamics dyn_status; pPhysicalEntity->GetStatus(&dyn_status); playerPos = playerViewPos + (dyn_status.v * fFrameTime * 2.0f); } Vec3 follow_target_dir(ZERO); EntityId follow_target_id = 0; static EntityId s_follow_target_id = 0; CGameRules * pGameRules = g_pGame->GetGameRules(); int playerTeam = pGameRules->GetTeam(rPlayer.GetEntity()->GetId()); float cloakedPlayerMultiplier = g_pGameCVars->pl_aim_cloaked_multiplier; const bool multipleTeams = pGameRules->GetTeamCount() > 0; const TAutoaimTargets& aaTargets = g_pGame->GetAutoAimManager().GetAutoAimTargets(); const int targetCount = aaTargets.size(); float fBestTargetDistance = FLT_MAX; for (int i = 0; i < targetCount; ++i) { const SAutoaimTarget& target = aaTargets[i]; if(multipleTeams && (pGameRules->GetTeam(target.entityId) == playerTeam)) { continue; } Vec3 targetPos = target.secondaryAimPosition; IEntity * pEntity = gEnv->pEntitySystem->GetEntity(target.entityId); if(pEntity) { IPhysicalEntity * pPhysicalEntity2 = pEntity->GetPhysics(); if(pPhysicalEntity2) { pe_status_dynamics dyn_status; pPhysicalEntity2->GetStatus(&dyn_status); targetPos = targetPos + (dyn_status.v * fFrameTime); } } Vec3 targetDistVec = (targetPos - playerPos); float distance = targetDistVec.GetLength(); if (distance <= 0.01f) continue; Vec3 dirToTarget = targetDistVec / distance; // fast reject everything behind player, too far away or too near from line of view // sort rest by angle to crosshair and distance from player const int kAutoaimVisibilityLatency = 1; if (!g_pGame->GetPlayerVisTable()->CanLocalPlayerSee(target.entityId, kAutoaimVisibilityLatency)) { // Since both player and target entities are ignored, and the ray still intersected something, there's something in the way. // Need to profile this and see if it's faster to do the below checks before doing the linetest. It's fairly expensive but // linetests generally are as well... - Richard continue; } const float angleDot = dirToTarget.dot(-playerRgt); const float angle = (RAD2DEG(acos_tpl(angleDot)) - 90.f); const float absAngle = fabsf(angle); const float angleDotV = playerUp.dot(dirToTarget); const float angleToTargetV = (RAD2DEG(acos_tpl(angleDotV)) - 90.f); const float absAngleV = fabsf(angleToTargetV); if ( s_follow_target_id == target.entityId ) { follow_target_id = target.entityId; follow_target_dir = dirToTarget; break; } else if(distance < fBestTargetDistance) { fBestTargetDistance = distance; follow_target_id = target.entityId; follow_target_dir = dirToTarget; } } if(follow_target_id != 0) { //Player up is the normal of the plane that we are rotating around - (Correct? Or do we want to project both the player direction and the target direction onto the X/Y plane?) Vec3 vProjectedTargetHorz = playerUp.cross(follow_target_dir.cross(playerUp)); Vec3 vProjectedTargetVert = playerRgt.cross(follow_target_dir.cross(playerRgt)); float horzDot = vProjectedTargetHorz.GetNormalized().dot(playerFwd); float vertDot = vProjectedTargetVert.GetNormalized().dot(playerFwd); const float directionDotHorz = follow_target_dir.dot(playerRgt); const float directionDotVert = follow_target_dir.dot(playerUp); const float angle = acos_tpl(horzDot); const float angleToTargetV = acos_tpl(vertDot); const float fHorzFinalAngle = (float)__fsel(directionDotHorz, -angle, angle); const float fVertFinalAngle = (float)__fsel(directionDotVert, angleToTargetV, -angleToTargetV); //CryWatch("Angle to target: %.6f", RAD2DEG(angle)); //CryWatch("Final Angle to target: %.6f", RAD2DEG(fHorzFinalAngle)); x = x + fVertFinalAngle; z = z + fHorzFinalAngle; } s_follow_target_id = follow_target_id; return; }
//------------------------------------------------------------------------- void CGameRulesStandardState::Update( float frameTime ) { if (gEnv->bServer) { if(m_state == EGRS_Intro) { // We assume there is an intro, if we reach this point and an intro hasnt been registered, we know there isn't one. Onwards and upwards. if(!m_pGameRules->IsIntroSequenceRegistered()) { ChangeState(EGRS_PreGame); } } if (m_state == EGRS_PreGame) { if (m_isStarting) { const float remainingTime = m_pGameRules->GetRemainingStartTimer(); if (remainingTime <= 0.f) { CryLog("CGameRulesStandardState::Update(), starting game"); ChangeState(EGRS_InGame); } } else { bool bOk = true; CGameLobby* pGameLobby = g_pGame->GetGameLobby(); const int numPlayers = m_pGameRules->GetPlayerCount(true); if (pGameLobby) { if (m_isWaitingForOverrideTimer) { //-- test override timer m_startTimerOverrideWait -= frameTime; bOk = (m_startTimerOverrideWait <= 0.0f); if (!bOk) { bOk = true; //-- testing min player count doesn't apply to private games const bool publicGame = !pGameLobby->IsPrivateGame(); const bool onlineGame = pGameLobby->IsOnlineGame(); if (publicGame && onlineGame) { // Start only when we have enough players if (m_pGameRules->GetTeamCount() > 1) { //-- team game, insist at least 1 player per team const int numPlayersPerTeamMin = g_pGameCVars->g_gameRules_startTimerMinPlayersPerTeam; const int numPlayersTeam1 = m_pGameRules->GetTeamPlayerCount(1, true); const int numPlayersTeam2 = m_pGameRules->GetTeamPlayerCount(2, true); bOk = ((numPlayersTeam1 >= numPlayersPerTeamMin) && (numPlayersTeam2 >= numPlayersPerTeamMin)); } else { //-- not a team game, so just insist on minimum 2 players const int numPlayersMin = g_pGameCVars->g_gameRules_startTimerMinPlayers; bOk = (numPlayers >= numPlayersMin); } const int numPlayersInLobby = pGameLobby->GetSessionNames().Size(); bOk |= (numPlayersInLobby == numPlayers); } if (bOk) { //-- Enforce a percentage of lobby players in game before starting countdown bOk = (!gEnv->IsClient() || (g_pGame->GetClientActorId() != 0)) && CheckInitialChannelPlayers(); } } } else { bOk = false; if (numPlayers) { //-- Start the override timer. m_startTimerOverrideWait = g_pGameCVars->g_gameRules_startTimerOverrideWait; m_isWaitingForOverrideTimer = true; } } } if (bOk) { CryLog("CGameRulesStandardState::Update(), we have %i players, starting the game", numPlayers); float startTimeLength = #if !defined(_RELEASE) g_pGameCVars->g_gameRules_skipStartTimer ? 0.0f : #endif g_pGameCVars->g_gameRules_startTimerLength; #if USE_PC_PREMATCH bool bDoPCPrematch = false; CGameRules::EPrematchState prematchState = m_pGameRules->GetPrematchState(); if (prematchState==CGameRules::ePS_Prematch) { int numRequiredPlayers = g_pGameCVars->g_minPlayersForRankedGame - m_pGameRules->GetPlayerCount(true); if ((numRequiredPlayers > 0) || (pGameLobby && pGameLobby->UseLobbyTeamBalancing() && !pGameLobby->IsGameBalanced())) { bDoPCPrematch = true; CPlaylistManager *pPlaylistManager = g_pGame->GetPlaylistManager(); if (pGameLobby && pPlaylistManager) { if (!pGameLobby->IsRankedGame() || pPlaylistManager->IsUsingCustomVariant()) { // Private games don't do prematch bDoPCPrematch = false; } } if (bDoPCPrematch) { // If we are waiting for players on pc, spawn ingame and set a prematch state which waits for players. m_pGameRules->StartPrematch(); startTimeLength = 0.f; } } if (!bDoPCPrematch) { m_pGameRules->SkipPrematch(); } } #endif m_pGameRules->ResetGameStartTimer(startTimeLength); StartCountdown(true); } } } else if (m_state == EGRS_PostGame) { const float prevUpdateStamp = m_timeInPostGame; const float timeInPost = (prevUpdateStamp + frameTime); const float timeToShowHUDMessage = g_pGameCVars->g_gameRules_postGame_HUDMessageTime; const float timeToShowTop3 = g_pGameCVars->g_gameRules_postGame_Top3Time; const float timeToShowScoreboard = g_pGameCVars->g_gameRules_postGame_ScoreboardTime; float killcamLength = m_pGameRules->GameEndedByWinningKill() ? g_pGameCVars->kc_length : 0.f; if (g_pGameCVars->kc_showHighlightsAtEndOfGame) { CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); if(pRecordingSystem) { killcamLength += pRecordingSystem->GetHighlightsReelLength(); killcamLength = min(killcamLength, 20.f); } } const float totalPostGameTime = timeToShowHUDMessage + timeToShowTop3 + timeToShowScoreboard + killcamLength; if (timeInPost > totalPostGameTime) { CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); if (!pRecordingSystem || (!pRecordingSystem->IsPlaybackQueued() && !pRecordingSystem->IsPlayingBack())) { CGameLobby *pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { CryLog("[GameRules] Server trying to return to lobby"); pGameLobby->SvFinishedGame(frameTime); } } else if(pRecordingSystem) { pRecordingSystem->StopHighlightReel(); } } m_timeInPostGame = timeInPost; } } CPlayer * pPlayer = static_cast<CPlayer*>(g_pGame->GetIGameFramework()->GetClientActor()); if((pPlayer && pPlayer->ShouldPlayIntro() || gEnv->bServer) && m_pGameRules->IsIntroSequenceRegistered() && !m_bHaveNotifiedIntroListeners) { // All flowgraph nodes that want to listen, should be created at this point OnIntroStart_NotifyListeners(); } #ifndef _RELEASE if(g_pGameCVars->g_hud_postgame_debug) { const char* stateName = ""; switch(m_state) { case EGRS_Reset: { stateName = "EGRS_Reset"; break;} case EGRS_Intro: { stateName = "EGRS_Intro"; break;} case EGRS_PreGame: { stateName = "EGRS_PreGame"; break;} case EGRS_InGame: { stateName = "EGRS_InGame"; break;} case EGRS_PostGame: { stateName = "EGRS_PostGame"; break;} case EGRS_MAX: { stateName = "EGRS_MAX"; break;} } CryWatch("GameRulesStandardState - State = %s", stateName); if(m_state == EGRS_PostGame) { const char* postGameStateName = ""; switch(m_postGameState) { case ePGS_Unknown: { postGameStateName = "ePGS_Unknown"; break; } case ePGS_Starting: { postGameStateName = "ePGS_Starting"; break; } case ePGS_HudMessage: { postGameStateName = "ePGS_HudMessage"; break; } case ePGS_FinalKillcam: { postGameStateName = "ePGS_FinalKillcam"; break; } case ePGS_HighlightReel: { postGameStateName = "ePGS_HighlightReel"; break; } case ePGS_Top3: { postGameStateName = "ePGS_Top3"; break; } case ePGS_Scoreboard: { postGameStateName = "ePGS_Scoreboard"; break; } } CryWatch("GameRulesStandardState -PostGameState = %s", postGameStateName); } } #endif if (gEnv->IsClient()) { if (m_state == EGRS_PreGame) { if( !gEnv->IsDedicated() ) { if (m_isStarting) { const float timeTillStartInSeconds = m_pGameRules->GetRemainingStartTimer(); SHUDEventWrapper::UpdateGameStartCountdown( ePreGameCountdown_MatchStarting, timeTillStartInSeconds ); } else { SHUDEventWrapper::UpdateGameStartCountdown( ePreGameCountdown_WaitingForPlayers, 0.0f ); } } } else if (m_state == EGRS_InGame && !gEnv->IsDedicated() ) { if (m_introMessageShown == false) // Show only once { CGameRules *pGameRules = g_pGame->GetGameRules(); if (pGameRules && pGameRules->HasGameActuallyStarted()) { if (EntityId localPlayerId = g_pGame->GetIGameFramework()->GetClientActorId()) { int teamId = g_pGame->GetGameRules()->GetTeam(localPlayerId); bool bTeamGame = (pGameRules->GetTeamCount() > 1); IActor *pActor = g_pGame->GetIGameFramework()->GetClientActor(); if (pActor->GetSpectatorMode()==CActor::eASM_None && !pActor->IsDead() && (!bTeamGame || teamId!=0)) { if (IGameRulesPlayerStatsModule *statsModule = pGameRules->GetPlayerStatsModule()) { const SGameRulesPlayerStat *stats = statsModule->GetPlayerStats(localPlayerId); if (stats->deaths <= 0) // Not died ever { if (m_startMatchString.empty() == false) { const char* gamemodeName = g_pGame->GetGameRules()->GetEntity()->GetClass()->GetName(); CryFixedStringT<32> strSignalName; strSignalName.Format("StartGame%s", gamemodeName); TAudioSignalID signalId = g_pGame->GetGameAudio()->GetSignalID(strSignalName); CryFixedStringT<64> localisedStartString = CHUDUtils::LocalizeString( m_startMatchString.c_str() ); if (bTeamGame) { CryFixedStringT<16> strTeamName; strTeamName.Format("@ui_hud_team_%d", teamId); SHUDEventWrapper::TeamMessage(strTeamName.c_str(), teamId, SHUDEventWrapper::SMsgAudio(signalId), false, true); SHUDEventWrapper::SimpleBannerMessage(localisedStartString.c_str(), SHUDEventWrapper::kMsgAudioNULL); } else { SHUDEventWrapper::RoundMessageNotify(localisedStartString.c_str(), SHUDEventWrapper::SMsgAudio(signalId)); } } } } m_introMessageShown = true; // Or not if has already died, but don't check again anyway. } } } } } else if(m_state == EGRS_PostGame && !gEnv->IsDedicated()) { if (!gEnv->bServer) { m_timeInPostGame += frameTime; } m_timeInCurrentPostGameState += frameTime; switch (m_postGameState) { case ePGS_Starting: { CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); if (pRecordingSystem != NULL && (pRecordingSystem->IsPlayingBack() || pRecordingSystem->IsPlaybackQueued())) { // Currently showing a killcam, skip to the killcam stage of the postgame flow EnterPostGameState(ePGS_FinalKillcam); } else { if (m_pGameRules->GetRoundsModule()) { EnterPostGameState(ePGS_Top3); } else { EnterPostGameState(ePGS_HudMessage); } } break; } case ePGS_HudMessage: { if (m_timeInCurrentPostGameState > g_pGameCVars->g_gameRules_postGame_HUDMessageTime) { EnterPostGameState(ePGS_FinalKillcam); } break; } case ePGS_FinalKillcam: { CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); if (!pRecordingSystem || !(pRecordingSystem->IsPlayingBack() || (pRecordingSystem->IsPlaybackQueued() && pRecordingSystem->HasWinningKillcam()))) { EnterPostGameState(ePGS_Top3); } #ifndef _RELEASE else if(g_pGameCVars->g_hud_postgame_debug && pRecordingSystem) { CryWatch("PostGameState - Waiting for final killcam to end:"); CryWatch("IsPlaybackQueued: %s, IsPlayingBack: %s", pRecordingSystem->IsPlaybackQueued() ? "True" : "False", pRecordingSystem->IsPlayingBack() ? "True" : "False"); } #endif break; } case ePGS_HighlightReel: { CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); if (!pRecordingSystem || (!pRecordingSystem->IsPlaybackQueued() && !pRecordingSystem->IsPlayingBack())) { CGameLobby *pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { CryLog("[GameRules] Client trying to return to lobby"); pGameLobby->SvFinishedGame(frameTime); EnterPostGameState(ePGS_LeavingGame); } } #ifndef _RELEASE else if(g_pGameCVars->g_hud_postgame_debug && pRecordingSystem) { CryWatch("PostGameState - Waiting for highlight reel to end:"); CryWatch("IsPlaybackQueued: %s, IsPlayingBack: %s, IsPlayingHighlightsReel: %s", pRecordingSystem->IsPlaybackQueued() ? "True" : "False", pRecordingSystem->IsPlayingBack() ? "True" : "False", pRecordingSystem->IsPlayingHighlightsReel() ? "True" : "False"); } #endif break; } case ePGS_Top3: { if (m_timeInCurrentPostGameState > g_pGameCVars->g_gameRules_postGame_Top3Time) { EnterPostGameState(ePGS_Scoreboard); } break; } case ePGS_Scoreboard: { if(m_timeInCurrentPostGameState > g_pGameCVars->g_gameRules_postGame_ScoreboardTime) { if(!m_bHasShownHighlightReel && g_pGameCVars->kc_showHighlightsAtEndOfGame) { EnterPostGameState(ePGS_HighlightReel); } else { CGameLobby *pGameLobby = g_pGame->GetGameLobby(); if (pGameLobby) { CryLog("[GameRules] Client trying to return to lobby [No highlight reel]"); pGameLobby->SvFinishedGame(frameTime); } } } break; } } } } }
void CAVMine::ProcessEvent(SEntityEvent &event) { if (m_frozen) return; switch(event.event) { case ENTITY_EVENT_ENTERAREA: { IEntity * pEntity = gEnv->pEntitySystem->GetEntity(event.nParam[0]); CGameRules* pGR = g_pGame->GetGameRules(); if(pEntity && pGR) { // if this is a team game, mines aren't set off by their own team if(pGR->GetTeamCount() > 0 && (m_teamId != 0 && pGR->GetTeam(pEntity->GetId()) == m_teamId)) break; // otherwise, not set off by the player who dropped them. if(pGR->GetTeamCount() == 0 && m_ownerId == pEntity->GetId()) break; // or a vehicle that player might happen to be in IVehicle* pVehicle = g_pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(event.nParam[0]); if(pVehicle && pVehicle->GetSeatForPassenger(m_ownerId)) break; IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus)) { // only count moving objects if(physStatus.v.GetLengthSquared() > 0.1f) m_currentWeight += physStatus.mass; if (m_currentWeight > m_triggerWeight) Explode(true); } } } break; } case ENTITY_EVENT_LEAVEAREA: { IEntity * pEntity = gEnv->pEntitySystem->GetEntity(event.nParam[0]); if(pEntity) { IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus)) { m_currentWeight -= physStatus.mass; if(m_currentWeight < 0) m_currentWeight = 0; } } } break; } default: break; } return CProjectile::ProcessEvent(event); }
void CAVMine::ProcessEvent(SEntityEvent &event) { if (m_frozen) return; switch(event.event) { case ENTITY_EVENT_ENTERAREA: { IEntity * pEntity = gEnv->pEntitySystem->GetEntity((EntityId)event.nParam[0]); CGameRules* pGR = g_pGame->GetGameRules(); if(pEntity && pGR) { // if this is a team game, mines aren't set off by their own team if(pGR->GetTeamCount() > 0 && (m_teamId != 0 && pGR->GetTeam(pEntity->GetId()) == m_teamId)) break; IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus)) { // only count moving objects if(physStatus.v.GetLengthSquared() > 0.1f) m_currentWeight += physStatus.mass; if (m_currentWeight > m_triggerWeight) Explode(true); } } } break; } case ENTITY_EVENT_LEAVEAREA: { IEntity * pEntity = gEnv->pEntitySystem->GetEntity((EntityId)event.nParam[0]); if(pEntity) { IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus)) { m_currentWeight -= physStatus.mass; if(m_currentWeight < 0) m_currentWeight = 0; } } } break; } default: break; } return CProjectile::ProcessEvent(event); }
void CHUDTagNames::Update() { CActor *pClientActor = static_cast<CActor *>(g_pGame->GetIGameFramework()->GetClientActor()); CGameRules *pGameRules = g_pGame->GetGameRules(); if(!pClientActor || !pGameRules || !gEnv->bMultiplayer) return; int iClientTeam = pGameRules->GetTeam(pClientActor->GetEntityId()); // Skip enemies, they need to be added only when shot // (except in spectator mode when we display everyone) for(int iTeam = 0; iTeam < pGameRules->GetTeamCount() + 1; ++iTeam) { if((iTeam == iClientTeam) || (pClientActor->GetSpectatorMode() != CActor::eASM_None)) { int iTeamPlayerCount = pGameRules->GetTeamPlayerCount(iTeam); for(int iPlayer=0; iPlayer<iTeamPlayerCount; iPlayer++) { IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pGameRules->GetTeamPlayer(iTeam,iPlayer)); if(!pActor) continue; // Never display the local player if(pActor == pClientActor) continue; // never display other spectators if(static_cast<CActor*>(pActor)->GetSpectatorMode() != CActor::eASM_None) continue; // never display the name of the player we're spectating (it's shown separately with their current health) if(pClientActor->GetSpectatorMode() == CActor::eASM_Follow && pClientActor->GetSpectatorTarget() == pActor->GetEntityId()) continue; DrawTagName(pActor); } } } IVehicleSystem *pVehicleSystem = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem(); if(!pVehicleSystem) return; IVehicleIteratorPtr pVehicleIter = pVehicleSystem->CreateVehicleIterator(); while(IVehicle *pVehicle=pVehicleIter->Next()) { SVehicleStatus rVehicleStatus = pVehicle->GetStatus(); if(0 == rVehicleStatus.passengerCount) continue; // Skip enemy vehicles, they need to be added only when shot (except in spectator mode...) bool bEnemyVehicle = true; for(int iSeatId=1; iSeatId<=pVehicle->GetLastSeatId(); iSeatId++) { IVehicleSeat *pVehicleSeat = pVehicle->GetSeatById(iSeatId); if(!pVehicleSeat) continue; EntityId uiEntityId = pVehicleSeat->GetPassenger(); if(0 == iClientTeam) { if(uiEntityId && IsFriendlyToClient(uiEntityId)) { bEnemyVehicle = false; } } else if(uiEntityId && pGameRules->GetTeam(uiEntityId) == iClientTeam) { bEnemyVehicle = false; } } if(bEnemyVehicle && (pClientActor->GetSpectatorMode() == CActor::eASM_None)) // again, draw enemies in spectator mode continue; DrawTagName(pVehicle); } // don't need to do any of this if we're in spectator mode - all player names will have been drawn above. if(pClientActor->GetSpectatorMode() == CActor::eASM_None) { for(TEnemyTagNamesList::iterator iter=m_enemyTagNamesList.begin(); iter!=m_enemyTagNamesList.end(); ++iter) { SEnemyTagName *pEnemyTagName = &(*iter); if(gEnv->pTimer->GetAsyncTime().GetSeconds() >= pEnemyTagName->fSpawnTime+((float) g_pGameCVars->hud_mpNamesDuration)) { // Note: iter=my_list.erase(iter) may not be standard/safe TEnemyTagNamesList::iterator iterNext = iter; ++iterNext; m_enemyTagNamesList.erase(iter); iter = iterNext; } else { IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEnemyTagName->uiEntityId); if(pActor) DrawTagName(pActor); IVehicle *pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(pEnemyTagName->uiEntityId); if(pVehicle) DrawTagName(pVehicle); } } } }