예제 #1
0
int CDLCManager::GetNamesStringOfPlayersMissingDLCsForLevel(const char* pLevelName, stack_string* pPlayersString)
{
	CGameLobby*  pGameLobby = g_pGame->GetGameLobby();
	CRY_ASSERT(pGameLobby);
	CRY_ASSERT(pGameLobby->IsServer());

	int  count = 0;

	uint32  requiredDLCs = GetRequiredDLCsForLevel(pLevelName);

	const SSessionNames&  lobbySessNames = pGameLobby->GetSessionNames();

	const int  nameSize = lobbySessNames.Size();
	for (int i=0; i<nameSize; ++i)
	{
		const SSessionNames::SSessionName&  player = lobbySessNames.m_sessionNames[i];
		const uint32  loadedDLC = (uint32) player.m_userData[eLUD_LoadedDLCs];
		if (!MeetsDLCRequirements(requiredDLCs, loadedDLC))
		{
			CryLog("CDLCManager::GetNamesStringOfPlayersMissingDLCsForLevel: '%s' does not meet DLC requirements for level '%s'", player.m_name, pLevelName);
			count++;
			if (!pPlayersString->empty())
			{
				pPlayersString->append(", ");
			}
			pPlayersString->append(player.m_name);
		}
	}

	return count;
}
예제 #2
0
//------------------------------------------------------------------------
void CGameRules::StoreMigratingPlayer(IActor* pActor)
{
	if (pActor == NULL)
	{
		GameWarning("Invalid data for migrating player");
		return;
	}

	IEntity* pEntity = pActor->GetEntity();
	EntityId id = pEntity->GetId();
	bool registered = false;

	uint16 channelId = pActor->GetChannelId();
	CRY_ASSERT(channelId);

	bool bShouldAdd = true;

	CGameLobby *pGameLobby = g_pGame->GetGameLobby();
	CRY_ASSERT(pGameLobby);
	if (pGameLobby)
	{
		SCryMatchMakingConnectionUID conId = pGameLobby->GetConnectionUIDFromChannelID((int) channelId);
		if (pGameLobby->GetSessionNames().Find(conId) == SSessionNames::k_unableToFind)
		{
			CryLog("CGameRules::StoreMigratingPlayer() player %s (channelId=%u) has already left the game, not storing", pEntity->GetName(), channelId);
			bShouldAdd = false;
		}
	}

	if (bShouldAdd && (!m_hostMigrationCachedEntities.empty()))
	{
		if (!stl::find(m_hostMigrationCachedEntities, pActor->GetEntityId()))
		{
			bShouldAdd = false;
		}
	}

	if (bShouldAdd)
	{
		for (uint32 index = 0; index < m_migratingPlayerMaxCount; ++index)
		{
			if (!m_pMigratingPlayerInfo[index].InUse())
			{
				m_pMigratingPlayerInfo[index].SetData(pEntity->GetName(), id, GetTeam(id), pEntity->GetWorldPos(), pEntity->GetWorldAngles(), pActor->GetHealth());
				m_pMigratingPlayerInfo[index].SetChannelID(channelId);
				registered = true;
				break;
			}
		}
	}

	pEntity->Hide(true);		// Hide the player, they will be unhidden when they rejoin

	if (!registered && bShouldAdd)
	{
		GameWarning("Too many migrating players!");
	}
}
예제 #3
0
void CUILobbyMP::GetPlayerList()
{
	CGameLobby* pGameLobby = g_pGame->GetGameLobby();
	SSessionNames sessions = pGameLobby->GetSessionNames();
	SUIArguments players, ids;
	for (uint i = 0; i < sessions.Size(); i++)
	{
		SSessionNames::SSessionName &player = sessions.m_sessionNames[i];
		players.AddArgument( string(player.m_name) );
		ids.AddArgument(player.m_conId.m_uid);
	}
	
	PlayerListReturn(players, ids);
}
예제 #4
0
//-------------------------------------------------------------------------
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;
				}
			}
		}
	}
}
예제 #5
0
//------------------------------------------------------------------------
bool CGameRules::OnPromoteToServer(SHostMigrationInfo& hostMigrationInfo, uint32& state)
{
	if (!g_pGame->GetIGameFramework()->ShouldMigrateNub(hostMigrationInfo.m_session))
	{
		return true;
	}

	CryLogAlways("[Host Migration]: CGameRules::OnPromoteToServer() started");

	// Server time will change after we migrate (change from old server time to new server time)
	m_gameStartedTime.SetValue(m_gameStartedTime.GetValue() - m_cachedServerTime.GetValue());
	m_gameStartTime.SetValue(m_gameStartTime.GetValue() - m_cachedServerTime.GetValue());

	// If this migration has reset (we're not the original anticipated host, remove any entities from the first attempt
	if (!m_hostMigrationCachedEntities.empty())
	{
		HostMigrationRemoveDuplicateDynamicEntities();
	}

	// Now we know we're the server, remove the actors for anyone we know isn't going to migrate
	CGameLobby *pGameLobby = g_pGame->GetGameLobby();
	CRY_ASSERT(pGameLobby);
	if (pGameLobby)
	{
		TPlayers playersToRemove;

		IActorSystem *pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem();

		playersToRemove.reserve(pActorSystem->GetActorCount());

		IActorIteratorPtr actorIt = pActorSystem->CreateActorIterator();
		IActor *pActor;
		while (pActor = actorIt->Next())
		{
			if (pActor->IsPlayer())
			{
				CRY_ASSERT(pActor->GetChannelId());
				SCryMatchMakingConnectionUID conId = pGameLobby->GetConnectionUIDFromChannelID((int) pActor->GetChannelId());
				if (pGameLobby->GetSessionNames().Find(conId) == SSessionNames::k_unableToFind)
				{
					CryLog("  player '%s' has not got a corresponding CGameLobby entry, removing actor", pActor->GetEntity()->GetName());
					playersToRemove.push_back(pActor->GetEntityId());
				}
			}
		}

		const int numPlayersToRemove = playersToRemove.size();
		for (int i = 0; i < numPlayersToRemove; ++ i)
		{
			FakeDisconnectPlayer(playersToRemove[i]);
		}
	}

	for (uint32 i = 0; i < MAX_PLAYERS; ++ i)
	{
		m_migratedPlayerChannels[i] = 0;
	}

	IItemSystem *pItemSystem = g_pGame->GetIGameFramework()->GetIItemSystem();

	IEntityItPtr it = gEnv->pEntitySystem->GetEntityIterator();
	it->MoveFirst();

	for (uint32 i = 0; i < m_hostMigrationItemMaxCount; ++ i)
	{
		m_pHostMigrationItemInfo[i].Reset();
	}
	uint32 itemIndex = 0;

	IEntity *pEntity = NULL;
	while (pEntity = it->Next())
	{
		IItem *pItem = pItemSystem->GetItem(pEntity->GetId());
		if (pItem)
		{
			if (pItem->GetOwnerId())
			{
				IEntity *pOwner = gEnv->pEntitySystem->GetEntity(pItem->GetOwnerId());
				if (pOwner)
				{
					EntityId currentItemId = 0;

					IActor *pOwnerActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pOwner->GetId());
					if (pOwnerActor)
					{
						IItem *pCurrentItem = pOwnerActor->GetCurrentItem();
						currentItemId = pCurrentItem ? pCurrentItem->GetEntityId() : 0;
					}

					CryLog("[CG] Item '%s' is owned by '%s'", pEntity->GetName(), pOwner->GetName());
					//m_pHostMigrationItemInfo[itemIndex].Set(pEntity->GetId(), pOwner->GetId(), pItem->IsUsed(), (pItem->GetEntityId() == currentItemId));
					itemIndex ++;
					if (itemIndex >= m_hostMigrationItemMaxCount)
					{
						CRY_ASSERT(itemIndex < m_hostMigrationItemMaxCount);
						break;
					}
				}
			}
		}
		// Tell entities that we're host migrating
		// - Currently only used by ForbiddenArea but may well be needed for other entities later
		// - Currently only called on the new server, add to OnDemoteToClient if we need to use this on a client
		IScriptTable *pScript = pEntity->GetScriptTable();
		if (pScript != NULL && pScript->GetValueType("OnHostMigration") == svtFunction)
		{
			m_pScriptSystem->BeginCall(pScript, "OnHostMigration");
			m_pScriptSystem->PushFuncParam(pScript);
			m_pScriptSystem->PushFuncParam(true);
			m_pScriptSystem->EndCall();
		}
	}

	// This needs initialising on the new server otherwise the respawn timer will be counting down
	// from uninitialised data.  Likewise for the pre-round timer.
	ResetReviveCycleTime();

	const int numRespawnParams = m_respawndata.size();
	for (int i = 0; i < numRespawnParams; ++ i)
	{
		SEntityRespawnData *pData = &m_respawndata[i];
		pEntity = gEnv->pEntitySystem->GetEntity(pData->m_currentEntityId);
		if (pEntity == NULL)
		{
			CryLog("  detected respawn entity (id=%u) is not present, scheduling for respawn", pData->m_currentEntityId);
			ScheduleEntityRespawn(pData->m_currentEntityId, false, g_pGameCVars->g_defaultItemRespawnTimer);
		}
	}

	CryLog("[Host Migration]: CGameRules::OnPromoteToServer() finished");

	CCCPOINT(HostMigration_OnPromoteToServer);
	return true;
}