void CGameRulesRSSpawning::PopulateSpawnData(SUsefulSpawnData& spawnData, EntityId playerId)
{

	int playerTeamId = m_pGameRules->GetTeam(playerId);
	int enemyTeamId	 = m_pGameRules->GetEnemyTeamId(playerTeamId);

	spawnData.playerId			= playerId;	

	spawnData.playerTeamId	= playerTeamId;

	spawnData.enemyTeamId		= enemyTeamId;

	
	//Find out how many enemy players are active
	int numActiveEnemyPlayers = 0;
	EntityId enemyPlayerId = 0;
	while( enemyPlayerId = m_pGameRules->GetTeamActivePlayer(enemyTeamId, numActiveEnemyPlayers++));

	//numActiveEnemyPlayers gets incremented after the call regardless of whether a player was found or not
	spawnData.numActiveEnemyPlayers = numActiveEnemyPlayers - 1;

	//Find out how many friendly players are active
	int numActiveFriendlyPlayers = 0;
	EntityId friendlyPlayerId = 0;
	while( friendlyPlayerId = m_pGameRules->GetTeamActivePlayer(playerTeamId, numActiveFriendlyPlayers++));

	//numActiveFriendlyPlayers gets incremented after the call regardless of whether a player was found or not
	spawnData.numActiveFriendlyPlayers = numActiveFriendlyPlayers - 1;

	spawnData.isInitialSpawn = IsPlayerInitialSpawning(playerId);
}
Esempio n. 2
0
CGameRulesSpawningBase::TSpawnLocations& CGameRulesSpawningBase::GetSpawnLocations(const EntityId playerId)
{
	if (m_initialSpawnLocations.empty())
	{
		return m_spawnLocations;
	}

	if (IsPlayerInitialSpawning(playerId))
	{
		return m_initialSpawnLocations[m_activeInitialSpawnGroupIndex].m_locations;
	}
	return m_spawnLocations;
}
EntityId CGameRulesRSSpawning::GetSpawnLocationNonTeamGame(EntityId playerId, const Vec3 &deathPos)
{
#if MONITOR_BAD_SPAWNS
	m_DBG_spawnData.scoringResults.clear();
#endif

	EntityId bestSpawnerId = 0;

	const bool bCheckLineOfSight = !gEnv->IsDedicated();

	TSpawnLocations& spawnLocations = GetSpawnLocations(playerId);
	if (m_pGameRules->GetLivingPlayerCount() > 0)
	{
		float fBestScore = FLT_MAX;

		SUsefulSpawnData spawnData;

		PopulateSpawnData(spawnData, playerId);

		int iSpawnIndex = 0;
		
		for (TSpawnLocations::const_iterator it=spawnLocations.begin(); it!=spawnLocations.end(); ++it)
		{
			SpawnLogAlways("[SPAWN] Spawn #%d", iSpawnIndex);

			EntityId spawnId(*it);

			const IEntity *pSpawn = gEnv->pEntitySystem->GetEntity(spawnId);

			Vec3 spawnPosition = pSpawn->GetPos();

			const float fScoreFromEnemies					= GetScoreFromProximityToEnemiesNoTeams(spawnData, spawnPosition);
			const float fScoreFromExclusionZones	= GetScoreFromProximityToExclusionZones(spawnData, spawnId);
			const float fScoreFromLineOfSight			= bCheckLineOfSight ? GetScoreFromLineOfSight(spawnData, spawnId) : 0.f;

			const float fScore = fScoreFromEnemies + fScoreFromExclusionZones + fScoreFromLineOfSight;

#if MONITOR_BAD_SPAWNS
			m_DBG_spawnData.scoringResults.push_back(SScoringResults(fScoreFromEnemies, fScoreFromLineOfSight > 0, fScoreFromExclusionZones > 0));
#endif

			if(fScore < fBestScore)
			{
				if(IsSpawnLocationSafe(spawnData.playerId, pSpawn, 1.0f, false, 0.0f))
				{
					SpawnLogAlways("[SPAWN] >> Total score %.6f, better than previous best of %.6f", fScore, fBestScore);
					bestSpawnerId = spawnId;
					fBestScore		= fScore;
#if MONITOR_BAD_SPAWNS
					m_DBG_spawnData.iSelectedSpawnIndex = iSpawnIndex;
					m_DBG_spawnData.selectedSpawn				= spawnId;
#endif
				}
				else
				{
					SpawnLogAlways("[SPAWN] >> Total score %.6f, better than %.6f but UNSAFE", fScore, fBestScore);
				}		
			}
			else
			{
				SpawnLogAlways("[SPAWN] >> Total score %.6f, too high, not using", fScore);
			}

			iSpawnIndex++;
		}
	}
	else
	{
		bool isInitialSpawn = IsPlayerInitialSpawning(playerId);
		bestSpawnerId = GetRandomSpawnLocation_Cached(spawnLocations, playerId, 0, isInitialSpawn);
	}

	return bestSpawnerId;
}
EntityId CGameRulesRSSpawning::GetBestSpawnUsingWeighting( SUsefulSpawnData& spawnData, const Vec3 * pBestLocation )
{
	float fBestScore = FLT_MAX;
	EntityId bestSpawnerId = 0;
	const Vec3 idealLocation = *pBestLocation;

	TPositionList FriendlyPositions, EnemyPositions;
	TMultiplierList FriendlyScoreMultipliers;
	FriendlyPositions.reserve(spawnData.numActiveFriendlyPlayers);
	FriendlyScoreMultipliers.reserve(spawnData.numActiveFriendlyPlayers);
	EnemyPositions.reserve(spawnData.numActiveEnemyPlayers);

	UpdateFriendlyPlayerPositionsAndMultipliers(spawnData, FriendlyPositions, FriendlyScoreMultipliers);
	UpdateEnemyPlayerPositions(spawnData, EnemyPositions);

	SpawnLogAlways("[SPAWN] Ideal location calculated as (%.2f, %.2f, %.2f)", idealLocation.x, idealLocation.y, idealLocation.z);

	int iSpawnIndex = 0;

#if MONITOR_BAD_SPAWNS
	m_DBG_spawnData.scoringResults.clear();
#endif

	EntityId lastSpawnId = 0;
	Vec3 lastSpawnPos(ZERO);
	{
		TPlayerDataMap::iterator it = m_playerValues.find(spawnData.playerId);
		if (it != m_playerValues.end())
		{
			lastSpawnId		= it->second.lastSpawnLocationId;

			if(lastSpawnId)
			{
				IEntity * pLastSpawnEnt = gEnv->pEntitySystem->GetEntity(lastSpawnId);
				lastSpawnPos	= pLastSpawnEnt->GetWorldPos();
			}
		}
	}

	EntityId lastPrecachedSpawnId = 0;
	Vec3 lastPrecachedSpawnPos(ZERO);
	if(spawnData.playerId==g_pGame->GetClientActorId())
	{
		if(IEntity* pLastPrecachedSpawnEnt = gEnv->pEntitySystem->GetEntity(m_currentBestSpawnId))
		{
			lastPrecachedSpawnId = m_currentBestSpawnId;
			lastPrecachedSpawnPos = pLastPrecachedSpawnEnt->GetWorldPos();
		}
	}

	TSpawnLocations& spawnLocations = GetSpawnLocations(spawnData.playerId);

#if !defined(_RELEASE)
	int nWrongTeamSpawns = 0, nUnsafeSpawns = 0;
#endif

	bool bCheckLineOfSight = !gEnv->IsDedicated();
	for (TSpawnLocations::const_iterator it=spawnLocations.begin(); it!=spawnLocations.end(); ++it)
	{
		SpawnLogAlways("[SPAWN] Spawn #%d", iSpawnIndex);

		EntityId spawnId(*it);

		int spawnTeam=GetSpawnLocationTeam(spawnId);
		if ((spawnTeam == 0) || (spawnTeam == spawnData.playerTeamId))
		{
			const IEntity *pSpawn = gEnv->pEntitySystem->GetEntity(spawnId);

			Vec3 spawnPosition = pSpawn->GetPos();

			const float fScoreFromEnemies			= GetScoreFromProximityToEnemies(spawnData, EnemyPositions, spawnPosition);
			const float fScoreFromFriendlies	= GetScoreFromProximityToFriendlies(spawnData, FriendlyPositions, FriendlyScoreMultipliers, spawnPosition);
			const float fScoreFromIdealPosn		=	GetScoreFromProximityToIdealLocation(spawnData, idealLocation, spawnPosition);
			const float fScoreFromExclusions	= GetScoreFromProximityToExclusionZones(spawnData, spawnId);
			const float fScoreFromLineOfSight	=	bCheckLineOfSight ? GetScoreFromLineOfSight(spawnData, spawnId) : 0.f;
			float fScoreFromLastSpawn		= 0.0f;
			
			if(lastSpawnId != 0)
				fScoreFromLastSpawn = GetScoreFromProximityToPreviousSpawn(lastSpawnPos, spawnPosition);
			
			float fScoreFromLastSelectedSpawn = 0.0f;
			if(lastPrecachedSpawnId)
				fScoreFromLastSelectedSpawn = GetScoreFromProximityToLastPrecachedSpawn(lastPrecachedSpawnPos, spawnPosition);

			const float fScore = fScoreFromEnemies + fScoreFromFriendlies + fScoreFromIdealPosn + fScoreFromExclusions + fScoreFromLineOfSight + fScoreFromLastSpawn;

#if MONITOR_BAD_SPAWNS
			m_DBG_spawnData.scoringResults.push_back(SScoringResults(fScoreFromEnemies, fScoreFromFriendlies, fScoreFromIdealPosn, fScoreFromLineOfSight > 0, fScoreFromExclusions > 0));
#endif

			if(fScore < fBestScore)
			{
				if(IsSpawnLocationSafe(spawnData.playerId, pSpawn, 1.0f, false, 0.0f))
				{
					SpawnLogAlways("[SPAWN] >> Total score %.6f, better than previous best of %.6f", fScore, fBestScore);
					bestSpawnerId = spawnId;
					fBestScore		= fScore;
#if MONITOR_BAD_SPAWNS
					m_DBG_spawnData.iSelectedSpawnIndex = iSpawnIndex;
					m_DBG_spawnData.selectedSpawn				= spawnId;
#endif
				}
				else
				{
#if !defined(_RELEASE)
					nUnsafeSpawns++;
#endif
					SpawnLogAlways("[SPAWN] >> Total score %.6f, better than %.6f but UNSAFE", fScore, fBestScore);
				}		
			}
			else
			{
				SpawnLogAlways("[SPAWN] >> Total score %.6f, too high, not using", fScore);
			}
		}
		else
		{
#if !defined(_RELEASE)
			nWrongTeamSpawns++;
#endif
		}
		
		iSpawnIndex++;
	}

#if !defined(_RELEASE)
	if(bestSpawnerId == 0)
	{
		IEntity * pPlayer = gEnv->pEntitySystem->GetEntity(spawnData.playerId);
		CryFatalError("ERROR: No spawner found. Should ALWAYS find a spawn.\n   Trying to spawn player EID %d, name '%s'.\n   Player is %s spawning.\n   %" PRISIZE_T " spawns found for spawn type, %d wrong team, %d unsafe", spawnData.playerId, pPlayer->GetName(), IsPlayerInitialSpawning(spawnData.playerId) ? "initial" : "normal", spawnLocations.size(), nWrongTeamSpawns, nUnsafeSpawns);
	}
#endif

	return bestSpawnerId;
}