void LightGroup::UpdateClients() { // Calculate our current color LTVector vColor = (m_bOn) ? m_vColor : LTVector(0.0f, 0.0f, 0.0f); { // Set up the update message CAutoMessage cMsg; cMsg.Writeuint8(MID_SFX_MESSAGE); cMsg.Writeuint8(SFX_LIGHTGROUP_ID); cMsg.WriteObject(m_hObject); cMsg.Writeuint32(m_nID); cMsg.WriteLTVector(vColor); // Send the message to all connected clients g_pLTServer->SendToClient(cMsg.Read(), LTNULL, MESSAGE_GUARANTEED); } { CAutoMessage cMsg; cMsg.Writeuint8(SFX_LIGHTGROUP_ID); cMsg.Writeuint32(m_nID); cMsg.WriteLTVector(vColor); // Make sure new clients will get the message g_pLTServer->SetObjectSFXMessage(m_hObject, cMsg.Read()); } m_bClientNeedsUpdate = false; }
void CClientMeleeCollisionController::HandleBlocked(HOBJECT hTarget, const LTVector& vPos, const LTVector& vDir) { // Get the proper weapon record... CClientWeapon* pClientWeapon = g_pClientWeaponMgr->GetCurrentClientWeapon(); HWEAPON hWeapon = pClientWeapon ? pClientWeapon->GetWeaponRecord() : NULL; //!!ARL: Use Attacker's weapon instead? (will need to be sent from server - probably along with block info) HWEAPONDATA hWeaponData = g_pWeaponDB->GetWeaponData(hWeapon, !USE_AI_DATA); // Spawn a block effect for it... const char* pszBlockFX = g_pWeaponDB->GetString(hWeaponData, "BlockFX"); CLIENTFX_CREATESTRUCT fxcs(pszBlockFX, 0, LTRigidTransform(vPos, LTRotation(vDir, LTVector(0,1,0)))); g_pGameClientShell->GetSimulationTimeClientFXMgr().CreateClientFX(NULL, fxcs, true); // Let the server objects know they've blocked / been blocked. CAutoMessage cMsg; cMsg.Writeuint8(MID_OBJECT_MESSAGE); cMsg.WriteObject(m_hObject); cMsg.Writeuint32(MID_MELEEBLOCK); cMsg.WriteObject(hTarget); g_pLTClient->SendToServer(cMsg.Read(), MESSAGE_GUARANTEED); // Disable attacker's collision (i.e. stop attacking). DisableCollisions(); // For local player attackers, send a BlockRecoil stimulus so a proper animation can be played. if (m_hObject == g_pPlayerMgr->GetMoveMgr()->GetObject()) { CPlayerBodyMgr::Instance().HandleAnimationStimulus("CS_RecoilFromBlock"); } }
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 DecisionObject::Show(bool bShow, bool bForceShow) { if( m_bLock ) return; // Send message to clients telling them about the DecisionObject... CAutoMessage cMsg; cMsg.Writeuint8(MID_DECISION); m_bVisible = bShow; if (bShow) { cMsg.Writeuint8(LTTRUE); cMsg.Writeuint8( (bForceShow ? LTTRUE : LTFALSE) ); for (int i=0; i < MAX_DECISION_CHOICES; i++) { cMsg.Writeuint32(m_ChoiceData[i].nStringID); } cMsg.WriteObject(m_hObject); cMsg.Writefloat(m_fRadius); } else { cMsg.Writeuint8(LTFALSE); cMsg.WriteObject(m_hObject); } g_pLTServer->SendToClient(cMsg.Read(), LTNULL, MESSAGE_GUARANTEED); }
void CCheatMgr::SendCheatMessage( CheatCode nCheatCode, uint32 nData ) { // Send the Message to the server CAutoMessage cMsg; cMsg.Writeuint8(MID_PLAYER_CHEAT); cMsg.Writeuint8((uint8)nCheatCode); cMsg.Writeuint32(nData); g_pLTClient->SendToServer(cMsg.Read(), MESSAGE_GUARANTEED); }
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); }
LTRESULT SendEmptyObjectMsg(uint32 nMsgID, HOBJECT hSource, HOBJECT hDest, uint32 nFlags) { LTRESULT nResult; CAutoMessage cMsg; cMsg.Writeuint32(nMsgID); nResult = g_pLTServer->SendToObject(cMsg.Read(), hSource, hDest, nFlags); return nResult; }
void CClientWeaponDisc::SendDefendMessage( uint8 cBlockMsgType, uint32 nAni ) const { LTRESULT ltResult; CAutoMessage cMsg; cMsg.Writeuint8( MID_PROJECTILE ); // write the projectile subtype cMsg.Writeuint8( cBlockMsgType ); // write the weapon type for server validation cMsg.Writeuint8( m_nAmmoId ); // write the current timestamp (in milliseconds) cMsg.Writeuint32( static_cast< int >( g_pLTClient->GetTime() * 1000.0f ) ); // get the swat defenese animation length uint32 nLength; ltResult = g_pModelLT->GetAnimLength( m_hObject, nAni, nLength ); ASSERT( LT_OK == ltResult ); // write the length cMsg.Writeuint32( nLength ); // send the message ltResult = g_pLTClient->SendToServer( cMsg.Read(), MESSAGE_GUARANTEED ); ASSERT( LT_OK == ltResult ); }
void CClientMeleeCollisionController::HandleCollision(HOBJECT hTarget, HMODELNODE hNodeHit, EPhysicsGroup eHitPhysics, const LTVector& vPos, const LTVector& vDir) { // Check if the attack has been blocked via rigidbody... if (eHitPhysics == PhysicsUtilities::ePhysicsGroup_UserBlockMelee) { HandleBlocked(hTarget, vPos, vDir); return; } // Check if the attack has been blocked via forced blocking (what the AI does)... CCharacterFX* pTargetFX = g_pGameClientShell->GetSFXMgr()->GetCharacterFX(hTarget); if (pTargetFX && pTargetFX->IsBlocking()) { HandleBlocked(hTarget, vPos, vDir); return; } // Handle normal damage... CAutoMessage cMsg; cMsg.Writeuint8(MID_OBJECT_MESSAGE); cMsg.WriteObject(m_hObject); cMsg.Writeuint32(MID_MELEEATTACK); cMsg.WriteObject(hTarget); cMsg.Writeuint32(hNodeHit); cMsg.WriteLTVector(vPos); cMsg.WriteLTVector(vDir); cMsg.Writeint32(g_pGameClientShell->GetServerRealTimeMS()); g_pLTClient->SendToServer(cMsg.Read(), MESSAGE_GUARANTEED); //!!ARL: Maybe DisableCollisions for hTarget if they are blocking? // (to avoid the weirdness of taking damage but still blocking the attack) // For local player targets, send an AttackRecoil stimulus so a proper animation can be played. if (hTarget == g_pPlayerMgr->GetMoveMgr()->GetObject()) { CPlayerBodyMgr::Instance().HandleAnimationStimulus("CS_RecoilFromAttack"); } }
void SpecialFX::TurnON() { if (!m_bLoop) { // We can turn on (create) non-looping fx as often as we want... ::PlayClientFX(m_sFxName, m_hObject, m_hTargetObj, LTNULL, LTNULL, LTNULL, m_dwFxFlags); if (m_bOneTime) { g_pLTServer->RemoveObject(m_hObject); } if( m_bRemoveTarget ) { g_pLTServer->RemoveObject( m_hTargetObj ); } } else if (!m_bIsOn) { CAutoMessage cMsg; cMsg.Writeuint8( SFX_CLIENTFXGROUP ); cMsg.WriteString( m_sFxName ); cMsg.Writeuint32( m_dwFxFlags ); if( m_hTargetObj ) { cMsg.Writeuint8( true ); cMsg.WriteObject( m_hTargetObj ); LTVector vPos; g_pLTServer->GetObjectPos( m_hTargetObj, &vPos ); cMsg.WriteCompPos( vPos ); } else { cMsg.Writeuint8( false ); } g_pLTServer->SetObjectSFXMessage( m_hObject, cMsg.Read() ); // Set flags so the client knows we are on... g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags, FLAG_FORCECLIENTUPDATE, FLAG_FORCECLIENTUPDATE ); g_pCommonLT->SetObjectFlags( m_hObject, OFT_User, USRFLG_SFX_ON, USRFLG_SFX_ON ); } m_bIsOn = true; }
void SetObjectClientFXMsg( HOBJECT hObj, char *sName, uint32 dwFlags ) { // [KLS 5/19/02] This really should be depricated, the only place that is // currently using it is the KeyItem and that object really shouldn't be // turning itself into a half-prop/half-special fx mutant. CAutoMessage cMsg; cMsg.Writeuint8( SFX_CLIENTFXGROUP ); cMsg.WriteString( sName ); cMsg.Writeuint32( dwFlags ); // Do not use any target information... cMsg.Writeuint8( false ); g_pLTServer->SetObjectSFXMessage( hObj, cMsg.Read() ); }
LTRESULT CTO2GameServerShell::OnServerInitialized() { LTRESULT nResult = CGameServerShell::OnServerInitialized(); // Don't do anything special if we're playing single-player if (!IsMultiplayerGame( )) { SetServerDir(0); return nResult; } IServerDirectory *pServerDir = Factory_Create_IServerDirectory_Titan( false, *g_pLTServer, NULL ); if( !pServerDir ) { ASSERT( !"ServerDir is NULL!" ); return LT_ERROR; } SetServerDir(pServerDir); // Set the game's name pServerDir->SetGameName(g_pVersionMgr->GetNetGameName()); // Set the version pServerDir->SetVersion(g_pVersionMgr->GetNetVersion()); pServerDir->SetRegion(g_pVersionMgr->GetNetRegion()); // Set up the network messaging header CAutoMessage cMsg; cMsg.Writeuint8(0xD); // SMSG_MESSAGE cMsg.Writeuint8(MID_MULTIPLAYER_SERVERDIR); pServerDir->SetNetHeader(*cMsg.Read()); StartupInfo_Titan startupInfo; startupInfo.m_sGameSpyName = "nolf2"; // Obfuscate the secret key a little. startupInfo.m_sGameSpySecretKey = "g"; startupInfo.m_sGameSpySecretKey += "3"; startupInfo.m_sGameSpySecretKey += "F"; startupInfo.m_sGameSpySecretKey += "o"; startupInfo.m_sGameSpySecretKey += "6"; startupInfo.m_sGameSpySecretKey += "x"; cMsg.Writeuint32(( uint32 )&startupInfo ); pServerDir->SetStartupInfo( *cMsg.Read( )); return nResult; }
void ModItem::ObjectTouch(HOBJECT hObject, bool bForcePickup/*=false*/) { if (!hObject) return; // If we hit non-player objects, just ignore them... if (IsPlayer(hObject)) { CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject(hObject); if (pPlayer && !pPlayer->IsDead()) { SetPlayerObj(hObject); CAutoMessage cMsg; cMsg.Writeuint32(MID_ADDMOD); cMsg.Writeuint8((uint8)m_nModId); g_pLTServer->SendToObject(cMsg.Read(), m_hObject, hObject, MESSAGE_GUARANTEED); } } }
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); } } }
bool ServerPhysicsCollisionMgr::HandleRigidBodyCollision( CollisionData& collisionData ) { if( !PhysicsCollisionMgr::HandleRigidBodyCollision( collisionData )) return false; // Check if this event needs to get sent to the client. if( collisionData.bSendToClient ) { CAutoMessage cMsg; cMsg.Writeuint8( MID_PHYSICSCOLLISION ); // We send the rigidbody values down to the client, even though // they can't be dereferenced. They will be used to // uniquely identify this collision event on the client. cMsg.Writeuint32(( uint32 )collisionData.hBodyA ); cMsg.Writeuint32(( uint32 )collisionData.hBodyB ); // Send the objects down if we had rigid bodies. We // can't get the objects without the rigid bodies, so // only sending them when we have non-null rigid bodies saves bandwidth. if( collisionData.hBodyA != INVALID_PHYSICS_RIGID_BODY ) cMsg.WriteObject( collisionData.hObjectA ); if( collisionData.hBodyB != INVALID_PHYSICS_RIGID_BODY ) cMsg.WriteObject( collisionData.hObjectB ); // We can write out 8bits of index here because we already // have a 255 limit on collisionproperties, since they must fit in the userflags. cMsg.Writeuint8(( uint8 )g_pLTDatabase->GetRecordIndex( collisionData.hCollisionPropertyA )); cMsg.Writeuint8(( uint8 )g_pLTDatabase->GetRecordIndex( collisionData.hCollisionPropertyB )); // Super fine resolution of the impulse isn't necessary // since the data tables are defined with integers. cMsg.Writefloat(collisionData.fImpulse); cMsg.WriteLTVector( collisionData.vCollisionPt ); cMsg.WriteLTVector( collisionData.vCollisionNormal ); // We're sending unguaranteed, since it's not essential the client is informed, // since it's just sounds and clientfx. g_pLTServer->SendToClient( cMsg.Read(), NULL, 0 ); } return true; }
void AmmoBox::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()) { int nValidIds = 0; for (int i=0; i < AB_MAX_TYPES; i++) { if (m_nAmmoId[i] != WMGR_INVALID_ID && m_nAmmoCount[i] > 0) { nValidIds++; } } if (nValidIds) { CAutoMessage cMsg; cMsg.Writeuint32(MID_AMMOBOX); cMsg.Writeuint8(nValidIds); for (int i=0; i < AB_MAX_TYPES; i++) { if (m_nAmmoId[i] != WMGR_INVALID_ID && m_nAmmoCount[i] > 0) { cMsg.Writeuint8(m_nAmmoId[i]); cMsg.Writeint32(m_nAmmoCount[i]); } } g_pLTServer->SendToObject(cMsg.Read(), m_hObject, hObject, MESSAGE_GUARANTEED); } } } }
void ClientVoteMgr::CallVoteKick(VoteType eVoteType, uint32 nClientID) { if (IsVoteInProgress()) { g_pTransmission->Show("ScreenVote_VoteInProgress"); return; } if (IsVoteDelayed()) { wchar_t szMsg[256]; szMsg[0] = '\0'; FormatString("ScreenVote_VoteDelayed",szMsg,LTARRAYSIZE(szMsg),(uint32)m_VoteDelayTimer.GetTimeLeft()); g_pTransmission->Show(szMsg); return; } CAutoMessage cMsg; cMsg.Writeuint8( MID_VOTE ); cMsg.WriteBits( eVote_Start, FNumBitsExclusive<kNumVoteActions>::k_nValue ); cMsg.WriteBits( eVoteType, FNumBitsExclusive<kNumVoteTypes>::k_nValue ); cMsg.Writeuint32( nClientID ); g_pLTClient->SendToServer( cMsg.Read(), 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); } }
uint32 Turret::ObjectMessageFn( HOBJECT hSender, ILTMessage_Read *pMsg ) { // Reset message to begining... pMsg->SeekTo( 0 ); uint32 dwMsgId = pMsg->Readuint32( ); switch( dwMsgId ) { case MID_DAMAGE : { uint32 dwMsgPos = pMsg->Tell( ); // Process base first so the dead flag gets set... uint32 dwRet = GameBase::ObjectMessageFn( hSender, pMsg ); if( m_Damage.IsDead( )) { OnDeath( ); } else { // Determine the percentage of health left on the turret... // This will be used to create certain ClientFX based on damage states... float fHealthPercent = 0.0f; if( m_Damage.GetMaxHitPoints( ) > 0.0f ) { fHealthPercent = m_Damage.GetHitPoints( ) / m_Damage.GetMaxHitPoints( ); } HATTRIBUTE hDamageStateStruct = g_pWeaponDB->GetAttribute( m_hTurret, WDB_TURRET_DamageState ); uint32 nNumDamageStates = g_pWeaponDB->GetNumValues( hDamageStateStruct ); uint32 nDamageState; for( nDamageState = 0; nDamageState < nNumDamageStates; ++nDamageState ) { // Run through the damage states and determine which ones to display... HATTRIBUTE hAttrib = g_pWeaponDB->GetStructAttribute( hDamageStateStruct, nDamageState, WDB_TURRET_fHealthPercent ); float fDamageStatePercent = g_pWeaponDB->GetFloat( hAttrib ); if( nDamageState > m_nCurDamageState && fDamageStatePercent >= fHealthPercent ) { m_nCurDamageState = nDamageState; } } // Send damage msg to operating client... CPlayerObj *pPlayer = dynamic_cast<CPlayerObj*>(g_pLTServer->HandleToObject( m_hOperatingObject )); if( pPlayer ) { CAutoMessage cMsg; cMsg.Writeuint8( MID_SFX_MESSAGE ); cMsg.Writeuint8( SFX_TURRET_ID ); cMsg.WriteObject( m_hObject ); cMsg.Writeuint8( kTurretFXMsg_Damage ); cMsg.Writeuint32( m_nCurDamageState ); g_pLTServer->SendToClient( cMsg.Read( ), pPlayer->GetClient( ), MESSAGE_GUARANTEED ); } } return dwRet; } break; } return GameBase::ObjectMessageFn( hSender, pMsg ); }
// ----------------------------------------------------------------------- // // // 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; if( nextLineToSend != lines.end() || 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. const int num_lines_left = (lines.end() - nextLineToSend); if( num_lines_left < s_MaxLinesPerMessage ) { cMsg.Writeuint16( num_lines_left ); } else { cMsg.Writeuint16( s_MaxLinesPerMessage ); } // Record the maximum number of lines. cMsg.Writeuint32( m_nMaxLines ); // Tell whether we want to clear old lines or not, cMsg.Writeuint8( m_bClearOldLines ); // Record each entry. int num_lines_sent = 0; LTVector system_center(0,0,0); LTFLOAT system_center_count = 0; while( nextLineToSend != lines.end() && num_lines_sent < s_MaxLinesPerMessage) { cMsg.WriteType( *nextLineToSend ); ++nextLineToSend; ++num_lines_sent; } #ifdef LINESYSTEM_DEBUG g_pLTServer->CPrint("Sent %d lines. %d lines left to send.", num_lines_sent, lines.end() - nextLineToSend ); #endif cMsg.WriteString( m_DebugString.c_str() ); // Send the message! g_pLTServer->SendToClient(cMsg.Read(), LTNULL, MESSAGE_GUARANTEED); // If we have cleared out our lines and have no more to send, // why should we exist? if( m_bClearOldLines && lines.empty() ) { char szObjectName[256]; g_pLTServer->GetObjectName(m_hObject, szObjectName, 256); LineSystem::SystemMap::iterator iter = LineSystem::g_systems.find( std::string(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; } }
void ServerVoteMgr::HandleVoteStart(HCLIENT hSender, ILTMessage_Read* pMsg) { if (!hSender) { return; } if (IsVoteInProgress()) { // Tell the player why their vote didn't start SendCancelVoteInProgress( hSender ); return; } VoteType eVoteType = (VoteType)pMsg->ReadBits( FNumBitsExclusive<kNumVoteTypes>::k_nValue ); //check to see if we have a real client uint32 nCallerID = g_pLTServer->GetClientID( hSender ); HCLIENT hCallerClient = g_pLTServer->GetClientHandle( nCallerID ); if( !hCallerClient ) return; GameClientData* pCallerGameClientData = ServerConnectionMgr::Instance().GetGameClientData( hCallerClient ); if( !pCallerGameClientData ) return; //check to see if the client has a live player... if (!GameModeMgr::Instance( ).m_grbAllowDeadVoting) { CPlayerObj* pPlayerObj = ( CPlayerObj* )g_pLTServer->HandleToObject( pCallerGameClientData->GetPlayer( )); if( !pPlayerObj || !pPlayerObj->IsAlive( )) { return; } }; // Make sure we start fresh. ClearVote( ); switch(eVoteType) { case eVote_Kick: case eVote_TeamKick: case eVote_Ban: { uint32 nTargetID = pMsg->Readuint32(); HCLIENT hTargetClient = g_pLTServer->GetClientHandle( nTargetID ); if( !hTargetClient ) return; GameClientData* pTargetGameClientData = ServerConnectionMgr::Instance().GetGameClientData( hTargetClient ); if( !pTargetGameClientData ) return; // Iterate through all the clients and see if anyone is ready to vote. ServerConnectionMgr::GameClientDataList& gameClientDataList = ServerConnectionMgr::Instance( ).GetGameClientDataList( ); ServerConnectionMgr::GameClientDataList::iterator iter = gameClientDataList.begin( ); for( ; iter != gameClientDataList.end( ); iter++ ) { GameClientData* pGameClientData = *iter; if( !pGameClientData->GetClient( )) continue; // Skip clients that aren't ready to play yet. if( pGameClientData->GetClientConnectionState() != eClientConnectionState_InWorld ) continue; // Client must have reached the inworld state. if( !pGameClientData->IsClientInWorld( )) continue; // Restrict elibible voters if it's a team kick. if( eVoteType == eVote_TeamKick ) { if( pCallerGameClientData->GetLastTeamId() != pGameClientData->GetLastTeamId( )) continue; } // Add to the eligible voter list. m_lstEligibleVoter.push_back( pGameClientData->GetClient( )); } // Check if we have a quorum of voters. uint32 nQuorum = ( eVoteType == eVote_TeamKick ) ? GameModeMgr::Instance().m_ServerSettings.m_nMinPlayersForTeamVote : GameModeMgr::Instance().m_ServerSettings.m_nMinPlayersForVote; //figure out how many votes are needed to pass uint8 nVotesNeeded = ((m_lstEligibleVoter.size() + 2) / 2); //the "+ 2" is here to ensure a majority not just half //if we have less than the "minimum" number of players, the vote must pass unanimously if( m_lstEligibleVoter.size( ) < nQuorum ) { nVotesNeeded = m_lstEligibleVoter.size( ); } // Put the caller on the list of voters already cast. m_lstVoterCastYes.push_back( pCallerGameClientData->GetClient( )); float fDuration = GameModeMgr::Instance().m_ServerSettings.m_nVoteLifetime; m_VoteTimer.Start(fDuration); m_CurrentVote.m_eVoteType = eVoteType; m_CurrentVote.m_nVoteID = m_CurrentVote.m_nVoteID++; //increment vote ID so that each vote is more or less unique... will wrap after 256 votes m_CurrentVote.m_nTargetID = nTargetID; m_CurrentVote.m_nCallerID = nCallerID; m_CurrentVote.m_nNoVotes = 0; m_CurrentVote.m_nYesVotes = 1; m_CurrentVote.m_nVotesNeeded = nVotesNeeded; CAutoMessage cMsg; cMsg.Writeuint8( MID_VOTE ); cMsg.WriteBits( eVote_Start, FNumBitsExclusive<kNumVoteActions>::k_nValue ); cMsg.Writeuint8( m_CurrentVote.m_nVoteID ); cMsg.WriteBits( eVoteType, FNumBitsExclusive<kNumVoteTypes>::k_nValue ); cMsg.Writeuint32( nCallerID ); cMsg.Writeuint32( nTargetID ); cMsg.Writeuint8( m_CurrentVote.m_nVotesNeeded ); cMsg.Writedouble( m_VoteTimer.GetTimeLeft( )); // Send the vote start info to the eligible voters. SendToEligibleVoters( *cMsg.Read( )); // Check if we've already achieved necessary votes. CheckVoteStatus(); } break; case eVote_NextRound: case eVote_NextMap: { // Iterate through all the clients and see if anyone is ready to vote. ServerConnectionMgr::GameClientDataList& gameClientDataList = ServerConnectionMgr::Instance( ).GetGameClientDataList( ); ServerConnectionMgr::GameClientDataList::iterator iter = gameClientDataList.begin( ); for( ; iter != gameClientDataList.end( ); iter++ ) { GameClientData* pGameClientData = *iter; if( !pGameClientData->GetClient( )) continue; // Skip clients that aren't ready to play yet. if( pGameClientData->GetClientConnectionState() != eClientConnectionState_InWorld ) continue; // Client must have reached the inworld state. if( !pGameClientData->IsClientInWorld( )) continue; // Add to the eligible voter list. m_lstEligibleVoter.push_back( pGameClientData->GetClient( )); } // Check if we have a quorum of voters. uint32 nQuorum = GameModeMgr::Instance().m_ServerSettings.m_nMinPlayersForVote; //figure out how many votes are needed to pass uint8 nVotesNeeded = ((m_lstEligibleVoter.size() + 2) / 2); //the "+ 2" is here to ensure a majority not just half //if we have less than the "minimum" number of players, the vote must pass unanimously if( m_lstEligibleVoter.size( ) < nQuorum ) { nVotesNeeded = m_lstEligibleVoter.size( ); } // Put the caller on the list of voters already cast. m_lstVoterCastYes.push_back( pCallerGameClientData->GetClient( )); float fDuration = GameModeMgr::Instance().m_ServerSettings.m_nVoteLifetime; m_VoteTimer.Start(fDuration); m_CurrentVote.m_eVoteType = eVoteType; m_CurrentVote.m_nVoteID = m_CurrentVote.m_nVoteID++; //increment vote ID so that each vote is more or less unique... will wrap after 256 votes m_CurrentVote.m_nTargetID = 0; m_CurrentVote.m_nCallerID = nCallerID; m_CurrentVote.m_nNoVotes = 0; m_CurrentVote.m_nYesVotes = 1; m_CurrentVote.m_nVotesNeeded = nVotesNeeded; CAutoMessage cMsg; cMsg.Writeuint8( MID_VOTE ); cMsg.WriteBits( eVote_Start, FNumBitsExclusive<kNumVoteActions>::k_nValue ); cMsg.Writeuint8( m_CurrentVote.m_nVoteID ); cMsg.WriteBits( eVoteType, FNumBitsExclusive<kNumVoteTypes>::k_nValue ); cMsg.Writeuint32( nCallerID ); cMsg.Writeuint32( 0 ); cMsg.Writeuint8( m_CurrentVote.m_nVotesNeeded ); cMsg.Writedouble( m_VoteTimer.GetTimeLeft( )); // Send the vote start info to the eligible voters. SendToEligibleVoters( *cMsg.Read( )); // Check if we've already achieved necessary votes. CheckVoteStatus(); } break; case eVote_SelectMap: { uint32 nMapIndex = pMsg->Readuint32(); uint32 nCallerID = g_pLTServer->GetClientID( hSender ); HCLIENT hCallerClient = g_pLTServer->GetClientHandle( nCallerID ); if( !hCallerClient ) return; GameClientData* pCallerGameClientData = ServerConnectionMgr::Instance().GetGameClientData( hCallerClient ); if( !pCallerGameClientData ) return; // Iterate through all the clients and see if anyone is ready to vote. ServerConnectionMgr::GameClientDataList& gameClientDataList = ServerConnectionMgr::Instance( ).GetGameClientDataList( ); ServerConnectionMgr::GameClientDataList::iterator iter = gameClientDataList.begin( ); for( ; iter != gameClientDataList.end( ); iter++ ) { GameClientData* pGameClientData = *iter; if( !pGameClientData->GetClient( )) continue; // Skip clients that aren't ready to play yet. if( pGameClientData->GetClientConnectionState() != eClientConnectionState_InWorld ) continue; // Client must have reached the inworld state. if( !pGameClientData->IsClientInWorld( )) continue; // Add to the eligible voter list. m_lstEligibleVoter.push_back( pGameClientData->GetClient( )); } // Check if we have a quorum of voters. uint32 nQuorum = GameModeMgr::Instance().m_ServerSettings.m_nMinPlayersForVote; //figure out how many votes are needed to pass uint8 nVotesNeeded = ((m_lstEligibleVoter.size() + 2) / 2); //the "+ 2" is here to ensure a majority not just half //if we have less than the "minimum" number of players, the vote must pass unanimously if( m_lstEligibleVoter.size( ) < nQuorum ) { nVotesNeeded = m_lstEligibleVoter.size( ); } // Put the caller on the list of voters already cast. m_lstVoterCastYes.push_back( pCallerGameClientData->GetClient( )); float fDuration = GameModeMgr::Instance().m_ServerSettings.m_nVoteLifetime; m_VoteTimer.Start(fDuration); m_CurrentVote.m_eVoteType = eVoteType; m_CurrentVote.m_nVoteID = m_CurrentVote.m_nVoteID++; //increment vote ID so that each vote is more or less unique... will wrap after 256 votes m_CurrentVote.m_nTargetID = nMapIndex; m_CurrentVote.m_nCallerID = nCallerID; m_CurrentVote.m_nNoVotes = 0; m_CurrentVote.m_nYesVotes = 1; m_CurrentVote.m_nVotesNeeded = nVotesNeeded; CAutoMessage cMsg; cMsg.Writeuint8( MID_VOTE ); cMsg.WriteBits( eVote_Start, FNumBitsExclusive<kNumVoteActions>::k_nValue ); cMsg.Writeuint8( m_CurrentVote.m_nVoteID ); cMsg.WriteBits( eVoteType, FNumBitsExclusive<kNumVoteTypes>::k_nValue ); cMsg.Writeuint32( nCallerID ); cMsg.Writeuint32( nMapIndex ); cMsg.Writeuint8( m_CurrentVote.m_nVotesNeeded ); cMsg.Writedouble( m_VoteTimer.GetTimeLeft( )); // Send the vote start info to the eligible voters. SendToEligibleVoters( *cMsg.Read( )); // Check if we've already achieved necessary votes. CheckVoteStatus(); } break; } }