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