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); }
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; }