Esempio n. 1
0
// IWeaponEventListener
//---------------------------------------
void CMiscAnnouncer::OnShoot(IWeapon *pWeapon, EntityId shooterId, EntityId ammoId, IEntityClass* pAmmoType, const Vec3 &pos, const Vec3 &dir, const Vec3 &vel)
{
	if(!ma_enabled || !AnnouncerRequired())
		return;

	CWeapon *pWeaponImpl = static_cast<CWeapon*>(pWeapon);
	IEntityClass *pWeaponEntityClass = pWeaponImpl->GetEntity()->GetClass();
	g_pGame->GetWeaponSystem()->GetWeaponAlias().UpdateClass(&pWeaponEntityClass);

	DbgLog("CMiscAnnouncer::OnShoot() pWeaponImpl=%s; shooter=%d; pAmmoType=%s", pWeaponImpl->GetEntity()->GetName(), g_pGame->GetGameRules()->GetEntityName(shooterId), pAmmoType->GetName());
	
	TWeaponFiredMap::iterator it = m_weaponFiredMap.find(pWeaponEntityClass);
	if(it != m_weaponFiredMap.end())
	{
		SOnWeaponFired &onWeaponFired = it->second;

		DbgLog("CMiscAnnouncer::OnShoot() has found the firing weaponClass in our weaponFiredMap. With announcement=%s", onWeaponFired.m_announcementName.c_str());

		// we only want to play the announcement once each game/round
		IActor *pClientActor = gEnv->pGame->GetIGameFramework()->GetClientActor();
		CGameRules *pGameRules = g_pGame->GetGameRules();
		int clientTeam = pGameRules->GetTeam(pClientActor->GetEntityId());
		int shooterTeam = pGameRules->GetTeam(shooterId);
		
		if (clientTeam == shooterTeam)
		{
			if (!onWeaponFired.m_havePlayedFriendly)
			{
				DbgLog("CMiscAnnouncer::OnShoot() we've not played this friendly annoucement already. Let's do it");
				CAnnouncer::GetInstance()->Announce(shooterId, onWeaponFired.m_announcementID, CAnnouncer::eAC_inGame);
			}
			else
			{
				DbgLog("CMiscAnnouncer::OnShoot() we've already played this friendly announcement. Not playing again");
			}
			onWeaponFired.m_havePlayedFriendly = true;
		}
		else
		{
			if (!onWeaponFired.m_havePlayedEnemy)
			{
				DbgLog("CMiscAnnouncer::OnShoot() we've not played this enemy announcement already. Let's do it");
				CAnnouncer::GetInstance()->Announce(shooterId, onWeaponFired.m_announcementID, CAnnouncer::eAC_inGame);
			}
			else
			{
				DbgLog("CMiscAnnouncer::OnShoot() we've already played this enemy announcement. Not playing again.");
			}
			onWeaponFired.m_havePlayedEnemy = true;
		}
	}
}
Esempio n. 2
0
	bool AllowedToTargetPlayer(const EntityId attackerId, const EntityId victimEntityId)
	{
		CGameRules *pGameRules = g_pGame->GetGameRules();
		if(pGameRules && pGameRules->IsTeamGame())
		{
			const int clientTeamId = pGameRules->GetTeam(attackerId);
			const int victimTeamId = pGameRules->GetTeam(victimEntityId);

			return (clientTeamId != victimTeamId) || (g_pGameCVars->g_friendlyfireratio > 0.0f);
		}

		return true; 
	}
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;
}
Esempio n. 4
0
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;
}
//---------------------------------------
//Returns signal index of 0 (for team 0 and 1) and 1 for team 2
int CAreaAnnouncer::GetAreaAnnouncerTeamIndex(const EntityId clientId)
{
	int team = 0;
	CGameRules* pGameRules = g_pGame->GetGameRules();
	if(pGameRules)
	{
		team = pGameRules->GetTeam(clientId);
	}
	return CLAMP(team - 1, 0, AREA_ANNOUNCERS - 1);
}
Esempio n. 6
0
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 CDangerousRigidBody::ProcessEvent( SEntityEvent& event )
{
	switch(event.event)
	{
	case ENTITY_EVENT_COLLISION:
		{
			if(m_dangerous)
			{
				EventPhysCollision *pCollision = (EventPhysCollision *)(event.nParam[0]);
				if(pCollision->pEntity[0] && pCollision->pEntity[1])
				{
					IPhysicalEntity* pOtherEntityPhysics = GetEntity()->GetPhysics() != pCollision->pEntity[0] ? pCollision->pEntity[0] : pCollision->pEntity[1];
					if( IEntity* pOtherEntity = gEnv->pEntitySystem->GetEntityFromPhysics(pOtherEntityPhysics) )
					{
						EntityId localClientId = gEnv->pGame->GetIGameFramework()->GetClientActorId();
						if(pOtherEntity->GetId() == localClientId) //Handle collision locally 
						{
							float currentTime = gEnv->pTimer->GetFrameStartTime().GetSeconds();
							if(currentTime - m_lastHitTime >  m_timeBetweenHits)
							{
								CGameRules* pGameRules = g_pGame->GetGameRules();

								bool sameTeam = m_activatorTeam && (pGameRules->GetTeam(localClientId) == m_activatorTeam);
								float damageDealt = !sameTeam ? m_damageDealt : g_pGameCVars->g_friendlyfireratio * m_damageDealt;

								Vec3 rigidBodyPos = GetEntity()->GetWorldPos();

								HitInfo hitInfo(0, localClientId, 0,
									damageDealt, 0.0f, 0, 0,
									sDangerousRigidBodyHitTypeId, rigidBodyPos, (pOtherEntity->GetWorldPos()-rigidBodyPos).GetNormalized(), Vec3(ZERO));
								pGameRules->ClientHit(hitInfo);
								m_lastHitTime = currentTime;
							}
						}
					}
				}
			}
		}
		break;
	case ENTITY_EVENT_RESET:
		{
			Reset();
		}
		break;
	}
}
void CServerPlayerTracker::KillOccurred(const HitInfo &hitInfo, uint16 victimChannelId, bool bExpectKillCam)
{
	if(hitInfo.targetId != GetEntityId() && bExpectKillCam) //We don't expect killcams when a player kills themselves
	{
		SKillCamValidation& victimData = GetOrCreateVictimData(victimChannelId);

		victimData.vLastKillDir = hitInfo.dir;
		victimData.uKills++;
		victimData.fLastKillTime = gEnv->pTimer->GetCurrTime();
	}

	CGameRules * pGameRules = g_pGame->GetGameRules();

	CGameRules::eThreatRating threatRating = pGameRules->GetThreatRatingByTeam(pGameRules->GetTeam(hitInfo.targetId), pGameRules->GetTeam(GetEntityId()));

	if(threatRating == CGameRules::eHostile)
	{
		m_nTotalHostileKills++;
	}
}
Esempio n. 9
0
void CUIObjectives::OnRequestMissionObjectives( const SUIEvent& event )
{
	CGameRules* pGameRules = GetGameRules();
	if ( pGameRules && g_pGame->GetIGameFramework()->GetClientActor() )
	{
		CActor* pActor = pGameRules->GetActorByChannelId( g_pGame->GetIGameFramework()->GetClientActor()->GetChannelId() );
		if ( pActor )
		{
			std::map< string, int > tmpList;
			int teamID = pGameRules->GetTeam( pActor->GetEntityId() );
			for ( TObjectiveMap::iterator it = m_ObjectiveMap.begin(); it != m_ObjectiveMap.end(); ++it )
			{
				CGameRules::TObjective* pObjective = pGameRules->GetObjective( teamID, it->first.c_str() );
				if ( pObjective )
					tmpList[ it->first ] = pObjective->status;
			}
			for ( std::map< string, int >::iterator it = tmpList.begin(); it != tmpList.end(); ++it )
				MissionObjectiveAdded( it->first, it->second );
		}
	}

}
//------------------------------------------------------------------------
EGameRulesMissionObjectives CGameRulesKingOfTheHillObjective::GetIcon( SHoldEntityDetails *pDetails, const char **ppOutName, const char **ppOutColour )
{
	SKotHEntity *pKotHEntity = static_cast<SKotHEntity*>(pDetails->m_pAdditionalData);
	CRY_ASSERT(pKotHEntity);

	EGameRulesMissionObjectives requestedIcon = EGRMO_Unknown;

	if (!pDetails->m_id)
	{
		requestedIcon = EGRMO_Unknown;
	}
	else
	{
		bool iconAllowed = true;
		if (!m_shouldShowIconFunc.empty())
		{
			IEntity *pEntity = gEnv->pEntitySystem->GetEntity(pDetails->m_id);
			if (pEntity)
			{
				IScriptTable *pEntityScript = pEntity->GetScriptTable();
				HSCRIPTFUNCTION iconCheckFunc;
				if (pEntityScript != NULL && pEntityScript->GetValue(m_shouldShowIconFunc.c_str(), iconCheckFunc))
				{
					IScriptSystem *pScriptSystem = gEnv->pScriptSystem;
					bool result = false;
					if (Script::CallReturn(pScriptSystem, iconCheckFunc, pEntityScript, result))
					{
						if (!result)
						{
							requestedIcon = EGRMO_Unknown;
							iconAllowed = false;
						}
					}
				}
			}
		}

		if (iconAllowed)
		{
			const char *pFriendlyColour = "#9AD5B7";
			const char *pHostileColour = "#AC0000";
			const char *pNeutralColour = "#666666";

			CGameRules *pGameRules = g_pGame->GetGameRules();
			int localTeamId = pGameRules->GetTeam(g_pGame->GetIGameFramework()->GetClientActorId());

			if ( (pDetails->m_controllingTeamId == 0) )
			{
				requestedIcon = m_neutralIcon;
				*ppOutName = m_iconTextCapture.c_str();
				*ppOutColour = pNeutralColour;
			}
			else if( (pDetails->m_controllingTeamId == CONTESTED_TEAM_ID) )
			{
				requestedIcon = m_contestedIcon;
				*ppOutName = m_iconTextClear.c_str();
				*ppOutColour = pHostileColour;
			}
			else if (pDetails->m_controllingTeamId == localTeamId)
			{
				requestedIcon = m_friendlyIcon;
				*ppOutName = m_iconTextDefend.c_str();
				*ppOutColour = pFriendlyColour;
			}
			else
			{
				requestedIcon = m_hostileIcon;
				*ppOutName = m_iconTextClear.c_str();
				*ppOutColour = pHostileColour;
			}
		}
	}

	return requestedIcon;
}
//------------------------------------------------------------------------
void CGameRulesKingOfTheHillObjective::ClSiteChangedOwner( SHoldEntityDetails *pDetails, int oldTeamId )
{
	// Site has been captured
	CGameRules *pGameRules = g_pGame->GetGameRules();
	EntityId clientActorId = g_pGame->GetIGameFramework()->GetClientActorId();
	int localTeam = pGameRules->GetTeam(clientActorId);

	SKotHEntity *pKotHEntity = static_cast<SKotHEntity*>(pDetails->m_pAdditionalData);
	CRY_ASSERT(pKotHEntity);

	const int ownerTeamId = pDetails->m_controllingTeamId;
	if (ownerTeamId > 0)
	{
		ClSiteChangedOwnerAnnouncement(pDetails, clientActorId, ownerTeamId, localTeam);

		if (localTeam == ownerTeamId)
		{
			CCCPOINT(KingOfTheHillObjective_SiteCapturedByFriendlyTeam);
			if (!m_friendlyCaptureString.empty())
			{
				SHUDEventWrapper::GameStateNotify(m_friendlyCaptureString.c_str());
			}
			if (!m_gameStateFriendlyString.empty())
			{
				const char *localisedMessage = CHUDUtils::LocalizeString(m_gameStateFriendlyString.c_str());
				SHUDEventWrapper::OnGameStatusUpdate(eGBNFLP_Good, localisedMessage);
			}
		}
		else
		{
			CCCPOINT(KingOfTheHillObjective_SiteCapturedByEnemyTeam);
			if (!m_enemyCaptureString.empty())
			{
				SHUDEventWrapper::GameStateNotify(m_enemyCaptureString.c_str());
			}
			if (!m_gameStateEnemyString.empty())
			{
				const char *localisedMessage = CHUDUtils::LocalizeString(m_gameStateEnemyString.c_str());
				SHUDEventWrapper::OnGameStatusUpdate(eGBNFLP_Bad, localisedMessage);
			}
		}
	}
	else if (oldTeamId > 0)
	{
		if (localTeam == oldTeamId)
		{
			CCCPOINT(KingOfTheHillObjective_SiteLostByFriendlyTeam);
			if (!m_friendlyLostString.empty())
			{
				SHUDEventWrapper::GameStateNotify(m_friendlyLostString.c_str());
			}
		}
		else
		{
			CCCPOINT(KingOfTheHillObjective_SiteLostByEnemyTeam);
			if (!m_enemyLostString.empty())
			{
				SHUDEventWrapper::GameStateNotify(m_enemyLostString.c_str());
			}
		}

		if (!m_gameStateNeutralString.empty())
		{
			const char *localisedMessage = CHUDUtils::LocalizeString(m_gameStateNeutralString.c_str());
			SHUDEventWrapper::OnGameStatusUpdate(eGBNFLP_Neutral, localisedMessage);
		}
	}

	int currActiveIndex = -1;
	for (int i = 0; i < HOLD_OBJECTIVE_MAX_ENTITIES; i ++)
	{
		if( !m_entities[i].m_id)
		{
			continue;
		}
		++currActiveIndex;

		if( &m_entities[i] != pDetails )
		{
			continue;
		}

		CRY_TODO( 23,03,2010, "HUD: OnSiteCaptured events are being sent multiple times from multiple places. /FH");
		SHUDEvent siteIsCaptured(eHUDEvent_OnSiteCaptured);
		siteIsCaptured.eventIntData = currActiveIndex;
		siteIsCaptured.eventIntData2 = ownerTeamId;
		CHUDEventDispatcher::CallEvent(siteIsCaptured);
	}
}
//------------------------------------------------------------------------
void CGameRulesKingOfTheHillObjective::Update( float frameTime )
{
	BaseType::Update(frameTime);

	CGameRules *pGameRules = g_pGame->GetGameRules();
	IGameRulesScoringModule *pScoringModule = pGameRules->GetScoringModule();

	const int localTeamId = pGameRules->GetTeam(g_pGame->GetIGameFramework()->GetClientActorId());

	for (int i = 0; i < HOLD_OBJECTIVE_MAX_ENTITIES; ++ i)
	{
		SHoldEntityDetails *pDetails = &m_entities[i];
		if (!pDetails->m_id)
		{
			continue;
		}

		SKotHEntity *pKotHEntity = static_cast<SKotHEntity *>(pDetails->m_pAdditionalData);
		CRY_ASSERT(pKotHEntity);

		if (gEnv->bServer && pScoringModule)
		{
#ifndef _RELEASE
			if (g_pGameCVars->g_KingOfTheHillObjective_watchLvl)
			{
				IEntity *pEntity = gEnv->pEntitySystem->GetEntity(pDetails->m_id);
				const char *pEntName = pEntity ? pEntity->GetName() : "<NULL>";
				if (pDetails->m_controllingTeamId == CONTESTED_TEAM_ID)
				{
					CryWatch("KotH entity '%s' is contested", pEntName);
				}
				else if (pDetails->m_controllingTeamId == 0)
				{
					CryWatch("KotH entity '%s' has no players nearby", pEntName);
				}
				else
				{
					CryWatch("KotH entity '%s' controlled by team %i, scoreTimerLength='%.2f', timeSinceLastScore='%.2f'", 
						pEntName, pDetails->m_controllingTeamId, pKotHEntity->m_scoreTimerLength, pKotHEntity->m_timeSinceLastScore);
				}
			}
#endif

			if (pKotHEntity->m_scoringTeamId)
			{
				const int teamIndex = pKotHEntity->m_scoringTeamId - 1;
				CRY_ASSERT_MESSAGE(teamIndex >= 0 && teamIndex < NUM_TEAMS, "Update() scoringTeamId is out of range");

				pKotHEntity->m_timeSinceLastScore += frameTime;

				if (pKotHEntity->m_timeSinceLastScore >= pKotHEntity->m_scoreTimerLength)
				{
					pScoringModule->OnTeamScoringEvent(teamIndex + 1, EGRST_KingOfTheHillObjectiveHeld);
					pKotHEntity->m_timeSinceLastScore = 0.f;
					AwardPlayerPoints(&pDetails->m_insideEntities[teamIndex], EGRST_KingOfTheHillObjectiveHeld);
					CCCPOINT_IF((pKotHEntity->m_scoringTeamId == 1), KingOfTheHillObjective_TeamMarinesScored);
					CCCPOINT_IF((pKotHEntity->m_scoringTeamId == 2), KingOfTheHillObjective_TeamCellScored);
				}
			}
		}
		if (gEnv->IsClient())
		{
			if (m_useIcons && pKotHEntity->m_needsIconUpdate)
			{
				UpdateIcon(pDetails);
			}

			if (pGameRules->GetGameMode() == eGM_CrashSite)
			{
				if (pDetails->m_localPlayerIsWithinRange && pDetails->m_controllingTeamId != CONTESTED_TEAM_ID)
				{
					CPersistantStats::GetInstance()->IncrementClientStats(EFPS_CrashSiteHeldTime, frameTime);
				}
			}

			if (pKotHEntity->m_bPulseEnabled)
			{
				pKotHEntity->m_pulseTime -= frameTime;
				if (pKotHEntity->m_pulseTime < 0.f)
				{
					eRadiusPulseType pulseType = GetPulseType(pDetails);
					const float radiusEffectScale = pKotHEntity->m_radiusEffectScale * pDetails->m_controlRadius;
					RadiusEffectPulse(pDetails->m_id, pulseType, radiusEffectScale);
					pKotHEntity->m_pulseTime = m_pulseTimerLength;
				}
			}
			else
			{
				if (!m_shouldDoPulseEffectFunc.empty())
				{
					IEntity *pEntity = gEnv->pEntitySystem->GetEntity(pDetails->m_id);
					if (pEntity)
					{
						IScriptTable *pEntityScript = pEntity->GetScriptTable();
						HSCRIPTFUNCTION pulseCheckFunc;
						if (pEntityScript != NULL && pEntityScript->GetValue(m_shouldDoPulseEffectFunc.c_str(), pulseCheckFunc))
						{
							IScriptSystem *pScriptSystem = gEnv->pScriptSystem;
							bool result = false;
							if (Script::CallReturn(pScriptSystem, pulseCheckFunc, pEntityScript, result))
							{
								pKotHEntity->m_bPulseEnabled = result;
							}
						}
					}
				}
			}

			const float fOldScoringSFX = pKotHEntity->m_fScoringSFX;

			if(pKotHEntity->m_scoringTeamId)
			{
				pKotHEntity->m_fScoringSFX = min(pKotHEntity->m_fScoringSFX + (frameTime * 2.0f), 1.0f);
			}
			else
			{
				pKotHEntity->m_fScoringSFX = max(pKotHEntity->m_fScoringSFX - (frameTime * 1.0f), 0.0f);
			}

			if(pKotHEntity->m_fScoringSFX != fOldScoringSFX)
				UpdateEntityAudio(pDetails);
		}
	}
}
Esempio n. 13
0
void CHUDTagNames::DrawTagName(IVehicle *pVehicle)
{
	CRY_ASSERT(pVehicle);
	if(!pVehicle)
		return;

	CActor *pClientActor = static_cast<CActor *>(g_pGame->GetIGameFramework()->GetClientActor());
	CGameRules *pGameRules = g_pGame->GetGameRules();
	int iClientTeam = pGameRules->GetTeam(pClientActor->GetEntityId());
	bool bThirdPerson = pClientActor->IsThirdPerson();

	bool bDrawSeatTagNames = false;
	if(pClientActor->GetSpectatorMode() == CActor::eASM_Follow)
	{
		IActor *pFollowedActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pClientActor->GetSpectatorTarget());
		if(pFollowedActor)
			bDrawSeatTagNames = (pVehicle == pFollowedActor->GetLinkedVehicle());
	}
	else
		bDrawSeatTagNames = (pVehicle == pClientActor->GetLinkedVehicle());

	if(bDrawSeatTagNames)
	{
		// When this is local player vehicle, we always display all passengers name above their head so that he can identify them

		for(int iSeatId=1; iSeatId<=pVehicle->GetLastSeatId(); iSeatId++)
		{
			IVehicleSeat *pVehicleSeat = pVehicle->GetSeatById(iSeatId);
			if(!pVehicleSeat)
				continue;

			IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pVehicleSeat->GetPassenger());
			if(!pActor || (pActor == pClientActor && !bThirdPerson))
				continue;

			DrawTagName(pActor,true);
		}

		return;
	}

	ColorF rgbTagName = COLOR_ENEMY;

	// Driver seat is always 1
	IVehicleSeat *pVehicleSeat = pVehicle->GetSeatById(1);
	if(!pVehicleSeat)
		return;

	IVehicleHelper *pVehicleHelper = pVehicleSeat->GetSitHelper();
	if(!pVehicleHelper)
		return;

	Vec3 vWorldPos = pVehicleHelper->GetWorldTM().GetTranslation();

	// Add some offset to be above the driver/pilot
	vWorldPos.z += 1.2f;

	AABB box; 
	pVehicle->GetEntity()->GetWorldBounds(box);

	bool bDrawOnTop = false;

	if(ProjectOnSphere(vWorldPos,box))
	{
		bDrawOnTop = true;
	}

	m_tagNamesVector.resize(0);

	for(int iSeatId=1; iSeatId<=pVehicle->GetLastSeatId(); iSeatId++)
	{
		IVehicleSeat *pVehicleSeat = pVehicle->GetSeatById(iSeatId);
		if(!pVehicleSeat)
			continue;

		EntityId uiEntityId = pVehicleSeat->GetPassenger();

		IActor *pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(uiEntityId);
		if(!pActor)
			continue;

		const char *szRank = GetPlayerRank(uiEntityId);

		IEntity *pEntity = pActor->GetEntity();
		if(!pEntity)
			continue;

		char szText[HUD_MAX_STRING_SIZE];
		if(szRank)
		{
			sprintf(szText,"%s %s",szRank,pEntity->GetName());
		}
		else
		{
			sprintf(szText,"%s",pEntity->GetName());
		}

		if(0 == iClientTeam)
		{
			if(uiEntityId && IsFriendlyToClient(uiEntityId))
			{
				rgbTagName = COLOR_FRIEND;
			}
		}
		else if(uiEntityId && pGameRules->GetTeam(uiEntityId) == iClientTeam)
		{
			rgbTagName = COLOR_FRIEND;
		}
		
		if(pActor->GetHealth() <= 0)
		{
			rgbTagName = COLOR_DEAD;
		}

		m_tagNamesVector.resize(m_tagNamesVector.size()+1);

		STagName *pTagName = &m_tagNamesVector[m_tagNamesVector.size()-1];

		pTagName->strName			= szText;
		pTagName->vWorld			= vWorldPos;
		pTagName->bDrawOnTop	= bDrawOnTop;
		pTagName->rgb					= rgbTagName;
	}

	DrawTagNames();
}
Esempio n. 14
0
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);
			}
		}
	}
}
//------------------------------------------------------------------------
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;
}
Esempio n. 17
0
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);
}
Esempio n. 18
0
void CHUDTagNames::DrawTagName(IActor *pActor,bool bLocalVehicle)
{
	CRY_ASSERT(pActor);
	if(!pActor)
		return;

	IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor();
	CGameRules *pGameRules = g_pGame->GetGameRules();
	int iClientTeam = pGameRules->GetTeam(pClientActor->GetEntityId());

	if(!bLocalVehicle && pActor->GetLinkedVehicle())
		return;
	
	const char *szRank = GetPlayerRank(pActor->GetEntityId());

	IEntity *pEntity = pActor->GetEntity();
	if(!pEntity)
		return;

	char szText[HUD_MAX_STRING_SIZE];
	if(szRank)
	{
		sprintf(szText,"%s %s",szRank,pEntity->GetName());
	}
	else
	{
		sprintf(szText,"%s",pEntity->GetName());
	}

	ICharacterInstance *pCharacterInstance = pEntity->GetCharacter(0);
	if(!pCharacterInstance)
		return;

	ISkeletonPose *pSkeletonPose = pCharacterInstance->GetISkeletonPose();
	if(!pSkeletonPose)
		return;

	int16 sHeadID = pSkeletonPose->GetJointIDByName("Bip01 Head");
	if(-1 == sHeadID)
		return;

	Matrix34 matWorld = pEntity->GetWorldTM() * Matrix34(pSkeletonPose->GetAbsJointByID(sHeadID));

	Vec3 vWorldPos = matWorld.GetTranslation();

	// Who has a bigger head? :)
	vWorldPos.z += 0.4f;

	AABB box; 
	pEntity->GetWorldBounds(box);

	bool bDrawOnTop = bLocalVehicle;

	if(ProjectOnSphere(vWorldPos,box))
	{
		bDrawOnTop = true;
	}

	ColorF rgbTagName = COLOR_ENEMY;

	if(0 == iClientTeam)
	{
		if(IsFriendlyToClient(pActor->GetEntityId()))
		{
			rgbTagName = COLOR_FRIEND;
		}
	}
	else if(pGameRules->GetTeam(pActor->GetEntityId()) == iClientTeam)
	{
		rgbTagName = COLOR_FRIEND;
	}

	if(pActor->GetHealth() <= 0)
	{
		rgbTagName = COLOR_DEAD;
	}

	m_tagNamesVector.resize(1);

	for(std::vector<EntityId>::iterator iter=SAFE_HUD_FUNC_RET(GetRadar()->GetSelectedTeamMates())->begin(); iter!=SAFE_HUD_FUNC_RET(GetRadar()->GetSelectedTeamMates())->end(); ++iter)
	{
		if(pActor->GetEntityId() == *iter)
		{
			// Teammate is selected in radar, force the visibility of that name					
			bDrawOnTop = true;
			break;
		}
	}

	STagName *pTagName = &m_tagNamesVector[0];

	pTagName->strName			= szText;
	pTagName->vWorld			= vWorldPos;
	pTagName->bDrawOnTop	= bDrawOnTop;
	pTagName->rgb					= rgbTagName;

	DrawTagNames();
}
Esempio n. 19
0
//------------------------------------------------------------------------
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));
		}
	}
}
Esempio n. 20
0
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);
}
Esempio n. 21
0
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);
}
Esempio n. 22
0
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);
	}
}
Esempio n. 23
0
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;
}