//------------------------------------------------------------------------
void CTeamVisualizationManager::ProcessTeamChangeVisualization(EntityId entityId) const
{
	if(!m_teamVisualizationPartsMap.empty())
	{
		if(entityId == g_pGame->GetClientActorId())
		{
			// If local player has changed team, refresh team materials for *all* players in game
			CGameRules* pGameRules = g_pGame->GetGameRules();
			CGameRules::TPlayers players;
			pGameRules->GetPlayers(players);

			CGameRules::TPlayers::const_iterator iter = players.begin();
			CGameRules::TPlayers::const_iterator end = players.end();
			while(iter != end)
			{
				RefreshPlayerTeamMaterial(*iter); 
				++iter;
			}
		}
		else // If remote player has changed team, just refresh that player.
		{
			RefreshPlayerTeamMaterial(entityId); 
		}
	}
}
//-------------------------------------------------------------------------
void CGameRulesStandardState::CleanUpAbortedIntro()
{
	CGameRules::TPlayers players; 
	m_pGameRules->GetPlayers(players);
	IActorSystem* pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem();
	CGameRules::TPlayers::const_iterator iter = players.begin();
	CGameRules::TPlayers::const_iterator end = players.end();
	while(iter != end)
	{
		CPlayer* pPlayer = static_cast<CPlayer*>( pActorSystem->GetActor( *iter ) );
		if(pPlayer)
		{
			pPlayer->OnIntroSequenceFinished(); 
		}
		++iter; 
	}
}
float CGameRulesRSSpawning::GetScoreFromProximityToEnemiesNoTeams( SUsefulSpawnData& spawnData, const Vec3& potentialSpawnPosition )
{
	SpawnLogAlways("[SPAWN] > GetScoreFromProximityToEnemiesNoTeams()");
	float fScoreFromEnemies = 0.0f;

	CGameRules::TPlayers players;
	g_pGame->GetGameRules()->GetPlayers(players);

	if(players.size() > 1)
	{
		const float fScoreOnTopOfEnemy = 200.0f;
		const float fMultiplierForEnemyDistance = 1.7f;
		const float fDistanceScoreMultiplier = 200.0f;
		int i = -1;

		for(CGameRules::TPlayers::iterator it=players.begin();it!=players.end();++it)
		{
			i++;

			if(*it == spawnData.playerId)
				continue;

			const IEntity *pOther = gEnv->pEntitySystem->GetEntity(*it);
			Vec3  vDiffToEnemy			 = (pOther->GetWorldPos() - potentialSpawnPosition);
			vDiffToEnemy.z					+= max(2.0f * vDiffToEnemy.z, 6.0f);
			float fDistanceFromEnemy = vDiffToEnemy.len();
			
			float fDistanceScoreFraction = __fres(max(fDistanceFromEnemy - 4.f, 0.001f));

			float fScoreForThisEnemy = max(fScoreOnTopOfEnemy - (fDistanceFromEnemy * fMultiplierForEnemyDistance), 0.0f) + (fDistanceScoreFraction * fDistanceScoreMultiplier);

			SpawnLogAlways("[SPAWN] >>> Score from Enemy %d is %.6f at distance %.1f", i, fScoreForThisEnemy, fDistanceFromEnemy);

			fScoreFromEnemies = max(fScoreForThisEnemy, fScoreFromEnemies);
		}

		SpawnLogAlways("[SPAWN] >> Total Score from Enemies: %.6f", fScoreFromEnemies);
	}

	return fScoreFromEnemies;
}
void CVTOLVehicleManager::Update(float frameTime)
{
	// Update logic goes here
	if(CGameRules* pGameRules = g_pGame->GetGameRules())
	{
		CGameRules::TPlayers players;
		pGameRules->GetPlayers(players);

		for (TVTOLList::iterator iter=m_vtolList.begin(), end=m_vtolList.end(); iter!=end; ++iter)
		{
			SVTOLInfo& info = iter->second;
			IVehicle* pVehicle = m_pVehicleSystem->GetVehicle( info.entityId );
			if(pVehicle)
			{
				info.stateTime += frameTime;

				// Find difference in rotation
				Quat newRotation = pVehicle->GetEntity()->GetWorldRotation();
				newRotation.Normalize();
				Quat rotationDifference = newRotation*info.location.q.GetInverted();
				rotationDifference.Normalize();

				// Store new rotation + position
				info.location.q = newRotation;
				info.location.t = pVehicle->GetEntity()->GetWorldPos();

				if(info.state==EVS_Normal)
				{
					pVehicle->NeedsUpdate(IVehicle::eVUF_AwakePhysics);

					if(CVehicleMovementMPVTOL* pMovement = static_cast<CVehicleMovementMPVTOL*>(pVehicle->GetMovement()))
					{
						const uint8 pathComplete = pMovement->GetPathComplete();
						if(pathComplete==1)
						{
							if(CMPPathFollowingManager* pMPPathFollowingManager = g_pGame->GetGameRules()->GetMPPathFollowingManager())
							{
								pMPPathFollowingManager->NotifyListenersOfPathCompletion(info.entityId);
							}
							pMovement->SetPathCompleteNotified();
						}
					}
				}

				// Check status
				if(info.state==EVS_Normal && pVehicle->GetDamageRatio() >= 1.f)
				{
					if(gEnv->bServer)
					{
						DestructionDamageRatioReached(pVehicle, info, frameTime);
					}
				}
				else if(info.state == EVS_Invisible)
				{
					if(info.stateTime > g_pGameCVars->g_VTOLRespawnTime)
					{
						RespawnVTOL(pVehicle, info);
					}
				}

				//Process players
				TPlayerList& currentPlayerList = info.playersInside;
				TPlayerList oldPlayerList = currentPlayerList;
				currentPlayerList.clear();

				CGameRules::TPlayers::iterator iterPlayer = players.begin();
				const CGameRules::TPlayers::const_iterator endPlayer = players.end();
				while(iterPlayer != endPlayer)
				{
					// Adding safeguard to protect against cases where user alt-f4 quits program. 
					UpdateEntityInVTOL(info, *iterPlayer); 
					++iterPlayer;
				}
				
				//Find out who has been inside since the last update, who has just entered, and who has left
				TPlayerStatusList playerStatusList;
				int currentId;
				for(unsigned int prev = 0; prev < currentPlayerList.size(); ++prev)
				{
					currentId = currentPlayerList[prev];
					bool found = false;
					TPlayerList::iterator oldIter = oldPlayerList.begin();
					TPlayerList::iterator oldEnd = oldPlayerList.end();
					while(oldIter != oldEnd)
					{
						if(currentId == *oldIter) //In both lists so still inside
						{
							found = true;
							playerStatusList.push_back( TPlayerStatus(currentId, E_PEVS_StillInside) );
							oldPlayerList.erase(oldIter);
							break;
						}
						++oldIter;
					}
					if(!found) //Only in current list so entered
					{
						playerStatusList.push_back( TPlayerStatus(currentId, E_PEVS_Entered) );
					}
				}
				//Those remaining in old list have exited
				for(unsigned int old = 0; old < oldPlayerList.size(); ++old) 
				{
					playerStatusList.push_back( TPlayerStatus(oldPlayerList[old], E_PEVS_Exited) );
				}

				//Act based on current state
				TPlayerStatusList::iterator statusIter = playerStatusList.begin();
				TPlayerStatusList::iterator statusEnd = playerStatusList.end();
				while(statusIter != statusEnd)
				{
					switch(statusIter->second)
					{
					case E_PEVS_Entered:
						{
							OnPlayerEntered(statusIter->first);
						}
						break;
					case E_PEVS_Exited:
						{
							OnPlayerExited(statusIter->first);
						}
						break;
					}
					++statusIter;
				}

				UpdateRotationOfInternalPlayers(info, playerStatusList, rotationDifference);
			}
		}
	}
}
//-------------------------------------------------------------------------
void CGameRulesStandardState::ChangeState( EGR_GameState newState )
{
	if (gEnv->bServer)
	{
		if (newState == EGRS_InGame)
		{
			CCCPOINT(GameRulesStandardState_EnterInGame);

#if !defined(_RELEASE) || defined(PERFORMANCE_BUILD)
			if (m_state != EGRS_InGame)
			{
				if (g_pGameCVars->g_gameRules_startCmd[0] != '\0')
				{
					gEnv->pConsole->ExecuteString(g_pGameCVars->g_gameRules_startCmd, false, true);
				}
			}
#endif // #if !defined(_RELEASE) || defined(PERFORMANCE_BUILD)

			m_pGameRules->ResetGameTime();
			IGameRulesStatsRecording	*st=m_pGameRules->GetStatsRecordingModule();
			if (st)
			{
				st->OnInGameBegin();
			}
		}
		else if (newState == EGRS_PostGame)
		{
			m_timeInPostGame = 0.0f;
			IGameRulesStatsRecording	*st=m_pGameRules->GetStatsRecordingModule();
			if (st)
			{
				st->OnPostGameBegin();
			}
#if defined(DEDICATED_SERVER) 
      if ( gEnv->bMultiplayer )
      {
        // Stop cvar probes.
        CGameRules::TPlayers players;
        m_pGameRules->GetPlayers(players);
        const int numPlayers = players.size();
        for (int i = 0; i < numPlayers; ++ i)
        {
          const EntityId playerId = players[i];
          IActor * pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(playerId);
          if ( pActor )
          {

            IGameObject * pGameObject = NULL;
            INetChannel * pNetChannel = NULL;
            IDefenceContext * pDefenceContext = NULL;

            if ( (pGameObject = pActor->GetGameObject()) )
            {
              if ( (pNetChannel = pGameObject->GetNetChannel()) )
              {
                if ( (pDefenceContext = pNetChannel->GetDefenceContext()) )
                {
                  pDefenceContext->EndCvarRequests();
                }
              }
            }
          }
        }
      }
#endif

			CGameLobby *pGameLobby = g_pGame->GetGameLobby();
			if (pGameLobby)
			{
				CryLog("[GameRules] GameFinished, telling clients");
				pGameLobby->SvFinishedGame(0.0f);
			}
		}
	}

	const bool bIsClient = gEnv->IsClient();
	if (bIsClient)
	{
		if (newState == EGRS_PostGame)
		{
			m_timeInPostGame = 0.0f;

			EnterPostGameState(ePGS_Starting);
		}
		else if (newState == EGRS_InGame)
		{
			CHUDEventDispatcher::CallEvent( SHUDEvent(eHUDEvent_OnGameStart) );
		}
		else if (newState == EGRS_Reset)
		{
			m_introMessageShown = false;
		}

		ClientChangeStateFeedback(newState);
	}

	m_state = newState;

	OnStateEntered_NotifyListeners(); 

	if (newState == EGRS_PostGame)
	{
		m_pGameRules->FreezeInput(true);
		g_pGame->GetUI()->ActivateDefaultState();	// must be after settings newState to pick endgame
	
		OnGameEnd_NotifyListeners();
	}
	else if (newState == EGRS_InGame)
	{
		OnGameStart_NotifyListeners();

		if (bIsClient && g_pGameCVars->g_gameRules_preGame_StartSpawnedFrozen)
		{
			g_pGameActions->FilterMPPreGameFreeze()->Enable(false);
			g_pGame->GetUI()->ActivateDefaultState();	// must be after settings newState
		}

		// Have to explicitly call the spawning module, can't use the listener since that would make the modules
		// dependent on the initialisation order - which comes from xml
		IGameRulesSpawningModule *pSpawningModule = m_pGameRules->GetSpawningModule();
		if (pSpawningModule)
		{
			pSpawningModule->OnInGameBegin();
		}
	}

	if (gEnv->bServer)
	{
		CHANGED_NETWORK_STATE(m_pGameRules, STANDARD_STATE_ASPECT);

		if (m_state == EGRS_InGame)
		{
			// Revive players - has to be done after setting m_state since we don't revive players in PreGame
			IGameRulesSpawningModule *pSpawningModule = m_pGameRules->GetSpawningModule();
			if (pSpawningModule)
			{
				const bool bOnlyIfDead = (g_pGameCVars->g_gameRules_preGame_StartSpawnedFrozen!=0);
				pSpawningModule->ReviveAllPlayers(false, bOnlyIfDead);
			}
		}
	}
}