Пример #1
0
bool ScmdServer_Impl::HandleListGameOptions( HCLIENT hClient, ILTMessage_Read& msg )
{
	ServerMissionSettings sms = g_pServerMissionMgr->GetServerSettings();

	CAutoMessage cMsg;
	cMsg.Writeuint8( MID_SCMD );
	cMsg.Writeuint8( kScmdCommandListGameOptions );
	cMsg.Writeuint8( kScmdCommandStatusOk );

	cMsg.Writeuint8( g_pGameServerShell->GetGameType( ));

	switch( g_pGameServerShell->GetGameType( ))
	{
		case eGameTypeDeathmatch:
		{
			cMsg.Writeuint8( sms.m_nRunSpeed );
			cMsg.Writeuint8( sms.m_nScoreLimit );
			cMsg.Writeuint8( sms.m_nTimeLimit );
			cMsg.Writeuint8( sms.m_nRounds );
		}
		break;

		case eGameTypeTeamDeathmatch:
		{
			cMsg.Writeuint8( sms.m_nRunSpeed );
			cMsg.Writeuint8( sms.m_nScoreLimit );
			cMsg.Writeuint8( sms.m_nTimeLimit );
			cMsg.Writeuint8( sms.m_nRounds );
			cMsg.Writebool( sms.m_bFriendlyFire) ;
		}
		break;

		case eGameTypeDoomsDay:
		{
			cMsg.Writeuint8( sms.m_nRunSpeed );
			cMsg.Writeuint8( sms.m_nTimeLimit );
			cMsg.Writeuint8( sms.m_nRounds );
			cMsg.Writebool( sms.m_bFriendlyFire );
		}
		break;

		case eGameTypeCooperative:
		{
			cMsg.Writebool( sms.m_bFriendlyFire) ;
			cMsg.Writeuint8( sms.m_nMPDifficulty );
			cMsg.Writefloat( sms.m_fPlayerDiffFactor );
		}
		break;

		default:
		{
		}
		break;
	}

	// Send the message.
	SendMessage( hClient, *cMsg );

	return true;
}
Пример #2
0
bool CServerMissionMgr::SendExitLevelMessage( )
{
	// Tell the players to prepare to exit a level.
	CPlayerObj::PlayerObjList::const_iterator iter = CPlayerObj::GetPlayerObjList( ).begin( );
	while( iter != CPlayerObj::GetPlayerObjList( ).end( ))
	{
		CPlayerObj* pPlayerObj = *iter;
		pPlayerObj->HandlePreExit();
		g_pGameServerShell->SendPlayerInfoMsgToClients(NULL,pPlayerObj,MID_PI_UPDATE);
		iter++;
	}

	CTeamMgr::Instance().UpdateClient();

	// See if we have already visited the level we are going to.
	CString sLoadGameFile = g_pServerSaveLoadMgr->GetWorldSaveFile( m_sCurrentWorldName );
	bool bRestoringLevel = !!CWinUtil::FileExist( sLoadGameFile );

	// Tell client's we're exiting.  Wait for their response.
	CAutoMessage cMsg;
	cMsg.Writeuint8( MID_EXIT_LEVEL );
	cMsg.WriteString( m_sCurrentWorldName );
	cMsg.Writebool( m_bNewMission );
	cMsg.Writebool( bRestoringLevel );
	cMsg.Writebool( true );
	g_pLTServer->SendToClient(cMsg.Read(), LTNULL, MESSAGE_GUARANTEED);

	return true;
}
Пример #3
0
bool CServerMissionMgr::ExitLevelToSavedGame( char const* pszNewLevel )
{
	TRACE( "CServerMissionMgr::ExitLevelToSavedGame\n" );

	// Check if we're already exiting a level.
	if( m_bExitingLevel )
		return true;

	// Verify inputs.
	if( !pszNewLevel )
	{
		ASSERT( !"CServerMissionMgr::ExitLevelToSavedGame: Invalid inputs." );
		return false;
	}

	// Default to this not being a mission change.
	m_bNewMission = false;

	// Check if the new level is a new mission.
	int nCurMission = m_nCurrentMission;
	if( !SetMissionBasedOnLevel( pszNewLevel ))
		return false;

	// If we switch to a custom level, then consider it a new mission.
	if( m_bCustomLevel )
	{
		m_bNewMission = true;
		m_nCurCampaignIndex = -1;
	}
	// If it's not a custom world, check if our mission changed.
	else
	{
		m_bNewMission = ( nCurMission != m_nCurrentMission );

		// If we had a mission switch, advance our campaign index.
		if( m_bNewMission )
		{
			// See if we can find the campaign index from our previous position.
			m_nCurCampaignIndex = FindNextCampaignIndex( m_nCurCampaignIndex, m_nCurrentMission );
		}
	}

	if (IsMultiplayerGame())
	{
		// Tell clients we're exiting. Don't wait for their response.
		CAutoMessage cMsg;
		cMsg.Writeuint8( MID_EXIT_LEVEL );
		cMsg.WriteString( m_sCurrentWorldName );
		cMsg.Writebool( m_bNewMission );
		cMsg.Writebool( false );
		cMsg.Writebool( false );
		g_pLTServer->SendToClient(cMsg.Read(), LTNULL, MESSAGE_GUARANTEED);
	}

	return true;
}
Пример #4
0
void SpecialMove::WriteSFXMsg(CAutoMessage& cMsg)
{
	// Set our special effect message.
	cMsg.Writeuint8(GetSFXID());
	cMsg.Writeuint32(m_eAnimation);
	cMsg.Writefloat(m_fActivateDist);
	cMsg.Writebool(m_bOn);
	cMsg.Writebool(m_bRadial);

	// Piggyback our Activate data.
	m_ActivateTypeHandler.WriteActivateTypeMsg(cMsg);
}
Пример #5
0
void Door::UpdateSector( bool bSectorActive )
{
	for(uint32 nCurrSector = 0; nCurrSector < knNumSectors; nCurrSector++)
	{
		// Do nothing if we don't have a sector
		if( m_sSectorName[nCurrSector].empty() )
			return;

		// Just in case we get in here before we expect to, update the sector ID..
		if( !m_nSectorID[nCurrSector] )
		{
			if( g_pLTServer->GetSectorID( m_sSectorName[nCurrSector].c_str(), &m_nSectorID[nCurrSector] ) != LT_OK )
			{
				// If we can't find the sector, dump a warning and forget...
				char aNameBuff[256];
				g_pLTServer->GetObjectName( m_hObject, aNameBuff, LTARRAYSIZE(aNameBuff) );
				g_pLTServer->CPrint( "Invalid sector specified in door %s: %s", aNameBuff, m_sSectorName[nCurrSector].c_str() );
				m_sSectorName[nCurrSector].clear();
				return;
			}
		}

		m_bSectorsActive = bSectorActive;

		// Send the dynamic sector message to all connected clients...
		// This is temporary until we get the new networking architecture in place.
		// We can't do it with an FX object because activeworldmodels already have an FX object...
		CAutoMessage cMsg;
		cMsg.Writeuint8( MID_DYNAMIC_SECTOR );
		cMsg.Writeuint32( m_nSectorID[nCurrSector] );
		cMsg.Writebool( bSectorActive );

		g_pLTServer->SendToClient( cMsg.Read(), NULL, MESSAGE_GUARANTEED);
	}
}
Пример #6
0
void GearItem::PickedUp(ILTMessage_Read *pMsg)
{
	// Did we really pick it up?

	bool bPickedUp = (pMsg ? pMsg->Readbool() : true);

	// If we were touched by a player, our m_hPlayerObj data member will be
	// set.  Send a message to that player's client letting it know that an
	// item has been picked up...

	if (m_hPlayerObj)
	{
        CPlayerObj* pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(m_hPlayerObj);
		if (pPlayer && !pPlayer->IsDead())
		{
			HCLIENT hClient = pPlayer->GetClient();
			if (hClient)
			{
				CAutoMessage cMsg;
				cMsg.Writeuint8(MID_GEAR_PICKEDUP);
				cMsg.Writeuint8((uint8)m_nGearId);
				cMsg.Writebool(bPickedUp);
				g_pLTServer->SendToClient(cMsg.Read(), hClient, MESSAGE_GUARANTEED);
			}
		}
	}

	if (bPickedUp)
	{
		PickupItem::PickedUp(pMsg);
		
		if( m_bRespawn )
		{
			GEAR const *pGear = g_pWeaponMgr->GetGear( m_nGearId );
			if( !pGear )
				return;

			// Change the skins and renderstyles to the waiting to respawn files...

			ObjectCreateStruct ocs;

			pGear->blrRespawnWaitSkins.CopyList( 0, ocs.m_SkinNames[0], MAX_CS_FILENAME_LEN + 1 );
			pGear->blrRespawnWaitRenderStyles.CopyList( 0, ocs.m_RenderStyleNames[0], MAX_CS_FILENAME_LEN + 1 );

			if( pGear->blrRespawnWaitRenderStyles.GetNumItems() < 1 )
				LTStrCpy( ocs.m_RenderStyleNames[0], s_szDefaultRS, ARRAY_LEN( s_szDefaultRS ));
			
			g_pCommonLT->SetObjectFilenames( m_hObject, &ocs );

			// Stop playing PowerupFX and play RespawnWaitFX...
		
			SetClientFX( pGear->szRespawnWaitFX );

			// Set our visibility...

			g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags, pGear->bRespawnWaitVisible ? FLAG_VISIBLE : 0, FLAG_VISIBLE );
			g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags2, pGear->bRespawnWaitTranslucent ? FLAG2_FORCETRANSLUCENT : 0, FLAG2_FORCETRANSLUCENT );
		}
	}
}
Пример #7
0
// --------------------------------------------------------------------------- //
//
//	ROUTINE:	TeamBalancer::BalanceTeamScore
//
//	PURPOSE:	balance teams by using playground sorting based on player scores
//
// --------------------------------------------------------------------------- //
bool TeamBalancer::BalanceTeamScore()
{

	m_nRoundsSinceScoreBalance = 0;

	bool bDoSort = false;


	//figure out the score difference
	int32 nDiff = LTDIFF(m_nTeamScores[0],m_nTeamScores[1]);
	if (nDiff > 0)
	{
		ServerConnectionMgr::GameClientDataList& gameClientDataList = ServerConnectionMgr::Instance( ).GetGameClientDataList( );
		//for 2 or fewer players don't bother doing a complicated sort, just balance the team sizes if needed
//		if (gameClientDataList.size() <= 2)
//		{
//			BalanceTeamSize();
//		}
//		else
		{
			int32 nLower = LTMIN(m_nTeamScores[0],m_nTeamScores[1]);

			//if the lower score is 0, treat it as one for these calculations to avoid divide by 0 errors
			if (nLower == 0)
			{
				nLower = 1;
			}

			//how much did the winners win by? This formula 1+(diff/lower) is used instead of
			//	(high/low) in order to handle 0 and negative high score more cleanly
			float fRatio = 1.0f + (float)nDiff/ (float)LTAbs(nLower);
			
			//see if the margin was wide enough to trigger a shuffle
			bDoSort = (fRatio >= GameModeMgr::Instance().m_grfTeamScoreBalancingPercent);
		}

	}

	if (bDoSort)
	{
		PlaygroundSort();

		CAutoMessage cClientMsg;
		cClientMsg.Writeuint8(MID_PLAYER_EVENT);
		cClientMsg.Writeuint8(kPEAutobalance);
		cClientMsg.Writebool( true ); //did score balancing
		g_pLTServer->SendToClient(cClientMsg.Read(), NULL, MESSAGE_GUARANTEED);

	}

	//chear the history, whether or not we actually sorted
	m_nTeamScores[0] = 0;
	m_nTeamScores[1] = 0;
	m_vecPlayerScores.clear();

	return bDoSort;
}
Пример #8
0
void CDestructibleModel::CreateDestroyedFX(const DamageStruct& DamageInfo)
{
	// If no destroyed fx is specifed, return...
	if ( LTStrEmpty( m_pszDestroyedFXName ) || !LTStrICmp(m_pszDestroyedFXName, FX_NONE)) return;

	// Use the position/rotation of the object for the fx...
	LTRigidTransform tObjTrans;
	g_pLTServer->GetObjectTransform(m_hObject, &tObjTrans);

	CAutoMessage cMsg;
	cMsg.Writeuint8(SFX_CLIENTFXGROUPINSTANT);
	cMsg.WriteString(m_pszDestroyedFXName);
	cMsg.Writebool( false ); // loop
	cMsg.Writebool( false ); // smooth shutdown
	cMsg.Writebool( false ); // No special parent
	cMsg.WriteLTVector(tObjTrans.m_vPos);
	cMsg.WriteCompLTRotation(tObjTrans.m_rRot);
	cMsg.Writebool( false ); // No target info

	g_pLTServer->SendSFXMessage(cMsg.Read(), 0);
}
Пример #9
0
void PickupItem::CreateSpecialFX( bool bUpdateClients /* = false  */ )
{
	{
		CAutoMessage cMsg;
		cMsg.Writeuint8(SFX_PICKUPITEM_ID);
		cMsg.Writebool(!!m_bRotate);
		cMsg.Writebool(!!m_bBounce);
		cMsg.WriteString( m_sClientFX.c_str() );
		cMsg.Writeuint8(m_nTeamId);
		g_pLTServer->SetObjectSFXMessage(m_hObject, cMsg.Read());
	}
}
Пример #10
0
void CHUDChatInput::Send()
{

	Show(false,false);

	// Ignore empty messages.
	if( !m_szChatStr[0] )
		return;

	// First check and see if it was a cheat that was entered...

	ConParse cParse( m_szChatStr );
	if( LT_OK == g_pCommonLT->Parse( &cParse ))
	{
		CParsedMsg parsedMsg( cParse.m_nArgs, cParse.m_Args );

		if (g_pCheatMgr->Check( parsedMsg ))
		{
			g_pClientSoundMgr->PlayInterfaceSound("Interface\\Menu\\Snd\\Cheat.wav");
			return;
		}
		// Check if this is an scmd command.
		else if( ScmdConsole::Instance( ).SendParsedCommand( parsedMsg ))
		{
			// If it was, it was sent.  Don't send chat.
			return;
		}
	}

	// Send the Message to the server
	CAutoMessage cMsg;
	uint8 nMsgID;
	if (g_pPlayerMgr->GetPlayerState() == PS_GHOST)
		nMsgID = MID_PLAYER_GHOSTMESSAGE;
	else
        nMsgID = MID_PLAYER_MESSAGE;
	cMsg.Writeuint8(nMsgID);
    cMsg.WriteString(m_szChatStr);
	cMsg.Writebool(m_bTeamMessage);
    g_pLTClient->SendToServer(cMsg.Read(), MESSAGE_GUARANTEED);

	// cache this string in the chat history
	for (int i = kMaxChatHistory-1; i > 0; i--)
	{
		SAFE_STRCPY(m_szChatHistory[i], m_szChatHistory[i-1]);
	}

	SAFE_STRCPY(m_szChatHistory[0], m_szChatStr);
}
Пример #11
0
void Water::HandleAllowSwimmingMsg( HOBJECT hSender, const CParsedMsg &crParsedMsg )
{
	static CParsedMsg::CToken s_cTok_0( "0" );

	m_bAllowSwimming = !(crParsedMsg.GetArg( 1 ) == s_cTok_0);

	CAutoMessage cMsg;
	cMsg.Writeuint8( MID_SFX_MESSAGE );
	cMsg.Writeuint8( m_nSfxMsgId );
	cMsg.WriteObject( m_hObject );
	cMsg.WriteBits( kVolumeBrush_AllowSwimming, FNumBitsExclusive<kVolumeBrush_NumMsgs>::k_nValue );
	cMsg.Writebool( m_bAllowSwimming );
	g_pLTServer->SendToClient( cMsg.Read( ), NULL, MESSAGE_GUARANTEED );

	CreateSpecialFXMsg( );
}
Пример #12
0
void ClientVoteMgr::CastVote(bool bVote)
{
	if (!IsVoteInProgress() || m_bHasVoted)
	{
		return;
	}

	CAutoMessage cMsg;
	cMsg.Writeuint8( MID_VOTE );
	cMsg.WriteBits( eVote_Cast, FNumBitsExclusive<kNumVoteActions>::k_nValue );
	cMsg.Writeuint8( m_CurrentVote.m_nVoteID );
	cMsg.Writebool( bVote );
	g_pLTClient->SendToServer( cMsg.Read(), MESSAGE_GUARANTEED );

	m_bHasVoted = true;
	g_pHUDMgr->QueueUpdate(kHUDVote);
}
Пример #13
0
void WeaponItem::ObjectTouch(HOBJECT hObject, bool bForcePickup/*=false*/)
{
	if (!hObject) return;

	// If we hit non-player objects, just ignore them...

	if (IsPlayer(hObject))
	{
        CCharacter* pCharObj = (CCharacter*)g_pLTServer->HandleToObject(hObject);

		if (pCharObj && !pCharObj->IsDead())
		{
			CAutoMessage cMsg;
			cMsg.Writeuint32(MID_ADDWEAPON);
			cMsg.Writeuint8(m_nWeaponId);
            cMsg.Writeuint8(m_nAmmoId);
            cMsg.Writeint32(m_nAmmo);
			cMsg.Writebool(bForcePickup);
			g_pLTServer->SendToObject(cMsg.Read(), m_hObject, hObject, MESSAGE_GUARANTEED);
		}
	}
}
Пример #14
0
void CTO2GameServerShell::Update(LTFLOAT timeElapsed)
{
	// Update the main server first
	CGameServerShell::Update(timeElapsed);

	m_VersionMgr.Update();

	if (!GetServerDir())
		return;

	//if we're hosting LANOnly game, don't publish the server
	if( m_ServerGameOptions.m_bLANOnly )
		return;

	// Are we still waiting?
	static std::string status;
	switch (GetServerDir()->GetCurStatus())
	{
		case IServerDirectory::eStatus_Processing : 
			status ="";
			break;
		case IServerDirectory::eStatus_Waiting : 
			if (status.empty())
				status = GetServerDir()->GetLastRequestResultString();
			break;
		case IServerDirectory::eStatus_Error : 
			{
				
				IServerDirectory::ERequest eErrorRequest = GetServerDir()->GetLastErrorRequest();
				status = GetServerDir()->GetLastRequestResultString();
				GetServerDir()->ProcessRequestList();
			}
			break;
	};



	// Publish the server if we've waited long enough since the last directory update
	uint32 nCurTime = (uint32)GetTickCount();
	if ((m_nLastPublishTime == 0) || 
		((nCurTime - m_nLastPublishTime) > k_nRepublishDelay))
	{
		status = "";
		m_nLastPublishTime = nCurTime;
		uint32 nMax = 0;
		g_pLTServer->GetMaxConnections(nMax);

		// If not run by a dedicated server, we need to add one connection
		// for the local host.
		if( !m_ServerGameOptions.m_bDedicated )
			nMax++;

		GetServerDir()->SetActivePeer(0);

		CAutoMessage cMsg;

		// Update the summary info
		cMsg.WriteString(GetHostName());
		GetServerDir()->SetActivePeerInfo(IServerDirectory::ePeerInfo_Name, *cMsg.Read());

		char fname[_MAX_FNAME] = "";
		_splitpath( GetCurLevel(), NULL, NULL, fname, NULL );

		// Update the summary info
		cMsg.WriteString(g_pVersionMgr->GetBuild());
		cMsg.WriteString( fname );
		cMsg.Writeuint8(GetNumPlayers());
		cMsg.Writeuint8(nMax);
		cMsg.Writebool(m_ServerGameOptions.m_bUsePassword);
		cMsg.Writeuint8((uint8)GetGameType());
		cMsg.WriteString( m_ServerGameOptions.m_sModName.c_str() );

		GetServerDir()->SetActivePeerInfo(IServerDirectory::ePeerInfo_Summary, *cMsg.Read());


		// Update the details
		ServerMissionSettings sms = g_pServerMissionMgr->GetServerSettings();
		cMsg.Writebool(sms.m_bUseSkills);
		cMsg.Writebool(sms.m_bFriendlyFire);
		cMsg.Writeuint8(sms.m_nMPDifficulty);
		cMsg.Writefloat(sms.m_fPlayerDiffFactor);

		CPlayerObj* pPlayer = GetFirstNetPlayer();
	    while (pPlayer)
		{
			//has player info
			cMsg.Writebool(true);
			cMsg.WriteString(pPlayer->GetNetUniqueName());
			cMsg.Writeuint16( Min( GetPlayerPing(pPlayer), ( uint32 )65535 ));
			pPlayer = GetNextNetPlayer();
		};

		//end of player info
		cMsg.Writebool(false);

	
		cMsg.Writeuint8(sms.m_nRunSpeed);
		cMsg.Writeuint8(sms.m_nScoreLimit);
		cMsg.Writeuint8(sms.m_nTimeLimit);

		GetServerDir()->SetActivePeerInfo(IServerDirectory::ePeerInfo_Details, *cMsg.Read());

		// Update the port
		char aHostAddr[16];
		uint16 nHostPort;
		g_pLTServer->GetTcpIpAddress(aHostAddr, sizeof(aHostAddr), nHostPort);
		cMsg.Writeuint16(nHostPort);
		GetServerDir()->SetActivePeerInfo(IServerDirectory::ePeerInfo_Port, *cMsg.Read());
		
		// Tell serverdir again about info, but in service specific manner.
		PeerInfo_Service_Titan peerInfo;
		peerInfo.m_sHostName = GetHostName( );
		peerInfo.m_sCurWorld = fname; 
		peerInfo.m_nCurNumPlayers = GetNumPlayers( );
		peerInfo.m_nMaxNumPlayers = nMax;
		peerInfo.m_bUsePassword = m_ServerGameOptions.m_bUsePassword;
		peerInfo.m_sGameType = GameTypeToString( GetGameType( ));
		peerInfo.m_nScoreLimit = sms.m_nScoreLimit;
		peerInfo.m_nTimeLimit = sms.m_nTimeLimit;

		PeerInfo_Service_Titan::Player player;
		CPlayerObj::PlayerObjList::const_iterator iter = CPlayerObj::GetPlayerObjList( ).begin( );
		while( iter != CPlayerObj::GetPlayerObjList( ).end( ))
		{
			CPlayerObj* pPlayerObj = *iter;

			player.m_sName = pPlayerObj->GetNetUniqueName( );
			player.m_nScore = pPlayerObj->GetPlayerScore()->GetScore( );

			float fPing;
			g_pLTServer->GetClientPing( pPlayerObj->GetClient( ), fPing );
			player.m_nPing = ( uint16 )( fPing + 0.5f );

			peerInfo.m_PlayerList.push_back( player );

			iter++;
		}


		cMsg.Writeuint32(( uint32 )&peerInfo );
		GetServerDir()->SetActivePeerInfo(IServerDirectory::ePeerInfo_Service, *cMsg.Read());

		// Tell the world about me...
		GetServerDir()->QueueRequest(IServerDirectory::eRequest_Publish_Server);
	}
}
Пример #15
0
// --------------------------------------------------------------------------- //
//
//	ROUTINE:	TeamBalancer::BalanceTeamSize
//
//	PURPOSE:	balance team sizes by moving the lowest score player(s) from the larger team
//
// --------------------------------------------------------------------------- //
bool TeamBalancer::BalanceTeamSize()
{
	bool bMovedPlayer = false;
	uint32 nTeamSizes[2] = {0,0};
	for (uint8 nTeam = 0;nTeam < 2;++nTeam)
	{
		CTeam* pTeam = CTeamMgr::Instance( ).GetTeam(nTeam);
		if (pTeam)
		{
			nTeamSizes[nTeam] = pTeam->GetNumPlayers();
		}
	}

	//check to see if one team is larger by at least 2 people
	if (LTDIFF(nTeamSizes[0],nTeamSizes[1]) > 1)
	{
		uint8 nLargerTeam = ((nTeamSizes[0] < nTeamSizes[1]) ? 1 : 0);
		uint8 nSmallerTeam = (nLargerTeam + 1) % MAX_TEAMS;

		//make a list of players on the team
		PlayerScoreHistoryArray vecScores;
		ServerConnectionMgr::GameClientDataList& gameClientDataList = ServerConnectionMgr::Instance( ).GetGameClientDataList( );
		ServerConnectionMgr::GameClientDataList::iterator iter = gameClientDataList.begin( );
		for( ; iter != gameClientDataList.end( ); iter++ )
		{
			GameClientData* pGameClientData = *iter;
			if( !pGameClientData->GetClient( ))
				continue;

			//if player is on the larger team, add him to our list
			if (nLargerTeam == pGameClientData->GetLastTeamId())
			{
				PlayerScoreHistory pairScore;
				pairScore.first = g_pLTServer->GetClientID(pGameClientData->GetClient( ));
				pairScore.second = 0;
				CPlayerScore* pScore = pGameClientData->GetPlayerScore(); 
				if (pScore)
				{
					pairScore.second = pScore->GetScore();
				}
				vecScores.push_back(pairScore);
			}
		}
		//sort the player list from highest to lowest
		std::sort(vecScores.begin(),vecScores.end(),PlayerScoreHistoryCompare());

		//while the teams are still unbalanced move lowest scoring players from the larger team to the smaller
		PlayerScoreHistoryArray::reverse_iterator scoreIter = vecScores.rbegin();
		while (LTDIFF(nTeamSizes[nLargerTeam],nTeamSizes[nSmallerTeam]) > 1 && scoreIter != vecScores.rend())
		{
			
			uint32 nID = scoreIter->first;
			GameClientData* pGameClientData = ServerConnectionMgr::Instance().GetGameClientDataByClientId(nID);

			if (pGameClientData)
			{
				pGameClientData->SetRequestedTeam(nSmallerTeam);
				CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject(pGameClientData->GetPlayer());
				if (pPlayer)
				{
					pPlayer->HandleTeamSwitchRequest();
				}
				//shrink the larger team and grow the smaller
				nTeamSizes[nLargerTeam]--;
				nTeamSizes[nSmallerTeam]++;

				bMovedPlayer = true;
			}
			scoreIter++;
		}
	}

	if (bMovedPlayer)
	{
		CAutoMessage cClientMsg;
		cClientMsg.Writeuint8(MID_PLAYER_EVENT);
		cClientMsg.Writeuint8(kPEAutobalance);
		cClientMsg.Writebool( false ); //didn't do score balancing
		g_pLTServer->SendToClient(cClientMsg.Read(), NULL, MESSAGE_GUARANTEED);
	}

	return bMovedPlayer;
}
Пример #16
0
// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CDebugLineFX::Update
//
//	PURPOSE:	Checks for new lines, clients, or a clear line and sends
//				the data down to any clients.
//
// ----------------------------------------------------------------------- //
void DebugLineSystem::Update()
{
	if( !m_hObject ) return;

	while( ( !m_lstDebugLines.empty() ) || m_bClearOldLines )
	{
		// Set up the message.
		CAutoMessage cMsg;

		cMsg.Writeuint8( MID_SFX_MESSAGE );

		// Record the ID and server object, used to route the message.
		cMsg.Writeuint8( SFX_DEBUGLINE_ID );
		cMsg.WriteObject( m_hObject );

		// Record the number of entries.
		int cLines = m_lstDebugLines.size();
		if( cLines < s_MaxLinesPerMessage )
		{
			cMsg.Writeuint16( cLines );
		}
		else
		{
			cMsg.Writeuint16( s_MaxLinesPerMessage );
		}

		// Tell whether we want to clear old lines or not, 
		cMsg.Writebool( m_bClearOldLines );
		cMsg.Writebool( m_bRelative );

		// Record each entry.

		int iLine=0;
		DEBUG_LINE_LIST::iterator itLine;
		for( itLine = m_lstDebugLines.begin(); itLine != m_lstDebugLines.end(); ++itLine )
		{
			cMsg.WriteType( *itLine );
			++iLine;
			if( iLine >= s_MaxLinesPerMessage )
			{
				break;
			}
		}
		m_lstDebugLines.erase( m_lstDebugLines.begin(), itLine );

		cMsg.WriteString( m_DebugString.c_str() );
		cMsg.WriteLTVector( m_vDebugStringPos );

		// Send the message!
		g_pLTServer->SendToClient(cMsg.Read(), NULL, MESSAGE_GUARANTEED);
		
		// If we have cleared out our lines and have no more to send,
		// why should we exist?
		if( m_bClearOldLines && ( cLines == 0 ) )
		{
			char szObjectName[256];
			g_pLTServer->GetObjectName(m_hObject, szObjectName, LTARRAYSIZE(szObjectName));
			LineSystem::SystemMap::iterator iter = LineSystem::g_systems.find( szObjectName );
			if( iter != LineSystem::g_systems.end() )
			{
				LineSystem::g_systems.erase(iter);
			}

			g_pLTServer->RemoveObject(m_hObject);
		}

		// Reset m_bClearOldLines so that we don't re-enter this block.
		m_bClearOldLines = false;
	}
}
Пример #17
0
bool ScmdServer_Impl::HandleSetGameOption( HCLIENT hClient, ILTMessage_Read& msg )
{
	bool bOk = true;

	// Get the game option they are setting.
	uint8 nGameOption = msg.Readuint8( );

	// Read in the value.
	char szVal[256];
	msg.ReadString( szVal, ARRAY_LEN( szVal ));

	ServerMissionSettings sms = g_pServerMissionMgr->GetServerSettings();
	switch( g_pGameServerShell->GetGameType( ))
	{
		case eGameTypeDeathmatch:
		{
			switch( nGameOption )
			{
				// Runspeed.
				case 0:
				{
					SetGameOption( sms.m_nRunSpeed, atoi( szVal ), 100, 150 );
				}
				break;
				// Score limit.
				case 1:
				{
					SetGameOption( sms.m_nScoreLimit, atoi( szVal ), 0, 255 );
				}
				break;
				// Time limit.
				case 2:
				{
					SetGameOption( sms.m_nTimeLimit, atoi( szVal ), 0, 255 );
				}
				break;
				// Rounds.
				case 3:
				{
					SetGameOption( sms.m_nRounds, atoi( szVal ), 1, 255 );
				}
				break;
				default:
				{
					bOk = false;
				}
				break;
			}
		}
		break;

		case eGameTypeTeamDeathmatch:
		{
			switch( nGameOption )
			{
				// Runspeed.
				case 0:
				{
					SetGameOption( sms.m_nRunSpeed, atoi( szVal ), 100, 150 );
				}
				break;
				// Score limit.
				case 1:
				{
					SetGameOption( sms.m_nScoreLimit, atoi( szVal ), 0, 255 );
				}
				break;
				// Time limit.
				case 2:
				{
					SetGameOption( sms.m_nTimeLimit, atoi( szVal ), 0, 255 );
				}
				break;
				// Rounds.
				case 3:
				{
					SetGameOption( sms.m_nRounds, atoi( szVal ), 1, 255 );
				}
				break;
				// Friendly fire.
				case 4:
				{
					SetGameOption( sms.m_bFriendlyFire, ( bool )( !!atoi( szVal )), false, true );
				}
				break;
				default:
				{
					bOk = false;
				}
				break;
			}
		}
		break;

		case eGameTypeDoomsDay:
		{
			switch( nGameOption )
			{
				// Runspeed.
				case 0:
				{
					SetGameOption( sms.m_nRunSpeed, atoi( szVal ), 100, 150 );
				}
				break;
				// Time limit.
				case 1:
				{
					SetGameOption( sms.m_nTimeLimit, atoi( szVal ), 0, 255 );
				}
				break;
				// Rounds.
				case 2:
				{
					SetGameOption( sms.m_nRounds, atoi( szVal ), 1, 255 );
				}
				break;
				// Friendly fire.
				case 3:
				{
					SetGameOption( sms.m_bFriendlyFire, ( bool )( !!atoi( szVal )), false, true );
				}
				break;
				default:
				{
					bOk = false;
				}
				break;
			}
		}
		break;

		case eGameTypeCooperative:
		{
			switch( nGameOption )
			{
				// Friendly fire.
				case 0:
				{
					SetGameOption( sms.m_bFriendlyFire, ( bool )( !!atoi( szVal )), false, true );
				}
				break;

				// mp difficulty.
				case 1:
				{
					SetGameOption( sms.m_nMPDifficulty, atoi( szVal ), 0, 255 );
				}
				break;

				// player diff factor.
				case 2:
				{
					SetGameOption( sms.m_fPlayerDiffFactor, ( float )atof( szVal ), 0.0f, 20.0f );
				}
				break;

				default:
				{
					bOk = false;
				}
				break;
			}
		}
		break;

		default:
		{
			bOk = false;
		}
		break;
	}
	
	// We need to tell the host client about the new settings.
	if( bOk )
	{
		// Record any changes.
		g_pServerMissionMgr->SetServerSettings(sms);

		// Try to find a local host if one exists.
		HCLIENT hHost = g_pLTServer->GetNextClient( NULL );
		while( hHost )
		{
			uint32 nClientInfoFlags = g_pLTServer->GetClientInfoFlags( hHost );
			if( nClientInfoFlags & CIF_LOCAL )
			{
				break;
			}

			hHost = g_pLTServer->GetNextClient( hHost );
		}
		
		// If we have a host, tell them about the new settings.
		if( hHost )
		{
			CAutoMessage cMsg;
			cMsg.Writeuint8( MID_MULTIPLAYER_OPTIONS );
			cMsg.Writeuint8( sms.m_nRunSpeed);
			cMsg.Writeuint8( sms.m_nScoreLimit);
			cMsg.Writeuint8( sms.m_nTimeLimit);
			cMsg.Writeuint8( sms.m_nRounds);
			cMsg.Writebool( sms.m_bFriendlyFire);
			cMsg.Writeuint8( sms.m_nMPDifficulty);
			cMsg.Writefloat( sms.m_fPlayerDiffFactor);
			g_pLTServer->SendToClient( cMsg.Read( ), hHost, MESSAGE_GUARANTEED );
		}
	}

	SendStatusMessage( hClient, kScmdCommandSetGameOption, ( bOk ) ? kScmdCommandStatusOk : kScmdCommandStatusFailed );

	return true;
}