EnemyGPP

Untitled

Jan 28th, 2018
523
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 202.88 KB | None | 0 0
  1. #include "r3dPCH.h"
  2. #include "r3d.h"
  3. #include "GameLevel.h"
  4.  
  5. #include "ServerGameLogic.h"
  6. #include "MasterServerLogic.h"
  7. #include "GameObjects/ObjManag.h"
  8.  
  9. #include "ObjectsCode/obj_ServerPlayer.h"
  10. #include "ObjectsCode/obj_ServerGravestone.h"
  11. #include "ObjectsCode/obj_ServerGrenade.h"
  12. #include "ObjectsCode/obj_ServerLightMesh.h"
  13. #include "ObjectsCode/sobj_SpawnedItem.h"
  14. #include "ObjectsCode/sobj_DroppedItem.h"
  15. #include "ObjectsCode/sobj_Note.h"
  16. #include "ObjectsCode/Zombies/sobj_Zombie.h"
  17. #include "ObjectsCode/Vehicles/obj_Vehicle.h"
  18. #include "ObjectsCode/obj_ServerPlayerSpawnPoint.h"
  19. #include "ObjectsCode/Zombies/sobj_ZombieSpawn.h"
  20. #include "ObjectsCode/obj_ServerBarricade.h"
  21. #include "ObjectsCode/obj_ServerLockbox.h"
  22. #include "ObjectsCode/obj_ServerFarmBlock.h"
  23. #include "ObjectsCode/Missions/MissionManager.h"
  24. #include "ObjectsCode/Missions/MissionTrigger.h"
  25. #include "ObjectsCode/obj_ServerItemSpawnPoint.h"//
  26. #include "ObjectsCode/obj_ServerGasZone.h"//
  27. #include "../EclipseStudio/Sources/ObjectsCode/Gameplay/BattleZone.h"//
  28.  
  29. #include "../EclipseStudio/Sources/GameCode/UserProfile.h"
  30. #include "../EclipseStudio/Sources/ObjectsCode/weapons/WeaponArmory.h"
  31. #include "../EclipseStudio/Sources/ObjectsCode/Gameplay/ZombieStates.h"
  32.  
  33. #include "ServerWeapons/ServerWeapon.h"
  34.  
  35. #include "NetworkHelper.h"
  36. #include "AsyncFuncs.h"
  37. #include "Async_ServerObjects.h"
  38. #include "Async_ServerState.h"
  39. #include "TeamSpeakServer.h"
  40.  
  41. #ifdef ENABLE_GAMEBLOCKS
  42. #include "GBClient/Inc/GBClient.h"
  43. #include "GBClient/Inc/GBReservedEvents.h"
  44.  
  45. #pragma comment(lib, "../../../server/GameBlocksSDK/Lib/vc100/Win32/GBClient.lib")
  46.  
  47. // PunkBuster SDK
  48. #ifdef __WITH_PB__
  49. #include "PunkBuster/pbcommon.h"
  50. #endif
  51.  
  52. GameBlocks::GBClient* g_GameBlocks_Client = NULL;
  53. GameBlocks::GBPublicSourceId g_GameBlocks_ServerID=0;
  54. bool g_GameBlocks_SentServerInfo = false;
  55. #endif //ENABLE_GAMEBLOCKS
  56.  
  57. ServerGameLogic gServerLogic;
  58.  
  59. const float RESPAWN_TIME_AIRDROPBR = 5.0f * 60.0f;//
  60. const float RESPAWN_TIME_AIRDROP = 4.0f * 60.0f * 60.0f; // 4 hours
  61. CVAR_FLOAT( _glm_bzOutKillTime, 5.0f, "battle zone out kill time");//
  62.  
  63. CVAR_FLOAT( _glm_SpawnRadius, 1.0f, "");
  64.  
  65. extern __int64 cfg_sessionId;
  66.  
  67. #include "../EclipseStudio/Sources/Gameplay_Params.h"
  68. CGamePlayParams GPP_Data;
  69. DWORD GPP_Seed = GetTickCount(); // seed used to xor CRC of gpp_data
  70.  
  71. extern float getWaterDepthAtPos(const r3dPoint3D& pos);
  72.  
  73.  
  74. bool IsNullTerminated(const char* data, int size)
  75. {
  76. for(int i=0; i<size; i++) {
  77. if(data[i] == 0)
  78. return true;
  79. }
  80.  
  81. return false;
  82. }
  83.  
  84. //
  85. //
  86. //
  87. //
  88. static void preparePacket(const GameObject* from, DefaultPacket* packetData)
  89. {
  90. r3d_assert(packetData);
  91. r3d_assert(packetData->EventID >= 0);
  92.  
  93. if(from && from->Class->Name != "obj_Building") {
  94. r3d_assert(from->GetNetworkID());
  95. //r3d_assert(from->NetworkLocal);
  96.  
  97. packetData->FromID = toP2pNetId(from->GetNetworkID());
  98. } else {
  99. packetData->FromID = 0; // world event
  100. }
  101.  
  102. return;
  103. }
  104.  
  105. ServerGameLogic::ServerGameLogic()
  106. {
  107. curPlayers_ = 0;
  108. maxLoggedPlayers_ = 0;
  109. curPeersConnected = 0;
  110.  
  111. if(!ginfo_.IsGameBR())//
  112. AirDropSpawnTime = r3dGetTime() + RESPAWN_TIME_AIRDROP;
  113.  
  114. // init index to players table
  115. for(int i=0; i<MAX_NUM_PLAYERS; i++) {
  116. plrToPeer_[i] = NULL;
  117. }
  118.  
  119. // init peer to player table
  120. for(int i=0; i<MAX_PEERS_COUNT; i++) {
  121. peers_[i].Clear();
  122. }
  123.  
  124. memset(&netRecvPktSize, 0, sizeof(netRecvPktSize));
  125. memset(&netSentPktSize, 0, sizeof(netSentPktSize));
  126.  
  127. net_lastFreeId = NETID_OBJECTS_START;
  128. net_mapLoaded_LastNetID = 0;
  129.  
  130. weaponStats_.reserve(128);
  131. }
  132.  
  133. ServerGameLogic::~ServerGameLogic()
  134. {
  135. }
  136.  
  137. void ServerGameLogic::Init(const GBGameInfo& ginfo, uint32_t creatorID)
  138. {
  139. r3dOutToLog("Game: Initializing with %d players\n", ginfo.maxPlayers); CLOG_INDENT;
  140. r3d_assert(curPlayers_ == 0);
  141. r3d_assert(curPeersConnected == 0);
  142.  
  143. creatorID_ = creatorID;
  144. ginfo_ = ginfo;
  145. curPlayers_ = 0;
  146. curPeersConnected = 0;
  147.  
  148. secsWithoutPlayers_ = 0;
  149. hibernateStarted_ = false;
  150. gameStartTimeAdminOffset = 0;
  151.  
  152. //
  153. if(ginfo_.IsGameBR())
  154. {
  155. m_isGameHasStarted = false;
  156. ForceStarGame = false;
  157. isCountingDown = false;
  158. canFinishMatch = false;
  159. haveWinningPlayer = false;
  160. playersTeleported = false;
  161. isGasSuspended = true;
  162. winningPlr = NULL;
  163. suspendTimer = 0;
  164. gasint = 0;
  165. rewardBR = 100;//reward here. synch point server/client (obj_Player::OnCreate() || obj_Player::OnDestroy())
  166. canCheckPlayers = r3dGetTime();
  167. gastimer = r3dGetTime();
  168. AirDropSpawnTime = r3dGetTime() + RESPAWN_TIME_AIRDROPBR;
  169.  
  170. r3dOutToLog("|=======================| Server game: Battle Royale |=======================|\n");
  171. }
  172. //
  173.  
  174. nextGroupID = 1;
  175.  
  176. nextLootboxUpdate_ = r3dGetTime() + u_GetRandom(10*60, 15*60); // spread lootbox update a bit across all servers
  177.  
  178. // init game time
  179. gameStartTime_ = r3dGetTime();
  180.  
  181. __int64 utcTime = GetUtcGameTime();
  182. struct tm* tm = _gmtime64(&utcTime);
  183. r3d_assert(tm);
  184.  
  185. char buf[128];
  186. asctime_s(buf, sizeof(buf), tm);
  187. r3dOutToLog("Server time is %s", buf);
  188.  
  189. return;
  190. }
  191.  
  192. void ServerGameLogic::SetNewGameInfo(DWORD flags, int gameTimeLimit)
  193. {
  194. ginfo_.flags = flags;
  195. ginfo_.gameTimeLimit = gameTimeLimit;
  196.  
  197. PKT_S2C_SetGameInfoFlags_s n;
  198. n.gameInfoFlags = ginfo_.flags;
  199. //
  200. if(ginfo_.IsGameBR() && !isCountingDown)
  201. n.GD = rewardBR*playersStarted;
  202. else
  203. n.GD =0;
  204. //
  205. p2pBroadcastToAll(&n, sizeof(n), true);
  206. }
  207.  
  208. void ServerGameLogic::CreateHost(int port)
  209. {
  210. r3dOutToLog("Starting server on port %d\n", port);
  211.  
  212. g_net.Initialize(this, "p2pNet");
  213. g_net.CreateHost(port, MAX_PEERS_COUNT);
  214. //g_net.dumpStats_ = 2;
  215.  
  216. return;
  217. }
  218.  
  219. void ServerGameLogic::Disconnect()
  220. {
  221. r3dOutToLog("Disconnect server\n");
  222.  
  223. #ifdef ENABLE_GAMEBLOCKS
  224. if(g_GameBlocks_Client)
  225. {
  226. g_GameBlocks_Client->Close();
  227. delete g_GameBlocks_Client;
  228. g_GameBlocks_Client = NULL;
  229. }
  230. #endif //ENABLE_GAMEBLOCKS
  231.  
  232. g_net.Deinitialize();
  233.  
  234. return;
  235. }
  236.  
  237. void ServerGameLogic::OnGameStart()
  238. {
  239. /*
  240. if(1)
  241. {
  242. r3dOutToLog("Main World objects\n"); CLOG_INDENT;
  243. for(GameObject* obj=GameWorld().GetFirstObject(); obj; obj=GameWorld().GetNextObject(obj))
  244. {
  245. if(obj->isActive()) r3dOutToLog("obj: %s %s\n", obj->Class->Name.c_str(), obj->Name.c_str());
  246. }
  247. }
  248.  
  249. if(1)
  250. {
  251. extern ObjectManager ServerDummyWorld;
  252. r3dOutToLog("Temporary World objects\n"); CLOG_INDENT;
  253. for(GameObject* obj=ServerDummyWorld.GetFirstObject(); obj; obj=ServerDummyWorld.GetNextObject(obj))
  254. {
  255. if(obj->isActive()) r3dOutToLog("obj: %s %s\n", obj->Class->Name.c_str(), obj->Name.c_str());
  256. }
  257. }*/
  258.  
  259.  
  260. // record last net id
  261. net_mapLoaded_LastNetID = net_lastFreeId;
  262. r3dOutToLog("net_mapLoaded_LastNetID: %d\n", net_mapLoaded_LastNetID);
  263.  
  264. // start getting server objects
  265. g_AsyncApiMgr->AddJob(new CJobGetServerObjects());
  266. // and saved state for objects
  267. g_AsyncApiMgr->AddJob(new CJobGetSavedServerState());
  268.  
  269. #ifdef ENABLE_GAMEBLOCKS
  270. // start gameblocks
  271. bool startGameblocks = false; // THAI server
  272. if(startGameblocks)
  273. {
  274. if(g_GameBlocks_Client)
  275. {
  276. r3dError("Gameblocks already initialized?!\n");
  277. }
  278. g_GameBlocks_SentServerInfo = false;
  279. g_GameBlocks_Client = new GameBlocks::GBClient();
  280. g_GameBlocks_ServerID = uint32_t(ginfo_.gameServerId);
  281.  
  282. /* GameBlocks::ClientConfigData gameblocks_config;
  283. gameblocks_config.gameblocksEnabled = true;
  284. gameblocks_config.serverAddress = "216.152.129.156";
  285. gameblocks_config.serverPort = 8730;
  286. gameblocks_config.sourceId = g_GameBlocks_ServerID;
  287. gameblocks_config.timeoutPeriod = 7;
  288. g_GameBlocks_Client->SetConfig(gameblocks_config);
  289.  
  290. if(!g_GameBlocks_Client->Connect())*/
  291.  
  292. extern int cfg_uploadLogs;
  293.  
  294. const char* gbServerURL=NULL;
  295. const char* gbServerIP=NULL;
  296. int gbServerPort=0;
  297. if(cfg_uploadLogs) // production environment (todo: need a different variable for that)
  298. {
  299. gbServerURL = "hammerpoint.infestation1.prod.gameblocks.info";
  300. gbServerPort = 8730;
  301. }
  302. else
  303. {
  304. gbServerIP = "67.86.56.36";
  305. gbServerPort = 8730;
  306. }
  307.  
  308.  
  309. r3dOutToLog("Connecting to gameblocks server '%s' at port %d\n", gbServerURL?gbServerURL:gbServerIP, gbServerPort);
  310.  
  311. GameBlocks::EGBClientError errCode;
  312. if(gbServerURL)
  313. errCode = g_GameBlocks_Client->ConnectUsingUrl(gbServerURL, gbServerPort, g_GameBlocks_ServerID);
  314. else
  315. errCode = g_GameBlocks_Client->Connect(gbServerIP, gbServerPort, g_GameBlocks_ServerID);
  316.  
  317. if(errCode != GameBlocks::GBCLIENT_ERROR_OK)
  318. {
  319. r3dOutToLog("Gameblocks failed to connect, code: %d\n", errCode);
  320. }
  321. g_GameBlocks_Client->SetTimeoutPeriod(30);
  322.  
  323. g_GameBlocks_Client->EnableAimBotDetector(8, 0.1f);
  324. if(!cfg_uploadLogs) // dev env only
  325. g_GameBlocks_Client->SetAimBotDetectorDebugPlayer("1641409");
  326. g_GameBlocks_Client->EnableWeaponCheatDetector(300);
  327. }
  328. #endif //ENABLE_GAMEBLOCKS
  329. }
  330.  
  331. DWORD ServerGameLogic::GetFreeNetId()
  332. {
  333. DWORD id = net_lastFreeId;
  334.  
  335. while(true)
  336. {
  337. if(GameWorld().GetNetworkObject(id) == NULL)
  338. {
  339. net_lastFreeId = id + 1;
  340. if(net_lastFreeId > 0xFFF0)
  341. net_lastFreeId = net_mapLoaded_LastNetID;
  342.  
  343. return id;
  344. }
  345.  
  346. id++;
  347. if(id > 0xFFF0)
  348. id = net_mapLoaded_LastNetID;
  349.  
  350. // check if we looped back
  351. if(id == net_lastFreeId)
  352. r3dError("net_lastFreeId overflow, no free slots");
  353. }
  354. }
  355.  
  356. void ServerGameLogic::CheckPeerValidity()
  357. {
  358. const float PEER_CHECK_DELAY = 0.2f; // do checks every N seconds
  359. const float IDLE_PEERS_DELAY = 5.0f; // peer have this N seconds to validate itself
  360. const float LOADING_PEER_PING = 60.0f; // loading peers must ping API every N seconds to indicate that player still in game
  361. const float LOADING_MAX_TIME = 600.0f; // max loading time for client
  362. const float SECREP1_DELAY = PKT_C2S_SecurityRep_s::REPORT_PERIOD*8; // x4 time of client reporting time (15sec) to receive security report
  363.  
  364. static float nextCheck = -1;
  365. const float curTime = r3dGetTime();
  366. if(curTime < nextCheck)
  367. return;
  368. nextCheck = curTime + PEER_CHECK_DELAY;
  369.  
  370. for(int peerId=0; peerId<MAX_PEERS_COUNT; peerId++)
  371. {
  372. peerInfo_s& peer = peers_[peerId];
  373. if(peer.status_ == PEER_FREE)
  374. continue;
  375.  
  376. // check againts not validated peers
  377. if(peer.status_ == PEER_CONNECTED)
  378. {
  379. if(curTime < peer.startTime + IDLE_PEERS_DELAY)
  380. continue;
  381.  
  382. DisconnectPeer(peerId, false, "no validation, last:%f/%d", peer.lastPacketTime, peer.lastPacketId);
  383. continue;
  384. }
  385.  
  386. // loading peers
  387. if(peer.status_ == PEER_LOADING)
  388. {
  389. if(curTime > peer.startTime + LOADING_MAX_TIME)
  390. {
  391. DisconnectPeer(peerId, true, "too long loading");
  392. continue;
  393. }
  394.  
  395. // have profile and joined the game
  396. if(peer.startGameAns == PKT_S2C_StartGameAns_s::RES_Ok)
  397. {
  398. if(peer.nextPingOnLoad < 0)
  399. peer.nextPingOnLoad = curTime + LOADING_PEER_PING;
  400.  
  401. if(curTime > peer.nextPingOnLoad)
  402. {
  403. peer.nextPingOnLoad = curTime + LOADING_PEER_PING;
  404. CJobUserPingGame* job = new CJobUserPingGame(peerId);
  405. g_AsyncApiMgr->AddJob(job);
  406. }
  407. }
  408. continue;
  409. }
  410.  
  411. // for playing peers - check for receiveing security report
  412. if(peer.player != NULL)
  413. {
  414. if(curTime > peer.secRepRecvTime + SECREP1_DELAY)
  415. {
  416. //DisconnectPeer(peerId, false, "no SecRep, last:%f/%d", peer.lastPacketTime, peer.lastPacketId);
  417. continue;
  418. }
  419. if(curTime > m_LastConnectionRep + 120)
  420. {
  421. peer.player->isHighPing = false;
  422. continue;
  423. }
  424. }
  425.  
  426. /*if(peer.player != NULL)//AlexRedd:: last connection
  427. {
  428. if(curTime > m_LastConnectionRep + 120)
  429. {
  430. peer.player->isHighPing = false;
  431. continue;
  432. }
  433. }*/
  434. }
  435.  
  436. return;
  437. }
  438.  
  439. //Skin system
  440. void ServerGameLogic::ApiPlayerUpdateWeaponSkins(obj_ServerPlayer* plr)
  441. {
  442. for( std::map< uint32_t, obj_ServerPlayer::WeaponSkins >::iterator Skinids = plr->WpnSKN.begin();Skinids != plr->WpnSKN.end(); ++Skinids )
  443. {
  444. obj_ServerPlayer::WeaponSkins& SkinWpn = Skinids->second;
  445.  
  446. if (SkinWpn.itemID != 0)
  447. {
  448. //r3dOutToLog("############ GUARDANDO EN LA DB\n");
  449. for (int i = 0;i<MAX_SKINS_BY_WEAPON;i++)
  450. {
  451. if (SkinWpn.SkinsBought[i] != 99)
  452. {
  453. CJobChangeWeaponSkins* job = new CJobChangeWeaponSkins(plr);
  454. job->ItemID = SkinWpn.itemID;
  455. job->Skin = SkinWpn.SkinsBought[i];
  456. job->LastSkinUsed = SkinWpn.LastSKINused;
  457. g_AsyncApiMgr->AddJob(job);
  458. }
  459. }
  460. }
  461. }
  462. }
  463. /////
  464.  
  465. void ServerGameLogic::ApiPlayerUpdateChar(obj_ServerPlayer* plr, bool disconnectAfter)
  466. {
  467. r3d_assert(!plr->inventoryOpActive_);
  468.  
  469. // force current GameFlags update
  470. plr->UpdateGameWorldFlags();
  471.  
  472. CJobUpdateChar* job = new CJobUpdateChar(plr);
  473. job->CharData = *plr->loadout_;
  474. job->OldData = plr->savedLoadout_;
  475. job->Disconnect = disconnectAfter;
  476. job->GD_Diff = plr->profile_.ProfileData.GameDollars - plr->savedGameDollars_;
  477. job->ResWood = plr->profile_.ProfileData.ResWood;
  478. job->ResStone = plr->profile_.ProfileData.ResStone;
  479. job->ResMetal = plr->profile_.ProfileData.ResMetal;
  480. job->SwearingCount = plr->profile_.ProfileData.SwearingCount;
  481. // add character play time to update data
  482. job->CharData.Stats.TimePlayed += (int)(r3dGetTime() - plr->startPlayTime_);
  483. g_AsyncApiMgr->AddJob(job);
  484.  
  485. bool needPing=false;
  486. #ifdef DISABLE_GI_ACCESS_ON_PTE_MAP
  487. if(gServerLogic.ginfo_.channel==6) // in PTE game, ping player
  488. needPing=true;
  489. #endif
  490. #ifdef DISABLE_GI_ACCESS_ON_PTE_STRONGHOLD_MAP
  491. if(gServerLogic.ginfo_.channel==6 && gServerLogic.ginfo_.mapId==GBGameInfo::MAPID_WZ_Cliffside) // in PTE game, ping player
  492. needPing=true;
  493. #endif
  494. #ifdef DISABLE_GI_ACCESS_FOR_CALI_SERVER
  495. if(gServerLogic.ginfo_.mapId==GBGameInfo::MAPID_WZ_California)
  496. needPing=true;
  497. #endif
  498. #ifdef DISABLE_GI_ACCESS_FOR_DEV_EVENT_SERVER
  499. if(gServerLogic.ginfo_.channel==6)
  500. needPing=true;
  501. #endif
  502.  
  503. if(needPing && !disconnectAfter)
  504. {
  505. CJobUserPingGame* pingJob = new CJobUserPingGame(plr->peerId_);
  506. g_AsyncApiMgr->AddJob(pingJob);
  507. }
  508. // replace character saved loadout. if update will fail, we'll disconnect player and keep everything at sync
  509. plr->savedLoadout_ = *plr->loadout_;
  510. plr->savedGameDollars_ = plr->profile_.ProfileData.GameDollars;
  511. }
  512.  
  513. void ServerGameLogic::ApiPlayerLeftGame(DWORD peerId)
  514. {
  515. const ServerGameLogic::peerInfo_s& peer = GetPeer(peerId);
  516. r3d_assert(peer.status_ >= PEER_LOADING);
  517.  
  518. CJobUserLeftGame* job = new CJobUserLeftGame(peerId);
  519. job->GameMapId = ginfo_.mapId;
  520. job->GameServerId = ginfo_.gameServerId;
  521. if(peer.player) {
  522. job->TimePlayed = (int)(r3dGetTime() - peer.player->startPlayTime_);
  523. }
  524. g_AsyncApiMgr->AddJob(job);
  525. }
  526.  
  527. void ServerGameLogic::LogInfo(DWORD peerId, const char* msg, const char* fmt, ...)
  528. {
  529. char buf[4096];
  530. va_list ap;
  531. va_start(ap, fmt);
  532. StringCbVPrintfA(buf, sizeof(buf), fmt, ap);
  533. va_end(ap);
  534.  
  535. LogCheat(peerId, 0, false, msg, buf);
  536. }
  537.  
  538. void ServerGameLogic::LogCheat(DWORD peerId, int LogID, int disconnect, const char* msg, const char* fmt, ...)
  539. {
  540. char buf[4096];
  541. va_list ap;
  542. va_start(ap, fmt);
  543. StringCbVPrintfA(buf, sizeof(buf), fmt, ap);
  544. va_end(ap);
  545.  
  546. const peerInfo_s& peer = GetPeer(peerId);
  547. DWORD IP = net_->GetPeerIp(peerId);
  548.  
  549. //extern int cfg_uploadLogs; // we don't use it anymore
  550. if(LogID > 0) // always upload cheats
  551. {
  552. CJobAddLogInfo* job = new CJobAddLogInfo();
  553. job->CheatID = LogID;
  554. job->CustomerID = peer.CustomerID;
  555. job->CharID = peer.CharID;
  556. job->IP = IP;
  557. r3dscpy(job->Gamertag, peer.temp_profile.ProfileData.ArmorySlots[0].Gamertag);
  558. r3dscpy(job->Msg, msg);
  559. r3dscpy(job->Data, buf);
  560. g_AsyncApiMgr->AddJob(job);
  561. }
  562.  
  563. const char* screenname = "<NOT_CONNECTED>";
  564. if(peer.status_ == PEER_PLAYING)
  565. screenname = peer.temp_profile.ProfileData.ArmorySlots[0].Gamertag;
  566.  
  567. r3dOutToLog("%s: peer%02d, r:%s %s, CID:%d [%s], ip:%s\n",
  568. LogID > 0 ? "!!! cheat" : "LogInfo",
  569. peerId,
  570. msg, buf,
  571. peer.CustomerID, screenname,
  572. inet_ntoa(*(in_addr*)&IP));
  573.  
  574. if(disconnect && peer.player)
  575. {
  576. // tell client he's cheating.
  577. // ptumik: no need to make it easier to hack
  578. //PKT_S2C_CheatWarning_s n2;
  579. //n2.cheatId = (BYTE)cheatId;
  580. //p2pSendRawToPeer(peerId, NULL, &n2, sizeof(n2));
  581.  
  582. net_->DisconnectPeer(peerId);
  583. // fire up disconnect event manually, enet might skip if if other peer disconnect as well
  584. OnNetPeerDisconnected(peerId);
  585. }
  586.  
  587. return;
  588. }
  589.  
  590. void ServerGameLogic::DisconnectPeer(DWORD peerId, bool cheat, const char* fmt, ...)
  591. {
  592. char buf[1024];
  593. va_list ap;
  594. va_start(ap, fmt);
  595. StringCbVPrintfA(buf, sizeof(buf), fmt, ap);
  596. va_end(ap);
  597.  
  598. LogCheat(peerId, cheat ? 99 : 0, false, "DisconnectPeer", buf);
  599.  
  600. net_->DisconnectPeer(peerId);
  601.  
  602. // fire up disconnect event manually, enet might skip if if other peer disconnect as well
  603. OnNetPeerDisconnected(peerId);
  604. }
  605.  
  606. void ServerGameLogic::OnNetPeerConnected(DWORD peerId)
  607. {
  608. //
  609. /*if (ginfo_.IsGameBR())
  610. {
  611. int startPlayers = (int)(ginfo_.maxPlayers * 0.5f);
  612. if (curPlayers_ >= startPlayers && !m_isGameHasStarted && !isCountingDown)
  613. {
  614. r3dOutToLog("Minimum required players achieved, starting match\n");
  615. StartCountdown();
  616. }
  617. }*/
  618. //
  619.  
  620. // too many connections, do not allow more connects
  621. if(peerId >= MAX_PEERS_COUNT)
  622. {
  623. r3dOutToLog("!!! peer%02d over MAX_PEERS_COUNT connected\n", peerId);
  624. net_->DisconnectPeer(peerId);
  625. return;
  626. }
  627.  
  628. if(gMasterServerLogic.shuttingDown_ || gameFinished_)
  629. {
  630. r3dOutToLog("peer connected while game is finished or shutting down\n");
  631. net_->DisconnectPeer(peerId);
  632. return;
  633. }
  634.  
  635. r3d_assert(ginfo_.maxPlayers > 0);
  636.  
  637. //r3dOutToLog("peer%02d connected\n", peerId); CLOG_INDENT;
  638.  
  639. peerInfo_s& peer = GetPeer(peerId);
  640. peer.SetStatus(PEER_CONNECTED);
  641.  
  642. curPeersConnected++;
  643. return;
  644. }
  645.  
  646. void ServerGameLogic::OnNetPeerDisconnected(DWORD peerId)
  647. {
  648. // too many connections, do not do anything
  649. if(peerId >= MAX_PEERS_COUNT)
  650. return;
  651.  
  652. //r3dOutToLog("peer%02d disconnected\n", peerId); CLOG_INDENT;
  653.  
  654. //
  655. if (ginfo_.IsGameBR())
  656. playersLeft--;
  657. //
  658.  
  659. peerInfo_s& peer = GetPeer(peerId);
  660.  
  661. // debug validation
  662. switch(peer.status_)
  663. {
  664. default:
  665. r3dError("!!! Invalid status %d in disconnect !!!", peer.status_);
  666. break;
  667. case PEER_FREE:
  668. break;
  669.  
  670. case PEER_CONNECTED:
  671. case PEER_VALIDATED1:
  672. r3d_assert(peer.player == NULL);
  673. r3d_assert(peer.playerIdx == -1);
  674. break;
  675.  
  676. case PEER_LOADING:
  677. r3d_assert(peer.playerIdx != -1);
  678. r3d_assert(plrToPeer_[peer.playerIdx] != NULL);
  679. r3d_assert(peer.player == NULL);
  680.  
  681. // if we got profile and joined game we need to report that player left to server.
  682. /*if(peer.startGameAns == PKT_S2C_StartGameAns_s::RES_Ok)
  683. {
  684. ApiPlayerLeftGame(peerId);
  685. }*/
  686.  
  687. plrToPeer_[peer.playerIdx] = NULL;
  688. break;
  689.  
  690. case PEER_PLAYING:
  691. r3d_assert(peer.playerIdx != -1);
  692. r3d_assert(plrToPeer_[peer.playerIdx] != NULL);
  693. r3d_assert(plrToPeer_[peer.playerIdx] == &peer);
  694. if(peer.player)
  695. {
  696. #ifdef VEHICLES_ENABLED
  697. // check if player is in vehicle, if is, remove player from vehicle
  698. if (peer.player->IsInVehicle())
  699. {
  700. obj_Vehicle* vehicle = obj_Vehicle::GetVehicleById(peer.player->currentVehicleId);
  701. if (vehicle)
  702. {
  703. peer.player->ExitVehicle(true, true, true);
  704. }
  705. }
  706. #endif
  707. gMasterServerLogic.RemovePlayer(peer.playerIdx);
  708.  
  709. if(peer.player->loadout_->Alive && !peer.player->wasDisconnected_/* && !peer.player->inventoryOpActive_*/)
  710. {
  711. r3dOutToLog("peer%02d player %s is updating his data\n", peerId, peer.player->userName);
  712. ApiPlayerUpdateChar(peer.player);
  713. }
  714.  
  715. ApiPlayerLeftGame(peerId);
  716.  
  717. // report to users
  718. //if(!(peer.player->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_HIDDEN))
  719. {
  720. PKT_S2C_PlayerNameLeft_s n;
  721. n.playerIdx = (WORD)peer.playerIdx;
  722.  
  723. // send to all, regardless visibility
  724. for(int i=0; i<MAX_PEERS_COUNT; i++) {
  725. if(peers_[i].status_ >= PEER_PLAYING && peers_[i].player && i != peerId) {
  726. net_->SendToPeer(&n, sizeof(n), i, true);
  727. }
  728. }
  729. }
  730.  
  731. DeletePlayer(peer.playerIdx, peer.player);
  732. }
  733.  
  734. plrToPeer_[peer.playerIdx] = NULL;
  735. break;
  736. }
  737.  
  738. if(peer.status_ != PEER_FREE)
  739. {
  740. // OnNetPeerDisconnected can fire multiple times, because of forced disconnect
  741. curPeersConnected--;
  742. }
  743.  
  744. // clear peer status
  745. peer.Clear();
  746.  
  747. return;
  748. }
  749.  
  750. float ServerGameLogic::getInGameTime()
  751. {
  752. __int64 gameUtcTime = GetUtcGameTime();
  753. struct tm* tm = _gmtime64(&gameUtcTime);
  754. r3d_assert(tm);
  755. return ((float)tm->tm_hour + (float)tm->tm_min / 59.0f);
  756. }
  757.  
  758. void ServerGameLogic::OnNetData(DWORD peerId, const r3dNetPacketHeader* packetData, int packetSize)
  759. {
  760. #ifdef __WITH_PB__
  761. if ( memcmp ( packetData, "\xff\xff\xff\xffPB_", 7 ) == 0 ) {
  762. PbSvAddEvent ( PB_EV_PACKET, (int)peerId, packetSize-4, (char*)packetData+4 ) ;
  763. PbClAddEvent ( PB_EV_PACKET, packetSize-4, (char*)packetData+4 ) ;
  764. return ;
  765. }
  766. #endif
  767.  
  768. // too many connections, do not do anything
  769. if(peerId >= MAX_PEERS_COUNT)
  770. return;
  771.  
  772. // we can receive late packets from logically disconnected peer.
  773. peerInfo_s& peer = GetPeer(peerId);
  774. if(peer.status_ == PEER_FREE)
  775. return;
  776.  
  777. if(packetSize < sizeof(DefaultPacket))
  778. {
  779. DisconnectPeer(peerId, true, "small packetSize %d", packetSize);
  780. return;
  781. }
  782. const DefaultPacket* evt = static_cast<const DefaultPacket*>(packetData);
  783.  
  784. // store last packet data for debug
  785. peer.lastPacketTime = r3dGetTime();
  786. peer.lastPacketId = evt->EventID;
  787.  
  788. // store received sizes by packets
  789. if(evt->EventID < 256)
  790. netRecvPktSize[evt->EventID] += packetSize;
  791.  
  792. if(gameFinished_)
  793. {
  794. r3dOutToLog("!!! peer%02d got packet %d while game is finished\n", peerId, evt->EventID);
  795. return;
  796. }
  797.  
  798. GameObject* fromObj = GameWorld().GetNetworkObject(evt->FromID);
  799.  
  800.  
  801. //r3dOutToLog("PACKET(%d): evtID:%d\n", peerId, evt->EventID);
  802.  
  803. // pass to world even processor first.
  804. if(ProcessWorldEvent(fromObj, evt->EventID, peerId, packetData, packetSize)) {
  805. return;
  806. }
  807.  
  808. if(evt->FromID && fromObj == NULL) {
  809. DisconnectPeer(peerId, true, "bad event %d from not registered object %d", evt->EventID, evt->FromID);
  810. return;
  811. }
  812.  
  813. if(fromObj)
  814. {
  815. if(IsServerPlayer(fromObj))
  816. {
  817. // make sure that sender of that packet is same player on server
  818. if(((obj_ServerPlayer*)fromObj)->peerId_ != peerId)
  819. {
  820. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Network, false, "PlayerPeer",
  821. "peerID: %d, player: %d, packetID: %d",
  822. peerId, ((obj_ServerPlayer*)fromObj)->peerId_, evt->EventID);
  823. return;
  824. }
  825. }
  826.  
  827. if(!fromObj->OnNetReceive(evt->EventID, packetData, packetSize))
  828. {
  829. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Network, true, "BadObjectEvent",
  830. "%d for %s %d",
  831. evt->EventID, fromObj->Name.c_str(), fromObj->GetNetworkID());
  832. }
  833. return;
  834. }
  835.  
  836. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Network, true, "BadWorldEvent",
  837. "event %d from %d, obj:%s",
  838. evt->EventID, evt->FromID, fromObj ? fromObj->Name.c_str() : "NONE");
  839. return;
  840. }
  841.  
  842. int ServerGameLogic::getReputationKillEffect(int repFromPlr, int repKilledPlr)
  843. {
  844. // Reputation system. Splits into three subsystems
  845. // CIVILIAN LOGIC
  846. if(repFromPlr > -20 && repFromPlr < 20)
  847. {
  848. if(repKilledPlr >= 1000)
  849. repFromPlr -= 20;
  850. else if(repKilledPlr >= 500)
  851. repFromPlr -= 15;
  852. else if(repKilledPlr >= 250)
  853. repFromPlr -= 10;
  854. else if(repKilledPlr >= 80)
  855. repFromPlr -= 4;
  856. else if(repKilledPlr >= 20)
  857. repFromPlr -= 3;
  858. else if(repKilledPlr >= 10)
  859. repFromPlr -= 2;
  860. else if(repKilledPlr <= -1000)
  861. repFromPlr += 20;
  862. else if(repKilledPlr <= -600)
  863. repFromPlr += 15;
  864. else if(repKilledPlr <= -300)
  865. repFromPlr += 10;
  866. else if(repKilledPlr <= -100)
  867. repFromPlr += 4;
  868. else if(repKilledPlr <= -20)
  869. repFromPlr += 3;
  870. else if(repKilledPlr <= -5)
  871. repFromPlr += 2;
  872. else
  873. repFromPlr -= 1;
  874.  
  875. }
  876. // BANDIT LOGIC (once you are in bandit section, you cannot come up to be neutral)
  877. else if(repFromPlr <= -20)
  878. {
  879. if(repKilledPlr >= 1000)
  880. repFromPlr -= 20;
  881. else if(repKilledPlr >= 500)
  882. repFromPlr -= 15;
  883. else if(repKilledPlr >= 250)
  884. repFromPlr -= 10;
  885. else if(repKilledPlr >= 80)
  886. repFromPlr -= 4;
  887. else if(repKilledPlr >= 20)
  888. repFromPlr -= 3;
  889. else if(repKilledPlr >= 10)
  890. repFromPlr -= 2;
  891. else if(repKilledPlr <= -1000)
  892. repFromPlr -= 20;
  893. else if(repKilledPlr <= -600)
  894. repFromPlr -= 15;
  895. else if(repKilledPlr <= -300)
  896. repFromPlr -= 10;
  897. else if(repKilledPlr <= -100)
  898. repFromPlr -= 4;
  899. else if(repKilledPlr <= -20)
  900. repFromPlr -= 3;
  901. else if(repKilledPlr <= -5)
  902. repFromPlr -= 2;
  903. else
  904. repFromPlr -= 1;
  905. }
  906. // LAWMAN LOGIC
  907. else if(repFromPlr >= 20)
  908. {
  909. if(repKilledPlr <= -1000)
  910. repFromPlr += 20;
  911. else if(repKilledPlr <= -600)
  912. repFromPlr += 15;
  913. else if(repKilledPlr <= -300)
  914. repFromPlr += 10;
  915. else if(repKilledPlr <= -100)
  916. repFromPlr += 4;
  917. else if(repKilledPlr <= -20)
  918. repFromPlr += 3;
  919. else if(repKilledPlr <= -5)
  920. repFromPlr += 2;
  921. // lawman is killing civilian\lawmen, hard penalty depending on how much of a lawmen killer is
  922. else if(repKilledPlr >= 1000)
  923. repFromPlr -= 125;
  924. else if(repKilledPlr >= 500)
  925. repFromPlr -= 60;
  926. else if(repKilledPlr >= 250)
  927. repFromPlr -= 40;
  928. else if(repKilledPlr >= 80)
  929. repFromPlr -= 15;
  930. else if(repKilledPlr >= 20)
  931. repFromPlr -= 2;
  932. else if(repKilledPlr >= 10)
  933. repFromPlr -= 1;
  934. else
  935. repFromPlr -= 1;
  936. }
  937.  
  938. return repFromPlr;
  939. }
  940.  
  941. void ServerGameLogic::DoKillPlayer(GameObject* sourceObj, obj_ServerPlayer* targetPlr, STORE_CATEGORIES weaponCat, bool forced_by_server, bool fromPlayerInAir, bool targetPlayerInAir )
  942. {
  943. r3dOutToLog("%s killed by %s, forced: %d\n", targetPlr->userName, sourceObj->Name.c_str(), (int)forced_by_server);
  944.  
  945. //AlexRedd:: KillFeed
  946. /*============================================================================*/
  947. //if (gServerLogic.ginfo_.channel == 6)
  948. {
  949. obj_ServerPlayer * killedByPlr = ((obj_ServerPlayer*)sourceObj);
  950. if(ginfo_.IsGameBR() && !m_isGameHasStarted)//
  951. killedByPlr->numKillWithoutDying = 0;
  952. else
  953. killedByPlr->numKillWithoutDying++;
  954. char deadplayer[128] = { 0 };
  955. char killerplayer[128] = { 0 };
  956. sprintf(deadplayer, targetPlr->userName);
  957. sprintf(killerplayer, killedByPlr->userName);
  958.  
  959. // sent kill packet
  960. PKT_S2C_KillPlayer_s n;
  961. if (IsServerPlayer(sourceObj))
  962. {
  963. if (targetPlr->profile_.CustomerID == killedByPlr->profile_.CustomerID &&
  964. !haveWinningPlayer) //
  965. {
  966. n.KillFlag = 1;
  967. r3dscpy(n.killer, deadplayer);
  968. }
  969. else if (targetPlr->lastHitBodyPart == 1)// By player headshot
  970. n.KillFlag = 2;
  971. else if (targetPlr->lastTimeHitItemID == WeaponConfig::ITEMID_UnarmedMelee) // By player Unarmed Melee
  972. n.KillFlag = 3;
  973. //
  974. else if (ginfo_.IsGameBR() && m_isGameHasStarted && haveWinningPlayer &&
  975. (targetPlr->profile_.CustomerID == killedByPlr->profile_.CustomerID))
  976. n.KillFlag = 6;
  977. //
  978. else//By player
  979. n.KillFlag = 4;
  980. }
  981. else if (sourceObj->isObjType(OBJTYPE_Zombie))//By zombie
  982. n.KillFlag = 5;
  983. else//Suicide
  984. n.KillFlag = 1;
  985. r3dscpy(n.victim, deadplayer);
  986. r3dscpy(n.killer, killerplayer);
  987. n.Killstreak = killedByPlr->numKillWithoutDying;
  988. n.lastTimeHitItemID = targetPlr->lastTimeHitItemID;
  989. n.targetId = toP2pNetId(targetPlr->GetNetworkID());
  990. n.killerWeaponCat = (BYTE)weaponCat;
  991. n.forced_by_server = forced_by_server;
  992. p2pBroadcastToActive(sourceObj, &n, sizeof(n), true);
  993. }
  994. /*============================================================================*/
  995.  
  996. {
  997. #ifdef VEHICLES_ENABLED
  998. if (targetPlr->IsInVehicle())
  999. targetPlr->ExitVehicle(true, true);
  1000. #endif
  1001. }
  1002.  
  1003. /*
  1004. if(!forced_by_server && sourceObj != targetPlr) // do not reward suicides
  1005. {
  1006. DropLootBox(targetPlr);
  1007. }*/
  1008.  
  1009. //
  1010. if (ginfo_.IsGameBR() && m_isGameHasStarted)
  1011. {
  1012. playersLeft--;
  1013. if(playersLeft>1)
  1014. {
  1015. PKT_C2C_ChatMessage_s n;
  1016. char buffer[64] = { 0 };
  1017. sprintf(buffer, "%i players left!", playersLeft);
  1018. r3dscpy(n.gamertag, "<BattleRoyale>");
  1019. r3dscpy(n.msg, buffer);
  1020. n.msgChannel = 1; // global
  1021. n.userFlag = 200; // battle royale
  1022. p2pBroadcastToAll(&n, sizeof(n), true);
  1023. }
  1024. }
  1025. //
  1026.  
  1027. // Initialize the player's aggressor for gravestone information
  1028. if( sourceObj->isObjType( OBJTYPE_Human ) )
  1029. {
  1030. if( sourceObj != targetPlr )
  1031. {
  1032. r3dscpy( targetPlr->aggressor, ((obj_ServerPlayer*)sourceObj)->userName );
  1033. targetPlr->killedBy = obj_ServerGravestone::KilledBy_Player;
  1034. }
  1035. else
  1036. {
  1037. r3dscpy( targetPlr->aggressor, "" );
  1038. targetPlr->killedBy = obj_ServerGravestone::KilledBy_Self;
  1039. }
  1040. }
  1041. else if( sourceObj->isObjType( OBJTYPE_Zombie ) )
  1042. {
  1043. r3dscpy( targetPlr->aggressor, "" );
  1044. targetPlr->killedBy = obj_ServerGravestone::KilledBy_Zombie;
  1045. }
  1046. #ifdef VEHICLES_ENABLED
  1047. else if( sourceObj->isObjType( OBJTYPE_Vehicle ) )
  1048. {
  1049. obj_Vehicle* veh = (obj_Vehicle*)sourceObj;
  1050. obj_ServerPlayer* p = veh->playersInVehicle[0];
  1051. if( p )
  1052. {
  1053. r3dscpy( targetPlr->aggressor, p->userName );
  1054. targetPlr->killedBy = obj_ServerGravestone::KilledBy_Player;
  1055. }
  1056. }
  1057. #endif
  1058. targetPlr->DoDeath();
  1059.  
  1060. if(forced_by_server)
  1061. return;
  1062.  
  1063. #ifdef ENABLE_GAMEBLOCKS
  1064. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  1065. {
  1066. if(IsServerPlayer(sourceObj))
  1067. {
  1068. g_GameBlocks_Client->PrepareEventForSending("Kill", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(IsServerPlayer(sourceObj)->profile_.CustomerID)));
  1069. g_GameBlocks_Client->AddKeyValueInt("VictimID", targetPlr->profile_.CustomerID);
  1070. g_GameBlocks_Client->AddKeyValueInt("WeaponType", weaponCat);
  1071. g_GameBlocks_Client->AddKeyValueFloat("Distance", (targetPlr->GetPosition()-sourceObj->GetPosition()).Length());
  1072. g_GameBlocks_Client->AddKeyValueVector3D("VictimPosition", targetPlr->GetPosition().x, targetPlr->GetPosition().y, targetPlr->GetPosition().z);
  1073. g_GameBlocks_Client->AddKeyValueVector3D("KillerPosition", sourceObj->GetPosition().x, sourceObj->GetPosition().y, sourceObj->GetPosition().z);
  1074. g_GameBlocks_Client->AddKeyValueInt("Headshot", targetPlr->lastHitBodyPart == 1);
  1075. g_GameBlocks_Client->AddKeyValueInt("WeaponID", targetPlr->lastTimeHitItemID);
  1076. g_GameBlocks_Client->AddKeyValueFloat("ServerTime", getInGameTime());
  1077. {
  1078. int hasNVG = 0;
  1079. if( IsServerPlayer(sourceObj)->isNVGEquipped() )
  1080. hasNVG = 1;
  1081. g_GameBlocks_Client->AddKeyValueInt("hasNVG", hasNVG);
  1082. }
  1083. g_GameBlocks_Client->SendEvent();
  1084. }
  1085. else if(sourceObj && sourceObj->Class->Name == "obj_Zombie")
  1086. {
  1087. g_GameBlocks_Client->PrepareEventForSending("KillByZombie", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(targetPlr->profile_.CustomerID)));
  1088. g_GameBlocks_Client->AddKeyValueVector3D("Position", targetPlr->GetPosition().x, targetPlr->GetPosition().y, targetPlr->GetPosition().z);
  1089. g_GameBlocks_Client->SendEvent();
  1090. }
  1091. }
  1092. #endif
  1093.  
  1094. targetPlr->loadout_->Stats.Deaths++;
  1095. //AddPlayerReward(targetPlr, RWD_Death, "RWD_Death");
  1096.  
  1097. // do not count suicide kills
  1098. if(sourceObj == targetPlr)
  1099. return;
  1100.  
  1101. if(IsServerPlayer(sourceObj))
  1102. {
  1103. // find spawn points within 500 meter radius of this kill and add "danger" to it
  1104. for(int i=0; i<gCPMgr.numControlPoints_; i++)
  1105. {
  1106. BasePlayerSpawnPoint* spawn = gCPMgr.controlPoints_[i];
  1107. for(int j=0; j<spawn->m_NumSpawnPoints; j++)
  1108. {
  1109. float dist = (targetPlr->GetPosition() - spawn->m_SpawnPoints[j].pos).Length();
  1110. if(dist < 500.0f)
  1111. {
  1112. spawn->m_SpawnPoints[j].danger++;
  1113. spawn->m_SpawnPoints[j].lastTimeDangerUpdated = r3dGetTime();
  1114. }
  1115. }
  1116. }
  1117. }
  1118.  
  1119. if(IsServerPlayer(sourceObj))
  1120. {
  1121. obj_ServerPlayer * fromPlr = ((obj_ServerPlayer*)sourceObj);
  1122.  
  1123. if(targetPlr->loadout_->Stats.Reputation > -5)
  1124. fromPlr->loadout_->Stats.KilledSurvivors++;
  1125. else
  1126. fromPlr->loadout_->Stats.KilledBandits++;
  1127.  
  1128. int origRep = fromPlr->loadout_->Stats.Reputation;
  1129.  
  1130. int newRep = getReputationKillEffect(fromPlr->loadout_->Stats.Reputation, targetPlr->loadout_->Stats.Reputation);
  1131. int diffRep = newRep - origRep;
  1132. if(diffRep < 0 && (r3dGetTime() < targetPlr->m_AggressionTimeUntil))
  1133. {
  1134. // do not do anything to fromPlr reputation. Target player had aggression timer on him, so our player is OK killing him without penalty
  1135. }
  1136. else
  1137. {
  1138. fromPlr->loadout_->Stats.Reputation = newRep;
  1139. if(diffRep != 0)
  1140. {
  1141. PKT_S2C_AddScore_s n;
  1142. n.ID = 0;
  1143. n.XP = 0;
  1144. n.GD = 0;
  1145. if(ginfo_.channel!=6 && //AlexRedd:: do not send reps for dev events servers
  1146. !ginfo_.IsGameBR())// // alex
  1147. n.Rep = diffRep;
  1148. else
  1149. n.Rep = 0;
  1150. p2pSendToPeer(fromPlr->peerId_, fromPlr, &n, sizeof(n));
  1151. }
  1152. }
  1153.  
  1154. if(!ginfo_.IsGameBR() && ginfo_.channel!=6)//
  1155. RewardKillPlayer(fromPlr, targetPlr, weaponCat);//AlexRedd:: kill rewards
  1156. }
  1157. // else if(sourceObj->isObjType(OBJTYPE_GameplayItem) && sourceObj->Class->Name == "obj_ServerAutoTurret")
  1158. // {
  1159. // // award kill to owner of the turret
  1160. // obj_ServerPlayer* turretOwner = IsServerPlayer(GameWorld().GetObject(sourceObj->ownerID));
  1161. // if(turretOwner)
  1162. // {
  1163. // turretOwner->loadout_->Stats.Kills++;
  1164. // }
  1165. // }
  1166.  
  1167. return;
  1168. }
  1169.  
  1170. void ServerGameLogic::RewardKillPlayer(obj_ServerPlayer* fromPlr, obj_ServerPlayer* targetPlr, STORE_CATEGORIES dmgCat)
  1171. {
  1172. r3d_assert(fromPlr);
  1173. r3d_assert(targetPlr);
  1174. //r3dOutToLog("RewardKillPlayer %s->%s\n", fromPlr->userName, targetPlr->userName); CLOG_INDENT;
  1175.  
  1176. if (fromPlr->numKillWithoutDying == 15)
  1177. AddPlayerReward(fromPlr, RWD_Kill15NotDying);
  1178. else if (fromPlr->numKillWithoutDying == 25)
  1179. AddPlayerReward(fromPlr, RWD_Kill25NotDying);
  1180. else if (fromPlr->numKillWithoutDying == 50)
  1181. {
  1182. AddPlayerReward(fromPlr, RWD_Kill50NotDying);
  1183. LogCheat(fromPlr->peerId_, PKT_S2C_CheatWarning_s::CHEAT_Kills, true, "HighKills 50");
  1184. }
  1185. else if (fromPlr->numKillWithoutDying == 100)
  1186. {
  1187. AddPlayerReward(fromPlr, RWD_Kill100NotDying);
  1188. LogCheat(fromPlr->peerId_, PKT_S2C_CheatWarning_s::CHEAT_Kills, true, "HighKills 100");
  1189. }
  1190.  
  1191. int gotKillReward = 0;
  1192. if (targetPlr->loadout_->ClanID != fromPlr->loadout_->ClanID)
  1193. {
  1194. // count kill streaks
  1195. if ((r3dGetTime() - fromPlr->LastEnemyKillTime) < GPP_Data.c_fKillStreakTimeout)
  1196. fromPlr->Killstreaks++;
  1197. else{
  1198. fromPlr->Killstreaks = 1;
  1199. if (dmgCat != storecat_GRENADE && (targetPlr->lastHitBodyPart == 1 && dmgCat != storecat_MELEE))
  1200. AddPlayerReward(fromPlr, RWD_PlayerKill);
  1201.  
  1202. }
  1203. if (fromPlr->Killstreaks == 2)
  1204. {
  1205. AddPlayerReward(fromPlr, RWD_Killstreak2);
  1206. gotKillReward++;
  1207. }
  1208. else if (fromPlr->Killstreaks == 3)
  1209. {
  1210. AddPlayerReward(fromPlr, RWD_Killstreak3);
  1211. gotKillReward++;
  1212. }
  1213. else if (fromPlr->Killstreaks == 4)
  1214. {
  1215. AddPlayerReward(fromPlr, RWD_Killstreak4);
  1216. gotKillReward++;
  1217. }
  1218. else if (fromPlr->Killstreaks == 5)
  1219. {
  1220. AddPlayerReward(fromPlr, RWD_Killstreak5);
  1221. gotKillReward++;
  1222. }
  1223. else if (fromPlr->Killstreaks == 6)
  1224. {
  1225. AddPlayerReward(fromPlr, RWD_Killstreak6);
  1226. gotKillReward++;
  1227. }
  1228. else if (fromPlr->Killstreaks == 7)
  1229. {
  1230. AddPlayerReward(fromPlr, RWD_Killstreak7);
  1231. gotKillReward++;
  1232. }
  1233. else if (fromPlr->Killstreaks == 8)
  1234. {
  1235. AddPlayerReward(fromPlr, RWD_Killstreak8);
  1236. gotKillReward++;
  1237. }
  1238.  
  1239. // update timer
  1240. fromPlr->LastEnemyKillTime = r3dGetTime();
  1241. }
  1242.  
  1243. if (dmgCat == storecat_GRENADE)
  1244. {
  1245. AddPlayerReward(fromPlr, RWD_ExplosionKill);
  1246. }
  1247. else if (targetPlr->lastHitBodyPart == 1 && dmgCat != storecat_MELEE) // headshot
  1248. {
  1249. AddPlayerReward(fromPlr, RWD_Headshot);
  1250. }
  1251. }
  1252.  
  1253. // make sure this function is the same on client: AI_Player.cpp bool canDamageTarget(const GameObject* obj)
  1254. bool ServerGameLogic::CanDamageThisObject(const GameObject* targetObj)
  1255. {
  1256. if(IsServerPlayer(targetObj))
  1257. {
  1258. return true;
  1259. }
  1260. else if(targetObj->isObjType(OBJTYPE_Zombie))
  1261. {
  1262. return true;
  1263. }
  1264. #ifdef VEHICLES_ENABLED
  1265. else if (targetObj->isObjType(OBJTYPE_Vehicle))
  1266. {
  1267. return true;
  1268. }
  1269. #endif
  1270. else if(targetObj->Class->Name == "obj_LightMesh")
  1271. {
  1272. return true;
  1273. }
  1274. else if(targetObj->isObjType(OBJTYPE_Barricade))
  1275. {
  1276. return true;
  1277. }
  1278.  
  1279. return false;
  1280. }
  1281.  
  1282. void ServerGameLogic::ApplyDamage(GameObject* fromObj, GameObject* targetObj, const r3dPoint3D& dmgPos, float damage, bool force_damage, STORE_CATEGORIES damageSource, uint32_t dmgItemID, bool canApplyBleeding)
  1283. {
  1284. r3d_assert(fromObj);
  1285. r3d_assert(targetObj);
  1286.  
  1287. //
  1288. if (ginfo_.IsGameBR() && isCountingDown)
  1289. damage = 0;
  1290. //
  1291.  
  1292. if(IsServerPlayer(fromObj))
  1293. {
  1294. obj_ServerPlayer* fromPlr = (obj_ServerPlayer*)fromObj;
  1295. if(damageSource == storecat_MELEE)
  1296. {
  1297. if(fromPlr->loadout_->Skills[CUserSkills::SKILL_Weapons1])
  1298. damage *= 1.05f;
  1299. if(fromPlr->loadout_->Skills[CUserSkills::SKILL_Weapons3])
  1300. damage *= 1.07f;
  1301. if(fromPlr->loadout_->Skills[CUserSkills::SKILL_Weapons6])
  1302. damage *= 1.10f;
  1303. }
  1304. }
  1305.  
  1306. if(IsServerPlayer(targetObj))
  1307. {
  1308. ApplyDamageToPlayer(fromObj, (obj_ServerPlayer*)targetObj, dmgPos, damage, -1, 0, force_damage, damageSource, dmgItemID, 0, canApplyBleeding);
  1309. return;
  1310. }
  1311. else if(targetObj->isObjType(OBJTYPE_Zombie))
  1312. {
  1313. ApplyDamageToZombie(fromObj, targetObj, dmgPos, damage, -1, 0, force_damage, damageSource, dmgItemID);
  1314. return;
  1315. }
  1316. else if(targetObj->Class->Name == "obj_LightMesh")
  1317. {
  1318. obj_ServerLightMesh* lightM = (obj_ServerLightMesh*)targetObj;
  1319. if(lightM->bLightOn)
  1320. {
  1321. lightM->bLightOn = false;
  1322. lightM->SyncLightStatus(-1);
  1323. }
  1324.  
  1325. return;
  1326. }
  1327. else if(targetObj->isObjType(OBJTYPE_Barricade))
  1328. {
  1329. obj_ServerBarricade* shield = (obj_ServerBarricade*)targetObj;
  1330. shield->DoDamage(damage);
  1331. return;
  1332. }
  1333. else if (targetObj->isObjType(OBJTYPE_Vehicle))
  1334. {
  1335. if (!fromObj->isObjType(OBJTYPE_Vehicle))
  1336. {
  1337. obj_Vehicle* vehicle = (obj_Vehicle*)targetObj;
  1338. vehicle->ApplyDamage(fromObj, damage, storecat_GRENADE);
  1339. }
  1340.  
  1341. return;
  1342. }
  1343.  
  1344. r3dOutToLog("!!! error !!! was trying to damage object %s [%s]\n", targetObj->Name.c_str(), targetObj->Class->Name.c_str());
  1345. }
  1346.  
  1347. // return true if hit was registered, false otherwise
  1348. // state is grabbed from the dynamics. [0] is from player in the air, [1] is target player in the air
  1349. bool ServerGameLogic::ApplyDamageToPlayer(GameObject* fromObj, obj_ServerPlayer* targetPlr, const r3dPoint3D& dmgPos, float damage, int bodyBone, int bodyPart, bool force_damage, STORE_CATEGORIES damageSource, uint32_t dmgItemID, int airState, bool canApplyBleeding)
  1350. {
  1351. r3d_assert(fromObj);
  1352. r3d_assert(targetPlr);
  1353.  
  1354. if(targetPlr->loadout_->Alive == 0)
  1355. return false;
  1356.  
  1357. if (ginfo_.IsGameBR() && isCountingDown) //
  1358. return false;
  1359.  
  1360. //AlexRedd:: FriendlyFire system
  1361. // disable dmg for same clan members
  1362. if (targetPlr->loadout_->FriendlyFire == 0 && targetPlr->loadout_->ClanID != 0 && IsServerPlayer(fromObj) && IsServerPlayer(fromObj)->loadout_->ClanID == targetPlr->loadout_->ClanID && damageSource != storecat_GRENADE && fromObj != targetPlr)
  1363. return false;
  1364.  
  1365. // can't damage players in safe zones (postbox now act like that)
  1366. if((targetPlr->loadout_->GameFlags & wiCharDataFull::GAMEFLAG_NearPostBox) && !force_damage)
  1367. return false;
  1368. // double check that we can't kill player that operating with global inventory
  1369. if(targetPlr->inventoryOpActive_)
  1370. return false;
  1371. // player's in the same group cannot damage each other (except for grenades)
  1372. if(targetPlr->groupID!= 0 && IsServerPlayer(fromObj) && IsServerPlayer(fromObj)->groupID==targetPlr->groupID && damageSource!=storecat_GRENADE
  1373. && fromObj!=targetPlr // if you are in group and damage is coming from player itself (for example falling damage) then ignore group
  1374. )
  1375. return false;
  1376.  
  1377. damage = targetPlr->ApplyDamage(damage, fromObj, bodyPart, damageSource, dmgItemID, canApplyBleeding);
  1378.  
  1379. if(fromObj->Class->Name == "obj_Zombie")
  1380. {
  1381. PKT_S2C_ZombieAttack_s n;
  1382. n.targetId = toP2pNetId(targetPlr->GetNetworkID());
  1383. p2pBroadcastToActive(fromObj, &n, sizeof(n));
  1384.  
  1385. #ifdef VEHICLES_ENABLED
  1386. if (!targetPlr->IsInVehicle())
  1387. {
  1388. #endif
  1389. extern float _zai_ChanceOfInfecting;
  1390. extern float _zai_InfectStrength;
  1391. if(u_GetRandom(0.0f, 100.0f) < _zai_ChanceOfInfecting) // chance of infecting
  1392. {
  1393. targetPlr->loadout_->Toxic += _zai_InfectStrength;
  1394. targetPlr->loadout_->Toxic = R3D_CLAMP(targetPlr->loadout_->Toxic, 0.0f, 100.0f);
  1395. }
  1396. #ifdef VEHICLES_ENABLED
  1397. }
  1398. #endif
  1399.  
  1400.  
  1401. }
  1402. else
  1403. {
  1404. // send damage packet, originating from the firing dude
  1405. PKT_S2C_Damage_s a;
  1406. a.dmgPos = dmgPos;
  1407. a.targetId = toP2pNetId(targetPlr->GetNetworkID());
  1408. a.damage = R3D_MIN((BYTE)damage, (BYTE)255);
  1409. a.dmgType = damageSource;
  1410. a.bodyBone = bodyBone;
  1411. p2pBroadcastToActive(fromObj, &a, sizeof(a));
  1412. }
  1413.  
  1414. // check if we killed player
  1415. if(targetPlr->loadout_->Health <= 0)
  1416. {
  1417. bool fromPlayerInAir = ((airState & 0x1) != 0);
  1418. bool targetPlayerInAir = ((airState & 0x2) != 0);
  1419.  
  1420. DoKillPlayer(fromObj, targetPlr, damageSource, false, fromPlayerInAir, targetPlayerInAir);
  1421. #ifdef MISSIONS
  1422. if( IsServerPlayer(fromObj) && ((obj_ServerPlayer*)fromObj)->m_MissionsProgress )
  1423. ((obj_ServerPlayer*)fromObj)->m_MissionsProgress->AddKill( targetPlr, dmgItemID );
  1424. #endif
  1425. }
  1426.  
  1427. return true;
  1428. }
  1429.  
  1430. bool ServerGameLogic::ApplyDamageToZombie(GameObject* fromObj, GameObject* targetZombie, const r3dPoint3D& dmgPos, float damage, int bodyBone, int bodyPart, bool force_damage, STORE_CATEGORIES damageSource, uint32_t dmgItemID)
  1431. {
  1432. r3d_assert(fromObj);
  1433. r3d_assert(targetZombie && targetZombie->isObjType(OBJTYPE_Zombie));
  1434.  
  1435. // relay to zombie logic
  1436. obj_Zombie* z = (obj_Zombie*)targetZombie;
  1437. bool killed = z->ApplyDamage(fromObj, damage, bodyPart, damageSource);
  1438.  
  1439. if(IsServerPlayer(fromObj) && killed)
  1440. {
  1441. IsServerPlayer(fromObj)->loadout_->Stats.KilledZombies++;
  1442. #ifdef MISSIONS
  1443. if( ((obj_ServerPlayer*)fromObj)->m_MissionsProgress )
  1444. IsServerPlayer(fromObj)->m_MissionsProgress->AddKill( z, dmgItemID );
  1445. #endif
  1446. }
  1447.  
  1448. return true;
  1449. }
  1450.  
  1451. #ifdef VEHICLES_ENABLED
  1452. bool ServerGameLogic::ApplyDamageToVehicle(GameObject* fromObj, GameObject* targetVehicle, const r3dPoint3D& dmgPos, float damage, bool forceDamage, STORE_CATEGORIES damageSource, uint32_t damageItemId)
  1453. {
  1454. r3d_assert(fromObj);
  1455. r3d_assert(targetVehicle && targetVehicle->isObjType(OBJTYPE_Vehicle));
  1456.  
  1457. obj_Vehicle* vehicle = (obj_Vehicle*)targetVehicle;
  1458. bool destroyed = vehicle->ApplyDamage(fromObj, damage, damageSource);
  1459. if (IsServerPlayer(fromObj) && destroyed)
  1460. {
  1461. // todo - add player kill
  1462. }
  1463.  
  1464. return true;
  1465. }
  1466. #endif
  1467.  
  1468. void ServerGameLogic::RelayPacket(DWORD peerId, const GameObject* from, const DefaultPacket* packetData, int packetSize, bool guaranteedAndOrdered)
  1469. {
  1470. if(!from)
  1471. {
  1472. r3dError("RelayPacket !from, event: %d", packetData->EventID);
  1473. }
  1474. const INetworkHelper* nh = const_cast<GameObject*>(from)->GetNetworkHelper();
  1475.  
  1476. for(int i=0; i<MAX_PEERS_COUNT; i++)
  1477. {
  1478. if(peers_[i].status_ >= PEER_PLAYING && i != peerId)
  1479. {
  1480. if(!nh->GetVisibility(i))
  1481. {
  1482. continue;
  1483. }
  1484.  
  1485. net_->SendToPeer(packetData, packetSize, i, guaranteedAndOrdered);
  1486. netSentPktSize[packetData->EventID] += packetSize;
  1487. }
  1488. }
  1489.  
  1490. return;
  1491. }
  1492.  
  1493. void ServerGameLogic::p2pBroadcastToActive(const GameObject* from, DefaultPacket* packetData, int packetSize, bool guaranteedAndOrdered)
  1494. {
  1495. if(!from)
  1496. {
  1497. r3dError("p2pBroadcastToActive !from, event: %d", packetData->EventID);
  1498. }
  1499. const INetworkHelper* nh = const_cast<GameObject*>(from)->GetNetworkHelper();
  1500.  
  1501. preparePacket(from, packetData);
  1502.  
  1503. for(int i=0; i<MAX_PEERS_COUNT; i++)
  1504. {
  1505. if(peers_[i].status_ >= PEER_PLAYING)
  1506. {
  1507. if(!nh->GetVisibility(i))
  1508. {
  1509. continue;
  1510. }
  1511. net_->SendToPeer(packetData, packetSize, i, guaranteedAndOrdered);
  1512. netSentPktSize[packetData->EventID] += packetSize;
  1513. }
  1514. }
  1515.  
  1516. return;
  1517. }
  1518.  
  1519. void ServerGameLogic::p2pBroadcastToAll(DefaultPacket* packetData, int packetSize, bool guaranteedAndOrdered)
  1520. {
  1521. preparePacket(NULL, packetData);
  1522.  
  1523. for(int i=0; i<MAX_PEERS_COUNT; i++)
  1524. {
  1525. if(peers_[i].status_ >= PEER_VALIDATED1)
  1526. {
  1527. net_->SendToPeer(packetData, packetSize, i, guaranteedAndOrdered);
  1528. netSentPktSize[packetData->EventID] += packetSize;
  1529. }
  1530. }
  1531.  
  1532. return;
  1533. }
  1534.  
  1535. void ServerGameLogic::p2pSendToPeer(DWORD peerId, const GameObject* from, DefaultPacket* packetData, int packetSize, bool guaranteedAndOrdered)
  1536. {
  1537. if(!from)
  1538. {
  1539. r3dError("p2pSendToPeer !from, event: %d", packetData->EventID);
  1540. }
  1541.  
  1542. const peerInfo_s& peer = GetPeer(peerId);
  1543. if(peer.status_ >= PEER_PLAYING)
  1544. {
  1545. const INetworkHelper* nh = const_cast<GameObject*>(from)->GetNetworkHelper();
  1546. if(!nh->GetVisibility(peerId))
  1547. {
  1548. return;
  1549. }
  1550.  
  1551. preparePacket(from, packetData);
  1552. net_->SendToPeer(packetData, packetSize, peerId, guaranteedAndOrdered);
  1553. netSentPktSize[packetData->EventID] += packetSize;
  1554. }
  1555. }
  1556.  
  1557. void ServerGameLogic::p2pSendRawToPeer(DWORD peerId, DefaultPacket* packetData, int packetSize, bool guaranteedAndOrdered)
  1558. {
  1559. const peerInfo_s& peer = GetPeer(peerId);
  1560. r3d_assert(peer.status_ != PEER_FREE);
  1561.  
  1562. preparePacket(NULL, packetData);
  1563. net_->SendToPeer(packetData, packetSize, peerId, guaranteedAndOrdered);
  1564. netSentPktSize[packetData->EventID] += packetSize;
  1565. }
  1566.  
  1567. void ServerGameLogic::InformZombiesAboutSound(const obj_ServerPlayer* plr, const ServerWeapon* wpn)
  1568. {
  1569. for(GameObject* obj = GameWorld().GetFirstObject(); obj; obj = GameWorld().GetNextObject(obj))
  1570. {
  1571. if(obj->isObjType(OBJTYPE_Zombie))
  1572. ((obj_Zombie*)obj)->SenseWeaponFire(plr, wpn);
  1573. }
  1574. }
  1575.  
  1576. void ServerGameLogic::InformZombiesAboutGrenadeSound(const obj_ServerGrenade* grenade, bool isExplosion)
  1577. {
  1578. for(std::list<obj_Zombie*>::iterator it = obj_Zombie::s_ListOfAllActiveZombies.begin(); it != obj_Zombie::s_ListOfAllActiveZombies.end(); ++it)
  1579. {
  1580. (*it)->SenseGrenadeSound(grenade, isExplosion);
  1581. }
  1582. }
  1583.  
  1584. #ifdef VEHICLES_ENABLED
  1585. void ServerGameLogic::InformZombiesAboutVehicleExplosion(const obj_Vehicle* vehicle)
  1586. {
  1587. for(std::list<obj_Zombie*>::iterator it = obj_Zombie::s_ListOfAllActiveZombies.begin(); it != obj_Zombie::s_ListOfAllActiveZombies.end(); ++it)
  1588. {
  1589. (*it)->SenseVehicleExplosion(vehicle);
  1590. }
  1591. }
  1592. #endif
  1593.  
  1594. wiStatsTracking ServerGameLogic::GetRewardData(obj_ServerPlayer* plr, EPlayerRewardID rewardID)
  1595. {
  1596. r3d_assert(g_GameRewards);
  1597. const CGameRewards::rwd_s& rwd = g_GameRewards->GetRewardData(rewardID);
  1598. if(!rwd.IsSet)
  1599. {
  1600. LogInfo(plr->peerId_, "GetReward", "%d not set", rewardID);
  1601. return wiStatsTracking();
  1602. }
  1603.  
  1604. wiStatsTracking stat;
  1605. stat.RewardID = (int)rewardID;
  1606. stat.GP = 0;
  1607.  
  1608. if(plr->loadout_->Hardcore)
  1609. {
  1610. stat.GD = rwd.GD_HARD;
  1611. stat.XP = rwd.XP_HARD;
  1612. }
  1613. else
  1614. {
  1615. if(rwd.GD_SOFT>0)
  1616. stat.GD = rwd.GD_SOFT;// + u_random(10);//AlexRedd:: random GD
  1617. else
  1618. stat.GD = rwd.GD_SOFT;
  1619. if(rwd.XP_SOFT>0)
  1620. stat.XP = rwd.XP_SOFT;// + u_random(10);//AlexRedd:: random XP
  1621. else
  1622. stat.XP = rwd.XP_SOFT;
  1623. }
  1624.  
  1625. return stat;
  1626. }
  1627.  
  1628. void ServerGameLogic::AddPlayerReward(obj_ServerPlayer* plr, EPlayerRewardID rewardID)
  1629. {
  1630. wiStatsTracking stat = GetRewardData(plr, rewardID);
  1631. if(stat.RewardID == 0)
  1632. return;
  1633.  
  1634. const CGameRewards::rwd_s& rwd = g_GameRewards->GetRewardData(rewardID);
  1635. AddDirectPlayerReward(plr, stat, rwd.Name.c_str());
  1636. }
  1637.  
  1638. void ServerGameLogic::AddDirectPlayerReward(obj_ServerPlayer* plr, const wiStatsTracking& in_rwd, const char* rewardName)
  1639. {
  1640. // add reward to player
  1641. wiStatsTracking rwd2 = plr->AddReward(in_rwd);
  1642. int xp = rwd2.XP;
  1643. int gp = rwd2.GP;
  1644. int gd = rwd2.GD;
  1645. if(xp == 0 && gp == 0 && gd == 0)
  1646. return;
  1647.  
  1648. r3dOutToLog("reward: %s got %dxp %dgp %dgd RWD_%s\n", plr->userName, xp, gp, gd, rewardName ? rewardName : "");
  1649.  
  1650. // send it to him
  1651. PKT_S2C_AddScore_s n;
  1652. n.ID = (WORD)in_rwd.RewardID;
  1653. n.XP = R3D_CLAMP(xp, -30000, 30000);
  1654. n.GD = (WORD)gd;
  1655. n.Rep = 0;
  1656. p2pSendToPeer(plr->peerId_, plr, &n, sizeof(n));
  1657.  
  1658. return;
  1659. }
  1660.  
  1661. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_ValidateConnectingPeer)
  1662. {
  1663. // reply back with our version
  1664. PKT_C2S_ValidateConnectingPeer_s n1;
  1665. n1.protocolVersion = P2PNET_VERSION;
  1666. n1.sessionId = 0;
  1667. p2pSendRawToPeer(peerId, &n1, sizeof(n1));
  1668.  
  1669. if(n.protocolVersion != P2PNET_VERSION)
  1670. {
  1671. DisconnectPeer(peerId, false, "Protocol Version mismatch");
  1672. return;
  1673. }
  1674. extern __int64 cfg_sessionId;
  1675. if(n.sessionId != cfg_sessionId)
  1676. {
  1677. DisconnectPeer(peerId, true, "Wrong sessionId");
  1678. return;
  1679. }
  1680.  
  1681. // switch to Validated state
  1682. peerInfo_s& peer = GetPeer(peerId);
  1683. peer.SetStatus(PEER_VALIDATED1);
  1684.  
  1685. return;
  1686. }
  1687.  
  1688. #ifdef VEHICLES_ENABLED
  1689. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_VehicleEnter)
  1690. {
  1691. obj_Vehicle* vehicle = obj_Vehicle::GetVehicleById(n.vehicleId);
  1692.  
  1693. if (!vehicle || !vehicle->isActive())
  1694. return;
  1695.  
  1696. // does the vehicle exist or have room?
  1697. PKT_S2C_VehicleEntered_s packet;
  1698.  
  1699. if (vehicle->GetDurability() <= 0 || vehicle->IsVehicleSeatsFull())
  1700. packet.isSuccess = false;
  1701. else
  1702. packet.isSuccess = true;
  1703.  
  1704. // put the requesting player in the vehicle
  1705. obj_ServerPlayer* player = IsServerPlayer(GetPeer(peerId).player);
  1706. if (!player || player->loadout_->Alive == 0)
  1707. return;
  1708.  
  1709. // make sure player is within 5 meters of vehicle
  1710. if ((player->GetPosition() - vehicle->GetPosition()).Length() > 5.0f)
  1711. packet.isSuccess = false;
  1712.  
  1713. if (packet.isSuccess)
  1714. {
  1715. player->EnterVehicle(vehicle);
  1716.  
  1717. packet.networkId = toP2pNetId(vehicle->GetNetworkID());
  1718. packet.vehicleId = vehicle->vehicleId;
  1719. packet.seat = (BYTE)player->seatPosition;
  1720. packet.curFuel = vehicle->GetFuel();
  1721.  
  1722. // let all of the clients know, this player has entered a vehicle
  1723. gServerLogic.p2pBroadcastToActive(GetPeer(peerId).player, &packet, sizeof(packet), true);
  1724. }
  1725. else // there is no available vehicle or seat
  1726. {
  1727. p2pSendToPeer(peerId, GetPeer(peerId).player, &packet, sizeof(packet));
  1728. }
  1729.  
  1730. return;
  1731. }
  1732.  
  1733. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_VehicleExit)
  1734. {
  1735. obj_Vehicle* vehicle = obj_Vehicle::GetVehicleById(n.vehicleId);
  1736. if (!vehicle)
  1737. return;
  1738.  
  1739. obj_ServerPlayer* player = IsServerPlayer(GetPeer(peerId).player);
  1740. if (!player)
  1741. return;
  1742.  
  1743. player->ExitVehicle(true);
  1744. }
  1745.  
  1746. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_VehicleHitTarget)
  1747. {
  1748. if (!fromObj || !fromObj->isObjType(OBJTYPE_Vehicle))
  1749. return;
  1750.  
  1751. obj_Vehicle* vehicle = (obj_Vehicle*)fromObj;
  1752. if (!vehicle)
  1753. return;
  1754.  
  1755. obj_ServerPlayer* player = vehicle->playersInVehicle[0];
  1756. if (!player) // we have no driver and we have no last driver.. fail
  1757. return;
  1758.  
  1759. GameObject* gameObj = GameWorld().GetNetworkObject(n.targetId);
  1760. if (!gameObj)
  1761. return;
  1762.  
  1763. float distanceCheck = (vehicle->GetSpeed() + 8.0f) * 2.0f; // temporary solution.
  1764. float distance = (vehicle->GetPosition() - gameObj->GetPosition()).Length();
  1765. if (distance > distanceCheck)
  1766. {
  1767. gServerLogic.LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_VehicleHitTarget, true, "VehicleHitTarget",
  1768. "dist: %f; distCheck: %f", distance, distanceCheck);
  1769. return;
  1770. }
  1771.  
  1772. if (gameObj->isObjType(OBJTYPE_Zombie))
  1773. {
  1774. obj_Zombie* zombie = (obj_Zombie*)gameObj;
  1775. if (zombie->ZombieHealth <= 0)
  1776. return;
  1777.  
  1778. ApplyDamageToZombie(player, gameObj, vehicle->GetPosition(), zombie->ZombieHealth + 1, 1, 1, true, storecat_Vehicle, vehicle->vehicleId);
  1779.  
  1780. vehicle->SetDurability(-10);
  1781.  
  1782. if (zombie->ZombieHealth >= 0.0f)
  1783. {
  1784. PKT_S2C_VehicleHitTargetFail_s n;
  1785. n.targetId = n.targetId;
  1786. p2pBroadcastToActive(vehicle, &n, sizeof(n));
  1787. }
  1788. }
  1789. else if (gameObj->isObjType(OBJTYPE_Human))
  1790. {
  1791. obj_ServerPlayer* hitPlayer = IsServerPlayer(gameObj);
  1792. if (hitPlayer)
  1793. {
  1794. if (hitPlayer->loadout_->GameFlags & wiCharDataFull::GAMEFLAG_NearPostBox || hitPlayer->loadout_->Health <= 0)
  1795. return;
  1796.  
  1797. ApplyDamageToPlayer(player, (obj_ServerPlayer*)gameObj, vehicle->GetPosition(), 200.0f, 1, 2, true, storecat_Vehicle, vehicle->vehicleId);
  1798.  
  1799. vehicle->SetDurability(-700, false);
  1800.  
  1801. if (hitPlayer->loadout_->Alive == 1)
  1802. {
  1803. PKT_S2C_VehicleHitTargetFail_s n;
  1804. n.targetId = n.targetId;
  1805. p2pBroadcastToActive(vehicle, &n, sizeof(n));
  1806. }
  1807. }
  1808. }
  1809. }
  1810.  
  1811. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_VehicleStopZombie)
  1812. {
  1813. GameObject* gameObj = GameWorld().GetNetworkObject(n.targetId);
  1814. if (!gameObj || !gameObj->isObjType(OBJTYPE_Zombie))
  1815. return;
  1816.  
  1817. ((obj_Zombie*)gameObj)->StopNavAgent();
  1818. }
  1819. #endif
  1820.  
  1821. obj_ServerPlayer* ServerGameLogic::CreateNewPlayer(DWORD peerId, const r3dPoint3D& spawnPos, float spawnDir, bool needsSpawnProtection, bool isFastLoad)
  1822. {
  1823. peerInfo_s& peer = GetPeer(peerId);
  1824. const int playerIdx = peer.playerIdx;
  1825.  
  1826. r3d_assert(playerIdx >= 0 && playerIdx < MAX_NUM_PLAYERS);
  1827. r3d_assert(peer.startGameAns == PKT_S2C_StartGameAns_s::RES_Ok);
  1828.  
  1829. // store game session id
  1830. peer.temp_profile.ProfileData.ArmorySlots[0].GameServerId = ginfo_.gameServerId;
  1831. peer.temp_profile.ProfileData.ArmorySlots[0].GameMapId = ginfo_.mapId;
  1832.  
  1833. // client server sync point
  1834. bool wipeInventory=false;
  1835. bool giveLoadout = false;
  1836. bool giveLoadoutSnipersMode = false;
  1837. bool giveLoadoutNoSnipersMode = false;
  1838. bool giveLoadoutBambi = false;
  1839. bool giveLoadoutBR = false;//
  1840.  
  1841. #ifdef DISABLE_GI_ACCESS_ON_PTE_MAP
  1842. if(ginfo_.channel == 6) // PTE map, wipe inventory and give one flashlight only
  1843. wipeInventory=true;
  1844. #endif
  1845. #ifdef DISABLE_GI_ACCESS_ON_PTE_STRONGHOLD_MAP
  1846. if(ginfo_.channel == 6 && ginfo_.mapId==GBGameInfo::MAPID_WZ_Cliffside) // PTE map, wipe inventory and give one flashlight only
  1847. wipeInventory=true;
  1848. #endif
  1849. #ifdef DISABLE_GI_ACCESS_FOR_CALI_SERVER
  1850. if(gServerLogic.ginfo_.mapId==GBGameInfo::MAPID_WZ_California)
  1851. wipeInventory=true;
  1852. #endif
  1853. #ifdef DISABLE_GI_ACCESS_FOR_DEV_EVENT_SERVER
  1854. if (ginfo_.channel == 6 && ginfo_.gameServerId != 22000 && ginfo_.gameServerId != 23000 && ginfo_.mapId!=GBGameInfo::MAPID_WZ_Caliwood)// 22000, 23000 = no drop (sinch point client/server)
  1855. {
  1856. wipeInventory = true;
  1857. if(gServerLogic.ginfo_.flags & GBGameInfo::SFLAGS_DisableASR)// Snipers Mode
  1858. giveLoadoutSnipersMode = true;
  1859. else if (gServerLogic.ginfo_.flags & GBGameInfo::SFLAGS_DisableSNP)// No Snipers Mode
  1860. giveLoadoutNoSnipersMode = true;
  1861. else
  1862. giveLoadout = true;
  1863. }
  1864. if(ginfo_.channel == 6 && ginfo_.mapId==GBGameInfo::MAPID_WZ_Caliwood) // bambi mode. give one flashlight only
  1865. {
  1866. wipeInventory=true;
  1867. giveLoadoutBambi = true;
  1868. }
  1869. #endif
  1870. //
  1871. if(ginfo_.IsGameBR())
  1872. {
  1873. wipeInventory=true;
  1874. giveLoadoutBR = true;
  1875. }
  1876. //
  1877.  
  1878. if(wipeInventory)
  1879. {
  1880. for(int i=0; i<wiCharDataFull::CHAR_MAX_BACKPACK_SIZE; ++i)
  1881. peer.temp_profile.ProfileData.ArmorySlots[0].Items[i].Reset();
  1882.  
  1883. if (giveLoadout) // Normal Mode
  1884. GiveDevEventLoadout(peerId);
  1885.  
  1886. if (giveLoadoutSnipersMode) // Snipers Mode
  1887. GiveDevEventLoadoutSnipersMode(peerId);
  1888.  
  1889. if (giveLoadoutNoSnipersMode) // No Snipers Mode
  1890. GiveDevEventLoadoutNoSnipersMode(peerId);
  1891.  
  1892. if (giveLoadoutBambi) // bambi mode
  1893. {
  1894. wiInventoryItem flashLightItem;
  1895. flashLightItem.InventoryID = 0;
  1896. flashLightItem.itemID = 101306;
  1897. flashLightItem.quantity = 1;
  1898. peer.temp_profile.ProfileData.ArmorySlots[0].Items[wiCharDataFull::CHAR_LOADOUT_WEAPON2] = flashLightItem;
  1899. }
  1900.  
  1901. if (giveLoadoutBR) //
  1902. GiveDevEventLoadoutBR(peerId);
  1903.  
  1904.  
  1905. /*if (!giveLoadout) // bambi mode
  1906. {
  1907. wiInventoryItem flashLightItem;
  1908. flashLightItem.InventoryID = 0;
  1909. flashLightItem.itemID = 101306;
  1910. flashLightItem.quantity = 1;
  1911. peer.temp_profile.ProfileData.ArmorySlots[0].Items[wiCharDataFull::CHAR_LOADOUT_WEAPON2] = flashLightItem;
  1912.  
  1913. }
  1914. else // dev event loadout mode
  1915. {
  1916. GiveDevEventLoadout(peerId);
  1917. }*/
  1918. }
  1919. // end
  1920.  
  1921. // create player
  1922. char name[128];
  1923. //sprintf(name, "player%02d", playerIdx);
  1924. sprintf(name, "%s", peer.temp_profile.ProfileData.ArmorySlots[0].Gamertag);
  1925. obj_ServerPlayer* plr = (obj_ServerPlayer*)srv_CreateGameObject("obj_ServerPlayer", name, spawnPos);
  1926.  
  1927. // add to peer-to-player table (need to do before player creation, because of network objects visibility check)
  1928. r3d_assert(plrToPeer_[playerIdx] != NULL);
  1929. r3d_assert(plrToPeer_[playerIdx]->player == NULL);
  1930. plrToPeer_[playerIdx]->player = plr;
  1931. // mark that we're active
  1932. peer.player = plr;
  1933.  
  1934. // fill player info
  1935. plr->m_PlayerRotation = spawnDir;
  1936. if(needsSpawnProtection)
  1937. {
  1938. if(ginfo_.mapId == GBGameInfo::MAPID_WZ_Hangar || //AlexRedd:: for map hangar we need half time spawn protection
  1939. ginfo_.IsGameBR())//
  1940. plr->m_SpawnProtectedUntil = r3dGetTime() + 15.0f; // 15 seconds of spawn protection
  1941. else
  1942. plr->m_SpawnProtectedUntil = r3dGetTime() + 30.0f; // 30 seconds of spawn protection
  1943. }
  1944.  
  1945. plr->peerId_ = peerId;
  1946. plr->SetNetworkID(playerIdx + NETID_PLAYERS_START);
  1947. plr->NetworkLocal = false;
  1948. #ifdef MISSIONS
  1949. peer.temp_profile.ProfileData.ArmorySlots[0].missionsProgress->m_player = plr;
  1950. #endif
  1951. plr->SetProfile(peer.temp_profile);
  1952. //Skin system
  1953. plr->GetDBSkins(peer.temp_profile.ProfileData);// get Skins Bought
  1954. plr->isFastLoad = isFastLoad;
  1955. plr->OnCreate();
  1956.  
  1957. // from this point we do expect security report packets
  1958. peer.secRepRecvTime = r3dGetTime();
  1959. peer.secRepGameTime = -1;
  1960. peer.secRepRecvAccum = 0;
  1961.  
  1962. m_LastConnectionRep = r3dGetTime();//AlexRedd:: for hight ping detect
  1963.  
  1964. plrList_[curPlayers_] = plr;
  1965. curPlayers_++;
  1966. maxLoggedPlayers_ = R3D_MAX(maxLoggedPlayers_, curPlayers_);
  1967.  
  1968. // report player to masterserver
  1969. gMasterServerLogic.AddPlayer(peer.playerIdx, peer.CustomerID, plr->loadout_);
  1970.  
  1971. // report joined player name to all users
  1972. //if(!(plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_HIDDEN))
  1973. //{
  1974. PKT_S2C_PlayerNameJoined_s n;
  1975. n.playerIdx = (WORD)playerIdx;
  1976. r3dscpy(n.gamertag, plr->userName);
  1977. n.reputation = plr->loadout_->Stats.Reputation;
  1978. n.ClanID = plr->loadout_->ClanID;
  1979. n.flags = 0;
  1980. if(plr->profile_.ProfileData.AccountType == 0) // legend
  1981. n.flags |= 1;
  1982. if(plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_DEV_ICON)
  1983. n.flags |= 2;
  1984. if(plr->profile_.ProfileData.AccountType == 54) // punisher
  1985. n.flags |= 4;
  1986. if(plr->profile_.ProfileData.PremiumAcc > 0)
  1987. n.flags |= 8;
  1988.  
  1989. // send to all, regardless visibility, excluding us
  1990. for(int i=0; i<MAX_PEERS_COUNT; i++) {
  1991. if(peers_[i].status_ >= PEER_PLAYING && peers_[i].player && i != peerId) {
  1992. net_->SendToPeer(&n, sizeof(n), i, true);
  1993. }
  1994. }
  1995. //}
  1996.  
  1997. // report list of current players to user, including us
  1998. {
  1999. for(int i=0; i<MAX_PEERS_COUNT; i++) {
  2000. if(peers_[i].status_ >= PEER_PLAYING && peers_[i].player) {
  2001. //if(!(peers_[i].player->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_HIDDEN))
  2002. //{
  2003. PKT_S2C_PlayerNameJoined_s n;
  2004. n.playerIdx = (WORD)peers_[i].playerIdx;
  2005. r3dscpy(n.gamertag, peers_[i].player->userName);
  2006. n.reputation = peers_[i].player->loadout_->Stats.Reputation;
  2007. n.ClanID = peers_[i].player->loadout_->ClanID;
  2008. n.flags = 0;
  2009. if(peers_[i].player->profile_.ProfileData.AccountType == 0) // legend
  2010. n.flags |= 1;
  2011. if(peers_[i].player->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_DEV_ICON)
  2012. n.flags |= 2;
  2013. if(peers_[i].player->profile_.ProfileData.AccountType == 54) // punisher
  2014. n.flags |= 4;
  2015. if(peers_[i].player->profile_.ProfileData.PremiumAcc > 0)
  2016. n.flags |= 8;
  2017.  
  2018. net_->SendToPeer(&n, sizeof(n), peerId, true);
  2019.  
  2020. // send call for help if any
  2021. if(r3dGetTime() < (peers_[i].player->lastCallForHelp+600))
  2022. {
  2023. PKT_S2C_CallForHelpEvent_s n3;
  2024. n3.playerIdx = (WORD)peers_[i].playerIdx;
  2025. r3dscpy(n3.distress, peers_[i].player->CallForHelp_distress);
  2026. r3dscpy(n3.reward, peers_[i].player->CallForHelp_reward);
  2027. n3.timeLeft = (peers_[i].player->lastCallForHelp+600) - r3dGetTime();
  2028. n3.locX = peers_[i].player->lastCallForHelpLocation.x;
  2029. n3.locZ = peers_[i].player->lastCallForHelpLocation.z;
  2030.  
  2031. net_->SendToPeer(&n3, sizeof(n3), peerId, true);
  2032. }
  2033. //}
  2034. }
  2035. }
  2036. }
  2037.  
  2038. return plr;
  2039. }
  2040.  
  2041. void ServerGameLogic::DeletePlayer(int playerIdx, obj_ServerPlayer* plr)
  2042. {
  2043. r3d_assert(plr);
  2044.  
  2045. r3d_assert(playerIdx == (plr->GetNetworkID() - NETID_PLAYERS_START));
  2046. r3dOutToLog("DeletePlayer: %s, playerIdx: %d\n", plr->userName, playerIdx);
  2047.  
  2048. #ifdef ENABLE_GAMEBLOCKS
  2049. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  2050. {
  2051. GameBlocks::Event_PlayerLeave_Send(g_GameBlocks_Client, g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(plr->profile_.CustomerID)), plr->userName);
  2052. }
  2053. #endif //ENABLE_GAMEBLOCKS
  2054. ResetNetObjVisData(plr);
  2055.  
  2056. // if player in group
  2057. if(plr->groupID!=0)
  2058. {
  2059. leavePlayerFromGroup(plr);
  2060. }
  2061.  
  2062. // remove player invites from other players
  2063. cleanPlayerGroupInvites(plr);
  2064.  
  2065. // send player destroy
  2066. {
  2067. PKT_S2C_DestroyNetObject_s n;
  2068. n.spawnID = gp2pnetid_t(plr->GetNetworkID());
  2069. p2pBroadcastToActive(plr, &n, sizeof(n));
  2070. }
  2071.  
  2072. #if defined(MISSIONS)
  2073. for(int i = 0; i < wiUserProfile::MAX_LOADOUT_SLOTS; ++i)
  2074. {
  2075. if( plr->profile_.ProfileData.ArmorySlots[ i ].missionsProgress )
  2076. delete plr->profile_.ProfileData.ArmorySlots[ i ].missionsProgress;
  2077. }
  2078. #endif
  2079.  
  2080. // mark for deletion
  2081. plr->setActiveFlag(0);
  2082. plr->wasDeleted = true;
  2083.  
  2084. // search for that player in flat array and remove it from there.
  2085. for(int i=0; i<curPlayers_; ++i)
  2086. {
  2087. if(plrList_[i] == plr)
  2088. {
  2089. memmove(plrList_ + i, plrList_ + i + 1, (curPlayers_ - i - 1) * sizeof(plrList_[0]));
  2090. break;
  2091. }
  2092. }
  2093. r3d_assert(curPlayers_ > 0);
  2094. curPlayers_--;
  2095.  
  2096. return;
  2097. }
  2098.  
  2099. // sync with CMasterUserServer::IsAdmin(DWORD CustomerID)
  2100. bool ServerGameLogic::IsAdmin(DWORD CustomerID)
  2101. {
  2102. /*
  2103. //@TH
  2104. switch(CustomerID)
  2105. {
  2106. case 1651761:
  2107. case 1651758:
  2108. case 1000015:
  2109. case 1000006:
  2110. case 1241667:
  2111. case 1000003:
  2112. case 1000012:
  2113. case 1000004:
  2114. case 1000014:
  2115. case 1000011:
  2116. case 1288630:
  2117. case 1125258:
  2118. case 1731195:
  2119. case 1320420:
  2120. case 1731117:
  2121. case 1731140:
  2122. case 1182980:
  2123. case 2280615: // askidmore@thewarz.com
  2124. case 3099993: // eric koch
  2125. return true;
  2126. }
  2127. */
  2128. return false;
  2129. }
  2130.  
  2131. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_JoinGameReq)
  2132. {
  2133. DWORD ip = net_->GetPeerIp(peerId);
  2134. r3dOutToLog("peer%02d PKT_C2S_JoinGameReq: CID:%d, ip:%s\n",
  2135. peerId, n.CustomerID, inet_ntoa(*(in_addr*)&ip));
  2136. CLOG_INDENT;
  2137.  
  2138. if(n.CustomerID == 0 || n.SessionID == 0 || n.CharID == 0)
  2139. {
  2140. gServerLogic.LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Protocol, true, "JoinGame",
  2141. "%d %d %d", n.CustomerID, n.SessionID, n.CharID);
  2142. return;
  2143. }
  2144.  
  2145. // check if that player was kicked before and ban time isn't expired
  2146. {
  2147. TKickedPlayers::iterator it = kickedPlayers_.find(n.CustomerID);
  2148. if(it != kickedPlayers_.end() && r3dGetTime() < it->second)
  2149. {
  2150. PKT_S2C_CustomKickMsg_s n2;
  2151. r3dscpy(n2.msg, "You are temporarily banned from this server");
  2152. p2pSendRawToPeer(peerId, &n2, sizeof(n2));
  2153.  
  2154. PKT_S2C_JoinGameAns_s n;
  2155. n.success = 0;
  2156. n.playerIdx = 0;
  2157. n.ownerCustomerID = 0;
  2158. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2159.  
  2160. DisconnectPeer(peerId, false, "temporary ban");
  2161. return;
  2162. }
  2163. }
  2164.  
  2165. // GetFreePlayerSlot
  2166. int playerIdx = -1;
  2167. int slotsToScan = IsAdmin(n.CustomerID) ? MAX_NUM_PLAYERS : ginfo_.maxPlayers;
  2168. for(int i=0; i<slotsToScan; i++)
  2169. {
  2170. if(plrToPeer_[i] == NULL)
  2171. {
  2172. playerIdx = i;
  2173. break;
  2174. }
  2175. }
  2176.  
  2177. if(playerIdx == -1)
  2178. {
  2179. PKT_S2C_JoinGameAns_s n;
  2180. n.success = 0;
  2181. n.playerIdx = 0;
  2182. n.ownerCustomerID = 0;
  2183. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2184.  
  2185. DisconnectPeer(peerId, false, "game is full"); //@ investigate why it's happening
  2186. return;
  2187. }
  2188.  
  2189. peerInfo_s& peer = GetPeer(peerId);
  2190. r3d_assert(peer.player == NULL);
  2191. peer.SetStatus(PEER_LOADING);
  2192. peer.playerIdx = playerIdx;
  2193. peer.CustomerID = n.CustomerID;
  2194. peer.SessionID = n.SessionID;
  2195. peer.CharID = n.CharID;
  2196. peer.nextPingOnLoad = -1;
  2197. peer.voicePeerId = (u_random(0xFFFFFFFE) & 0xFFFF0000) | playerIdx;
  2198. peer.voiceClientId = 0;
  2199.  
  2200. // add to players table
  2201. r3d_assert(plrToPeer_[playerIdx] == NULL);
  2202. plrToPeer_[playerIdx] = &peer;
  2203.  
  2204. // send join answer to peer
  2205. {
  2206. PKT_S2C_JoinGameAns_s n;
  2207. n.success = 1;
  2208. n.playerIdx = playerIdx;
  2209. n.ownerCustomerID = creatorID_;
  2210. n.gameInfo = ginfo_;
  2211. n.gameTime = GetUtcGameTime();
  2212. n.voiceId = peer.voicePeerId;
  2213. n.voicePwd = TSServer_GetPassword();
  2214.  
  2215. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2216. }
  2217.  
  2218. // send game parameters to peer
  2219. {
  2220. PKT_S2C_SetGamePlayParams_s n;
  2221. n.GPP_Data = GPP_Data;
  2222. n.GPP_Seed = GPP_Seed;
  2223. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2224. }
  2225.  
  2226. // start thread for profile loading
  2227. r3d_assert(peer.startGameAns == 0);
  2228. g_AsyncApiMgr->AddJob(new CJobProcessUserJoin(peerId));
  2229.  
  2230. return;
  2231. }
  2232.  
  2233. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_StartGameReq)
  2234. {
  2235. peerInfo_s& peer = GetPeer(peerId);
  2236. r3d_assert(peer.playerIdx != -1);
  2237. r3d_assert(peer.player == NULL);
  2238. r3d_assert(peer.status_ == PEER_LOADING);
  2239.  
  2240. r3dOutToLog("peer%02d PKT_C2S_StartGameReq, playerIdx:%d startGameAns: %d, lastNetID: %d\n", peerId, peer.playerIdx, peer.startGameAns, n.lastNetID); CLOG_INDENT;
  2241.  
  2242. /*if(n.lastNetID != net_mapLoaded_LastNetID)
  2243. {
  2244. PKT_S2C_StartGameAns_s n2;
  2245. n2.result = PKT_S2C_StartGameAns_s::RES_UNSYNC;
  2246. p2pSendRawToPeer(peerId, &n2, sizeof(n2));
  2247. DisconnectPeer(peerId, true, "netID doesn't match %d vs %d", n.lastNetID, net_mapLoaded_LastNetID);
  2248. return;
  2249. }*/
  2250.  
  2251. // check for default values, just in case
  2252. r3d_assert(0 == PKT_S2C_StartGameAns_s::RES_Unactive);
  2253. r3d_assert(1 == PKT_S2C_StartGameAns_s::RES_Ok);
  2254. switch(peer.startGameAns)
  2255. {
  2256. // we have profile, process
  2257. case PKT_S2C_StartGameAns_s::RES_Ok:
  2258. break;
  2259.  
  2260. // no profile loaded yet
  2261. case PKT_S2C_StartGameAns_s::RES_Unactive:
  2262. {
  2263. // we give 60sec to finish getting profile per user
  2264. if(r3dGetTime() > (peer.startTime + 60.0f))
  2265. {
  2266. PKT_S2C_StartGameAns_s n;
  2267. n.result = PKT_S2C_StartGameAns_s::RES_Failed;
  2268. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2269. DisconnectPeer(peerId, true, "timeout getting profile data");
  2270. }
  2271. else
  2272. {
  2273. // still pending
  2274. PKT_S2C_StartGameAns_s n;
  2275. n.result = PKT_S2C_StartGameAns_s::RES_Pending;
  2276. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2277. }
  2278. return;
  2279. }
  2280.  
  2281. default:
  2282. {
  2283. PKT_S2C_StartGameAns_s n;
  2284. n.result = (BYTE)peer.startGameAns;
  2285. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2286. DisconnectPeer(peerId, true, "StarGameReq: %d", peer.startGameAns);
  2287. return;
  2288. }
  2289. }
  2290.  
  2291. // we have player profile, put it in game
  2292. r3d_assert(peer.startGameAns == PKT_S2C_StartGameAns_s::RES_Ok);
  2293.  
  2294. // we must have only one profile with correct charid
  2295. if(peer.temp_profile.ProfileData.NumSlots != 1 ||
  2296. peer.temp_profile.ProfileData.ArmorySlots[0].LoadoutID != peer.CharID)
  2297. {
  2298. PKT_S2C_StartGameAns_s n;
  2299. n.result = PKT_S2C_StartGameAns_s::RES_Failed;
  2300. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2301.  
  2302. DisconnectPeer(peerId, true, "CharID mismatch %d vs %d", peer.CharID, peer.temp_profile.ProfileData.ArmorySlots[0].LoadoutID);
  2303. return;
  2304. }
  2305.  
  2306. // and it should be alive.
  2307. wiCharDataFull& loadout = peer.temp_profile.ProfileData.ArmorySlots[0];
  2308. if(loadout.Alive == 0)
  2309. {
  2310. PKT_S2C_StartGameAns_s n;
  2311. n.result = PKT_S2C_StartGameAns_s::RES_Failed;
  2312. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2313.  
  2314. DisconnectPeer(peerId, true, "CharID %d is DEAD", peer.CharID);
  2315. return;
  2316. }
  2317.  
  2318. if(peer.temp_profile.ProfileData.isDevAccount==0) // no check for Devs
  2319. {
  2320. if(ginfo_.gameTimeLimit > int(peer.temp_profile.ProfileData.TimePlayed/60/60))
  2321. {
  2322. PKT_S2C_StartGameAns_s n;
  2323. n.result = PKT_S2C_StartGameAns_s::RES_Failed;
  2324. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2325.  
  2326. DisconnectPeer(peerId, true, "Gametime limit on server");
  2327. return;
  2328. }
  2329. }
  2330.  
  2331. // trial accs allowed to connect only to trial servers
  2332. /*if(ginfo_.channel!=1 && peer.temp_profile.IsTrialAccount())
  2333. {
  2334. PKT_S2C_StartGameAns_s n;
  2335. n.result = PKT_S2C_StartGameAns_s::RES_Failed;
  2336. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2337.  
  2338. DisconnectPeer(peerId, true, "Trial accs not allowed");
  2339. return;
  2340. }
  2341.  
  2342. if(ginfo_.channel==1 && !peer.temp_profile.IsTrialAccount())
  2343. {
  2344. if(peer.temp_profile.ProfileData.isDevAccount>0)
  2345. {
  2346. // allow devs to connect to trial servers
  2347. }
  2348. else
  2349. {
  2350. PKT_S2C_StartGameAns_s n;
  2351. n.result = PKT_S2C_StartGameAns_s::RES_Failed;
  2352. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2353.  
  2354. DisconnectPeer(peerId, true, "Trial acc is required to join trial server");
  2355. return;
  2356. }
  2357. }*/
  2358.  
  2359. if(ginfo_.channel==4 && peer.temp_profile.ProfileData.PremiumAcc == 0)
  2360. {
  2361. PKT_S2C_StartGameAns_s n;
  2362. n.result = PKT_S2C_StartGameAns_s::RES_Failed;
  2363. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2364.  
  2365. DisconnectPeer(peerId, true, "Premium required");
  2366. return;
  2367. }
  2368. if(peer.temp_profile.ProfileData.isDevAccount==0) // only for Devs
  2369. {
  2370. if(ginfo_.mapId == GBGameInfo::MAPID_ServerTest)
  2371. {
  2372. PKT_S2C_StartGameAns_s n;
  2373. n.result = PKT_S2C_StartGameAns_s::RES_Failed;
  2374. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2375.  
  2376. DisconnectPeer(peerId, true, "This map only for DEV accounts");
  2377. return;
  2378. }
  2379. }
  2380.  
  2381. //
  2382. if (ginfo_.IsGameBR() && m_isGameHasStarted)
  2383. {
  2384. PKT_S2C_StartGameAns_s n;
  2385. n.result = PKT_S2C_StartGameAns_s::RES_Failed;
  2386. p2pSendRawToPeer(peerId, &n, sizeof(n));
  2387. r3dOutToLog("peer connected while game has started!\n");
  2388. DisconnectPeer(peerId, true, "game has started!");
  2389. return;
  2390. }
  2391.  
  2392. peer.SetStatus(PEER_PLAYING);
  2393.  
  2394. // if by some fucking unknown method you appeared at 0,0,0 - pretend he was dead, so it'll spawn at point
  2395. if(loadout.Alive == 1 && loadout.GameMapId != GBGameInfo::MAPID_ServerTest && loadout.GamePos.Length() < 10 && !ginfo_.IsGameBR())//
  2396. {
  2397. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Data, false, "ZeroSpawn", "%f %f %f", loadout.GamePos.x, loadout.GamePos.y, loadout.GamePos.z);
  2398. loadout.Alive = 2;
  2399. }
  2400.  
  2401. // get spawn position
  2402. r3dPoint3D spawnPos;
  2403. float spawnDir;
  2404. bool needsSpawnProtection = false;
  2405. //r3dOutToLog("!!! Loading Pos: %.3f %.3f %.3f\n", loadout.GamePos.x, loadout.GamePos.y, loadout.GamePos.z);
  2406. GetStartSpawnPosition(loadout, &spawnPos, &spawnDir, needsSpawnProtection);
  2407. if(peer.isServerHop) // if player server hopped, then he will need spawnProtection no matter what, as he will spawn in random location
  2408. needsSpawnProtection = true;
  2409.  
  2410. // adjust for positions that is under ground because of geometry change
  2411. if(Terrain)
  2412. {
  2413. float y1 = Terrain->GetHeight(spawnPos);
  2414. if(spawnPos.y <= y1)
  2415. spawnPos.y = y1 + 0.1f;
  2416. }
  2417. //r3dOutToLog("!!! Final Pos: %.3f %.3f %.3f\n", spawnPos.x, spawnPos.y, spawnPos.z);
  2418.  
  2419. // create that player
  2420. obj_ServerPlayer* plr = CreateNewPlayer(peerId, spawnPos, spawnDir, needsSpawnProtection, n.FastLoad);
  2421.  
  2422. // send current weapon info to player
  2423. SendWeaponsInfoToPlayer(peerId);
  2424.  
  2425. // send answer to start game
  2426. {
  2427. PKT_S2C_StartGameAns_s n;
  2428. n.result = PKT_S2C_StartGameAns_s::RES_Ok;
  2429. p2pSendRawToPeer(peerId, &n, sizeof(n)); //net_->SendToPeer(&n, sizeof(n), peerId, true);
  2430. }
  2431.  
  2432. #ifdef ENABLE_GAMEBLOCKS
  2433. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  2434. {
  2435. DWORD IP = net_->GetPeerIp(peerId);
  2436. GameBlocks::Event_PlayerJoin_Send(g_GameBlocks_Client, g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(peer.CustomerID)), loadout.Gamertag, inet_ntoa(*(in_addr*)&IP));
  2437.  
  2438. g_GameBlocks_Client->PrepareEventForSending("Player Information", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(peer.CustomerID)));
  2439. g_GameBlocks_Client->AddKeyValueInt("charID", peer.CharID);
  2440. g_GameBlocks_Client->AddKeyValueString("Name", loadout.Gamertag);
  2441. g_GameBlocks_Client->AddKeyValueString("IP", inet_ntoa(*(in_addr*)&IP));
  2442. g_GameBlocks_Client->AddKeyValueInt("KillCiv", loadout.Stats.KilledSurvivors);
  2443. g_GameBlocks_Client->AddKeyValueInt("KillBand", loadout.Stats.KilledBandits);
  2444. g_GameBlocks_Client->AddKeyValueInt("KillZomb", loadout.Stats.KilledZombies);
  2445. g_GameBlocks_Client->AddKeyValueInt("TimeAlive", loadout.Stats.TimePlayed);
  2446. g_GameBlocks_Client->AddKeyValueInt("Reputation", loadout.Stats.Reputation);
  2447. g_GameBlocks_Client->AddKeyValueInt("XP", loadout.Stats.XP);
  2448. g_GameBlocks_Client->AddKeyValueVector3D("Position", spawnPos.x, spawnPos.y, spawnPos.z);
  2449. g_GameBlocks_Client->AddKeyValueInt("TrialAccount", peer.temp_profile.IsTrialAccount()?1:0);
  2450. g_GameBlocks_Client->AddKeyValueInt("IsDeveloper", peer.temp_profile.ProfileData.isDevAccount);
  2451. char buffer[20] = {0};
  2452. sprintf(buffer, "%I64d", n.uniqueID);
  2453. g_GameBlocks_Client->AddKeyValueString("NIC_ID", buffer);
  2454. g_GameBlocks_Client->AddKeyValueInt("AccountType", peer.temp_profile.ProfileData.AccountType);
  2455. g_GameBlocks_Client->SendEvent();
  2456. }
  2457. #endif //ENABLE_GAMEBLOCKS
  2458.  
  2459. // send message to client that he was server hopped
  2460. if(peer.isServerHop)
  2461. {
  2462. PKT_C2C_ChatMessage_s n2;
  2463. n2.FromID = toP2pNetId(plr->GetNetworkID());
  2464. n2.msgChannel = 1; // global
  2465. n2.userFlag = 2; // mark as dev, so color is red
  2466. r3dscpy(n2.gamertag, "<SYSTEM>");
  2467. r3dscpy(n2.msg, "You were teleported to a safe location because of quick change of game servers");
  2468. p2pSendToPeer(plr->peerId_, plr, &n2, sizeof(n2), 1);
  2469. }
  2470.  
  2471. #ifdef MISSIONS
  2472. if( Mission::g_pMissionMgr )
  2473. {
  2474. Mission::g_pMissionMgr->SendActiveMissionsToPlayer( *plr );
  2475.  
  2476. // Sync client mission progress with what's been loaded, and now copied to the player on the server.
  2477. Mission::MissionsProgress* mp = plr->profile_.ProfileData.ArmorySlots[0].missionsProgress;
  2478. if( mp )
  2479. {
  2480. //r3dOutToLog("Syncing Remote Missions Progress for player %s\n", plr->Name);
  2481. mp->SyncRemoteMissionsProgress();
  2482. }
  2483. else
  2484. {
  2485. r3dOutToLog("!!! Missions Progress not set, unable to sync Remote Missions Progress for player %s\n", plr->Name);
  2486. }
  2487. }
  2488. #endif
  2489.  
  2490. return;
  2491. }
  2492.  
  2493. bool ServerGameLogic::CheckForPlayersAround(const r3dPoint3D& pos, float dist)
  2494. {
  2495. float distSq = dist * dist;
  2496. for(int i=0; i<curPlayers_; i++)
  2497. {
  2498. const obj_ServerPlayer* plr = plrList_[i];
  2499. if((plr->GetPosition() - pos).LengthSq() < distSq)
  2500. return true;
  2501. }
  2502.  
  2503. return false;
  2504. }
  2505.  
  2506. void ServerGameLogic::GetStartSpawnPosition(const wiCharDataFull& loadout, r3dPoint3D* pos, float* dir, bool& needsSpawnProtection)
  2507. {
  2508. needsSpawnProtection = false;
  2509.  
  2510. // if no map assigned yet, or new map, or newly created character (alive == 3) or joining PTE map
  2511. if((loadout.GameMapId == 0 || loadout.GameMapId != ginfo_.mapId || loadout.Alive == 3
  2512. #ifdef DISABLE_GI_ACCESS_ON_PTE_MAP
  2513. || ginfo_.channel == 6
  2514. #endif
  2515. #ifdef DISABLE_GI_ACCESS_ON_PTE_STRONGHOLD_MAP
  2516. || (ginfo_.channel == 6 && ginfo_.mapId==GBGameInfo::MAPID_WZ_Cliffside)
  2517. #endif
  2518. #ifdef DISABLE_GI_ACCESS_FOR_CALI_SERVER
  2519. || (gServerLogic.ginfo_.mapId==GBGameInfo::MAPID_WZ_California)
  2520. #endif
  2521. #ifdef DISABLE_GI_ACCESS_FOR_DEV_EVENT_SERVER
  2522. || ginfo_.channel == 6
  2523. #endif
  2524. )&& !ginfo_.IsGameBR())//
  2525. {
  2526. needsSpawnProtection = true;
  2527. GetSpawnPositionNewPlayer(loadout.GamePos, pos, dir);
  2528. // move spawn pos at radius
  2529. pos->x += u_GetRandom(-_glm_SpawnRadius, _glm_SpawnRadius);
  2530. pos->z += u_GetRandom(-_glm_SpawnRadius, _glm_SpawnRadius);
  2531. //r3dOutToLog("new spawn at position %f %f %f\n", pos->x, pos->y, pos->z);
  2532. return;
  2533. }
  2534.  
  2535. // alive at current map
  2536. if(loadout.GameMapId && (loadout.GameMapId == ginfo_.mapId) && loadout.Alive == 1 &&
  2537. !ginfo_.IsGameBR())
  2538. {
  2539. needsSpawnProtection = true;
  2540. GetSpawnPositionAfterDeath(loadout.GamePos, pos, dir);
  2541. // move spawn pos at radius
  2542. pos->x += u_GetRandom(-_glm_SpawnRadius, _glm_SpawnRadius);
  2543. pos->z += u_GetRandom(-_glm_SpawnRadius, _glm_SpawnRadius);
  2544. //r3dOutToLog("revived at position %f %f %f\n", pos->x, pos->y, pos->z);
  2545. return;
  2546. /*needsSpawnProtection = false;
  2547. PxRaycastHit hit;
  2548. PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK,0,0,0), PxSceneQueryFilterFlags(PxSceneQueryFilterFlag::eSTATIC|PxSceneQueryFilterFlag::eDYNAMIC));
  2549. bool hitResult = g_pPhysicsWorld->raycastSingle(PxVec3(loadout.GamePos.x, loadout.GamePos.y + 0.5f, loadout.GamePos.z), PxVec3(0, -1, 0), 500.0f, PxSceneQueryFlags(PxSceneQueryFlag::eIMPACT), hit, filter);
  2550. r3dPoint3D posForWater = loadout.GamePos;
  2551. if( hitResult )
  2552. posForWater = r3dPoint3D(hit.impact.x, hit.impact.y, hit.impact.z); // This is the ground position underwater.
  2553.  
  2554. float waterDepth = getWaterDepthAtPos(posForWater);
  2555.  
  2556. //r3dOutToLog("!!! WaterCheck Hit: %d, Depth: %.3f, Impact: %.3f, %.3f, %.3f\n", (int)hitResult, waterDepth, posForWater.x, posForWater.y, posForWater.z);
  2557.  
  2558. const float allowedDepth = 1.5f;
  2559. if(waterDepth > allowedDepth) // too deep, start swimming
  2560. {
  2561. *pos = r3dPoint3D(posForWater.x, posForWater.y + (waterDepth - allowedDepth), posForWater.z); // adjust to water, in case player logged out while swimming
  2562. }
  2563. else
  2564. {
  2565. *pos = AdjustPositionToFloor(loadout.GamePos); // adjust to floor, in case if player logged out while being on top of other player or anything like that
  2566. }
  2567. *dir = loadout.GameDir;
  2568. //r3dOutToLog("alive at position %.3f %.3f %.3f\n", pos->x, pos->y, pos->z);
  2569. return;*/
  2570. }
  2571.  
  2572. // revived (alive == 2) - spawn to closest spawn point
  2573. if(loadout.GameMapId && loadout.Alive == 2 &&
  2574. !ginfo_.IsGameBR())//
  2575. {
  2576. needsSpawnProtection = true;
  2577. GetSpawnPositionAfterDeath(loadout.GamePos, pos, dir);
  2578. // move spawn pos at radius
  2579. pos->x += u_GetRandom(-_glm_SpawnRadius, _glm_SpawnRadius);
  2580. pos->z += u_GetRandom(-_glm_SpawnRadius, _glm_SpawnRadius);
  2581. //r3dOutToLog("revived at position %f %f %f\n", pos->x, pos->y, pos->z);
  2582. return;
  2583. }
  2584.  
  2585. //
  2586. if(ginfo_.IsGameBR())
  2587. {
  2588. needsSpawnProtection = true;
  2589. GetSpawnPositionBattleRoyale(loadout.GamePos, pos, dir);
  2590. pos->x += u_GetRandom(-_glm_SpawnRadius, _glm_SpawnRadius);
  2591. pos->z += u_GetRandom(-_glm_SpawnRadius, _glm_SpawnRadius);
  2592. return;
  2593. }
  2594.  
  2595. r3dOutToLog("%d %d %d\n", loadout.GameMapId, loadout.Alive, ginfo_.mapId);
  2596. r3d_assert(false && "GetStartSpawnPosition");
  2597. }
  2598.  
  2599. void ServerGameLogic::GetSpawnPositionNewPlayer(const r3dPoint3D& GamePos, r3dPoint3D* pos, float* dir)
  2600. {
  2601. if(gCPMgr.numControlPoints_ == 0)
  2602. {
  2603. r3dOutToLog("!!!!!!!!!!!! THERE IS NO CONTROL POINTS !!!!!!!\n");
  2604. *pos = r3dPoint3D(0, 0, 0);
  2605. *dir = 0;
  2606. return;
  2607. }
  2608.  
  2609. int idx1 = u_random(gCPMgr.numControlPoints_);
  2610. r3d_assert(idx1 < gCPMgr.numControlPoints_);
  2611. const BasePlayerSpawnPoint* spawn = gCPMgr.controlPoints_[idx1];
  2612. spawn->getSpawnPoint(*pos, *dir);
  2613. return;
  2614. }
  2615.  
  2616. void ServerGameLogic::GetSpawnPositionAfterDeath(const r3dPoint3D& GamePos, r3dPoint3D* pos, float* dir)
  2617. {
  2618. if(gCPMgr.numControlPoints_ == 0)
  2619. {
  2620. r3dError("!!!!!!!!!!!! THERE IS NO CONTROL POINT !!!!!!!\n");
  2621. *pos = r3dPoint3D(0, 0, 0);
  2622. *dir = 0;
  2623. return;
  2624. }
  2625.  
  2626. // set defaults in case if all spawnpoints is in 100m range (server test map)
  2627. *pos = GamePos;
  2628. *dir = 0;
  2629.  
  2630. // NOTE: this function is used from another thread from CJobProcessUserJoin::DetectServerHop. DO NOT add any statics here
  2631. // spawn to closest point (but don't spawn player at almost exactly same spawn if he died to close to spawn location)
  2632. float minDist = FLT_MAX;
  2633. for(int i=0; i<gCPMgr.numControlPoints_; i++)
  2634. {
  2635. const BasePlayerSpawnPoint* spawn = gCPMgr.controlPoints_[i];
  2636. for(int j=0; j<spawn->m_NumSpawnPoints; j++)
  2637. {
  2638. float dist = (GamePos - spawn->m_SpawnPoints[j].pos).Length();
  2639. if(dist < 100.0f) // to make sure that player will not keep spawning at the same location
  2640. continue;
  2641. if(dist < minDist)
  2642. {
  2643. *pos = spawn->m_SpawnPoints[j].pos;
  2644. *dir = spawn->m_SpawnPoints[j].dir;
  2645. minDist = dist;
  2646. }
  2647. }
  2648. }
  2649.  
  2650. return;
  2651. }
  2652.  
  2653. void ServerGameLogic::GetSpawnPositionAfterDeath2(const r3dPoint3D& GamePos, r3dPoint3D* pos, float* dir)
  2654. {
  2655. if(gCPMgr.numControlPoints_ == 0)
  2656. {
  2657. r3dError("!!!!!!!!!!!! THERE IS NO CONTROL POINT !!!!!!!\n");
  2658. *pos = r3dPoint3D(0, 0, 0);
  2659. *dir = 0;
  2660. return;
  2661. }
  2662.  
  2663. // find points in 1km radius and select one with least amount of "danger" in it
  2664. static BasePlayerSpawnPoint::node_s listOfPoints[1000];
  2665. int numPoints = 0;
  2666.  
  2667. for(int i=0; i<gCPMgr.numControlPoints_; i++)
  2668. {
  2669. const BasePlayerSpawnPoint* spawn = gCPMgr.controlPoints_[i];
  2670. for(int j=0; j<spawn->m_NumSpawnPoints; j++)
  2671. {
  2672. float dist = (GamePos - spawn->m_SpawnPoints[j].pos).Length();
  2673. if(dist < 1000.0f) // to make sure that player will not keep spawning at the same location
  2674. {
  2675. listOfPoints[numPoints++] = spawn->m_SpawnPoints[j];
  2676. if(numPoints==1000) // reached maximum
  2677. break;
  2678. }
  2679. }
  2680. }
  2681.  
  2682. if(numPoints == 0) // fallback to old method
  2683. {
  2684. return GetSpawnPositionAfterDeath(GamePos, pos, dir);
  2685. }
  2686.  
  2687. *pos = listOfPoints[0].pos;
  2688. *dir = listOfPoints[0].dir;
  2689.  
  2690. // and now find closest point to our location
  2691. int curDanger = 99999999;
  2692. float minDist = FLT_MAX;
  2693. for(int i=0; i<numPoints; ++i)
  2694. {
  2695. if(listOfPoints[i].danger > curDanger)
  2696. continue;
  2697.  
  2698. float dist = (GamePos - listOfPoints[i].pos).Length();
  2699. if(dist < 100.0f) // to make sure that player will not keep spawning at the same location
  2700. continue;
  2701. if(dist < minDist && listOfPoints[i].danger <= curDanger) // select smaller distance and lowest danger
  2702. {
  2703. *pos = listOfPoints[i].pos;
  2704. *dir = listOfPoints[i].dir;
  2705. minDist = dist;
  2706. curDanger = listOfPoints[i].danger;
  2707. }
  2708. }
  2709.  
  2710. return;
  2711. }
  2712.  
  2713. r3dPoint3D ServerGameLogic::AdjustPositionToFloor(const r3dPoint3D& pos)
  2714. {
  2715. // do this in a couple of steps. firstly try +0.25, +1, then +5, then +50, then absolute +1000
  2716. PxSweepHit hit;
  2717. PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK, 0, 0, 0), PxSceneQueryFilterFlag::eSTATIC);
  2718. PxSphereGeometry sphere(0.25f);
  2719.  
  2720. if (!g_pPhysicsWorld->PhysXScene->sweepSingle(sphere, PxTransform(PxVec3(pos.x, pos.y+0.5f, pos.z), PxQuat(0,0,0,1)), PxVec3(0, -1, 0), 2000.0f, PxSceneQueryFlag::eIMPACT, hit, filter))
  2721. if (!g_pPhysicsWorld->PhysXScene->sweepSingle(sphere, PxTransform(PxVec3(pos.x, pos.y+1.0f, pos.z), PxQuat(0,0,0,1)), PxVec3(0, -1, 0), 2000.0f, PxSceneQueryFlag::eIMPACT, hit, filter))
  2722. if (!g_pPhysicsWorld->PhysXScene->sweepSingle(sphere, PxTransform(PxVec3(pos.x, pos.y+5.0f, pos.z), PxQuat(0,0,0,1)), PxVec3(0, -1, 0), 2000.0f, PxSceneQueryFlag::eIMPACT, hit, filter))
  2723. if (!g_pPhysicsWorld->PhysXScene->sweepSingle(sphere, PxTransform(PxVec3(pos.x, pos.y+50.0f, pos.z), PxQuat(0,0,0,1)), PxVec3(0, -1, 0), 2000.0f, PxSceneQueryFlag::eIMPACT, hit, filter))
  2724. if (!g_pPhysicsWorld->PhysXScene->sweepSingle(sphere, PxTransform(PxVec3(pos.x, 1000.0f, pos.z), PxQuat(0,0,0,1)), PxVec3(0, -1, 0), 2000.0f, PxSceneQueryFlag::eIMPACT, hit, filter))
  2725. {
  2726. r3dOutToLog("!! there is no floor under %f %f %f\n", pos.x, pos.y, pos.z);
  2727. return pos;
  2728. }
  2729.  
  2730. return r3dPoint3D(hit.impact.x, hit.impact.y + 0.01f, hit.impact.z);
  2731. }
  2732.  
  2733. //
  2734. // every server network object must call this function in their OnCreate() - TODO: think about better way to automatize that
  2735. //
  2736. void ServerGameLogic::NetRegisterObjectToPeers(GameObject* netObj)
  2737. {
  2738. r3d_assert(netObj->GetNetworkID());
  2739.  
  2740. // scan for all peers and see if they within distance of this object
  2741. INetworkHelper* nh = netObj->GetNetworkHelper();
  2742. for(int peerId=0; peerId<MAX_PEERS_COUNT; peerId++)
  2743. {
  2744. const peerInfo_s& peer = peers_[peerId];
  2745. if(peer.player == NULL)
  2746. continue;
  2747.  
  2748. float dist = (peer.player->GetPosition() - netObj->GetPosition()).LengthSq();
  2749. if(dist < nh->distToCreateSq)
  2750. {
  2751. #ifdef _DEBUG
  2752. r3dOutToLog("NETHELPER: %s: on create - entered visibility of network object %d %s\n", peer.player->userName, netObj->GetNetworkID(), netObj->Name.c_str());
  2753. #endif
  2754. r3d_assert(nh->PeerVisStatus[peerId] == 0);
  2755. nh->PeerVisStatus[peerId] = 1;
  2756.  
  2757. int packetSize = 0;
  2758. DefaultPacket* packetData = nh->NetGetCreatePacket(&packetSize);
  2759. if(packetData)
  2760. {
  2761. preparePacket(netObj, packetData);
  2762. net_->SendToPeer(packetData, packetSize, peerId, true);
  2763. netSentPktSize[packetData->EventID] += packetSize;
  2764. }
  2765. }
  2766. }
  2767.  
  2768. }
  2769.  
  2770. void ServerGameLogic::UpdateNetObjVisData(DWORD peerId, obj_ServerPlayer* pl, GameObject* netObj)
  2771. {
  2772. if (netObj->Class->Name != "obj_Building")
  2773. {
  2774. if (!netObj->GetNetworkID()) return;
  2775. r3d_assert(netObj->GetNetworkID());
  2776. }
  2777. r3d_assert(!(netObj->ObjFlags & OBJFLAG_JustCreated)); // object must be fully created at this moment
  2778.  
  2779. //const peerInfo_s& peer = GetPeer(peerId);
  2780. float dist = (pl->GetPosition() - netObj->GetPosition()).LengthSq();
  2781.  
  2782. INetworkHelper* nh = netObj->GetNetworkHelper();
  2783. if(nh->PeerVisStatus[peerId] == 0)
  2784. {
  2785. if (netObj->Class->Name != "obj_Building")
  2786. {
  2787. if(dist < nh->distToCreateSq)
  2788. {
  2789. #ifdef _DEBUG
  2790. //r3dOutToLog("NETHELPER: %s: entered visibility of network object %d %s\n", pl->userName, netObj->GetNetworkID(), netObj->Name.c_str());
  2791. #endif
  2792. if (netObj->Class->Name != "obj_Building")
  2793. {
  2794. nh->PeerVisStatus[peerId] = 1;
  2795.  
  2796. int packetSize = 0;
  2797. DefaultPacket* packetData = nh->NetGetCreatePacket(&packetSize);
  2798. if(packetData)
  2799. {
  2800. if (netObj->Class->Name == "obj_Building")
  2801. {
  2802. PKT_S2C_CreateBuilding_s n;
  2803. n.angle = netObj->GetRotationVector();
  2804. n.col = false;
  2805. if(netObj->ObjFlags & OBJFLAG_PlayerCollisionOnly)
  2806. n.col = true;
  2807.  
  2808. n.pos = netObj->GetPosition();
  2809. r3dscpy(n.fname,netObj->FileName.c_str());
  2810. n.spawnID = 0;
  2811. net_->SendToPeer(&n, sizeof(n), peerId, false);
  2812. }
  2813. else
  2814. {
  2815. preparePacket(netObj, packetData);
  2816. net_->SendToPeer(packetData, packetSize, peerId, true);
  2817. netSentPktSize[packetData->EventID] += packetSize;
  2818. }
  2819. }
  2820. }
  2821. else
  2822. {
  2823. nh->PeerVisStatus[peerId] = 1;
  2824.  
  2825. int packetSize = 0;
  2826. DefaultPacket* packetData = nh->NetGetCreatePacket(&packetSize);
  2827. if(packetData)
  2828. {
  2829. preparePacket(netObj, packetData);
  2830. net_->SendToPeer(packetData, packetSize, peerId, false);
  2831. netSentPktSize[packetData->EventID] += packetSize;
  2832. }
  2833. return;
  2834. }
  2835. }
  2836. }
  2837. else
  2838. {
  2839. #ifdef _DEBUG
  2840. //r3dOutToLog("NETHELPER: %s: entered visibility of network object %d %s\n", pl->userName, netObj->GetNetworkID(), netObj->Name.c_str());
  2841. #endif
  2842. if ((r3dGetTime() - pl->startPlayTime_) > 10.0f)
  2843. {
  2844. nh->PeerVisStatus[peerId] = 1;
  2845.  
  2846. int packetSize = 0;
  2847. DefaultPacket* packetData = nh->NetGetCreatePacket(&packetSize);
  2848. if(packetData)
  2849. {
  2850. // r3dOutToLog("SEND PACKET CREATEBUILDING TO PEER%d NAME %s FNAME %s\n",peerId,peer.player->userName,netObj->FileName.c_str());
  2851. preparePacket(netObj, packetData);
  2852. net_->SendToPeer(packetData, packetSize, peerId, false);
  2853. netSentPktSize[packetData->EventID] += packetSize;
  2854. }
  2855. return;
  2856. }
  2857. else
  2858. {
  2859. nh->PeerVisStatus[peerId] = 1;
  2860.  
  2861. int packetSize = 0;
  2862. DefaultPacket* packetData = nh->NetGetCreatePacket(&packetSize);
  2863. if(packetData)
  2864. {
  2865. // r3dOutToLog("SEND PACKET CREATEBUILDING TO PEER%d NAME %s FNAME %s\n",peerId,peer.player->userName,netObj->FileName.c_str());
  2866. preparePacket(netObj, packetData);
  2867. net_->SendToPeer(packetData, packetSize, peerId, false);
  2868. netSentPktSize[packetData->EventID] += packetSize;
  2869. }
  2870. return;
  2871. }
  2872. }
  2873. }
  2874. else
  2875. {
  2876. if(netObj && netObj->isObjType(OBJTYPE_Human))
  2877. {
  2878. /* @PZDEV: Just for test */
  2879. obj_ServerPlayer* plr = (obj_ServerPlayer*)netObj;
  2880. /*if (plr) // Made by Pakorn ^^
  2881. {
  2882. PKT_S2C_DestroyNetObject_s n;
  2883. n.spawnID = toP2pNetId(netObj->GetNetworkID());
  2884.  
  2885. // send only to that peer!
  2886. preparePacket(netObj, &n);
  2887. net_->SendToPeer(&n, sizeof(n), peerId, true);
  2888. netSentPktSize[n.EventID] += sizeof(n);
  2889.  
  2890. nh->PeerVisStatus[peerId] = 0;
  2891. }*/
  2892. }
  2893. else
  2894. {
  2895. // already visible
  2896. if(dist > nh->distToDeleteSq)
  2897. {
  2898. #ifdef _DEBUG
  2899. //r3dOutToLog("NETHELPER: %s: left visibility of network object %d %s\n", pl->userName, netObj->GetNetworkID(), netObj->Name.c_str());
  2900. #endif
  2901. PKT_S2C_DestroyNetObject_s n;
  2902. n.spawnID = toP2pNetId(netObj->GetNetworkID());
  2903.  
  2904. // send only to that peer!
  2905. preparePacket(netObj, &n);
  2906. net_->SendToPeer(&n, sizeof(n), peerId, true);
  2907. netSentPktSize[n.EventID] += sizeof(n);
  2908.  
  2909. nh->PeerVisStatus[peerId] = 0;
  2910. }
  2911. }
  2912. }
  2913. }
  2914.  
  2915. void ServerGameLogic::UpdateNetObjVisData(obj_ServerPlayer* plr)
  2916. {
  2917. DWORD peerId = plr->peerId_;
  2918.  
  2919. if (!plr) return;
  2920.  
  2921. // scan for all objects and create/destroy them based on distance
  2922. for(GameObject* obj=GameWorld().GetFirstObject(); obj; obj=GameWorld().GetNextObject(obj))
  2923. {
  2924. if (!plr) return;
  2925.  
  2926. if(obj->GetNetworkID() == 0)
  2927. continue;
  2928. if(obj->ObjFlags & OBJFLAG_JustCreated)
  2929. continue;
  2930. if(!obj->isActive())
  2931. continue;
  2932.  
  2933. INetworkHelper* nh = obj->GetNetworkHelper();
  2934.  
  2935. if ((plr->GetPosition() - obj->GetPosition()).LengthSq() < nh->distToCreateSq && nh->PeerVisStatus[peerId] == 0)
  2936. UpdateNetObjVisData(peerId, plr, obj);
  2937. else if ((plr->GetPosition() - obj->GetPosition()).LengthSq() > nh->distToDeleteSq && nh->PeerVisStatus[peerId] == 1)
  2938. UpdateNetObjVisData(peerId, plr, obj);
  2939. }
  2940. if (plr->isFastLoad)
  2941. {
  2942. extern ObjectManager ServerDummyWorld;
  2943. for(GameObject* obj=ServerDummyWorld.GetFirstObject(); obj; obj=ServerDummyWorld.GetNextObject(obj))
  2944. {
  2945. if (!plr) return;
  2946.  
  2947. if(obj->ObjFlags & OBJFLAG_JustCreated)
  2948. continue;
  2949. if(!obj->isActive())
  2950. continue;
  2951.  
  2952. INetworkHelper* nh = obj->GetNetworkHelper();
  2953. if ((plr->GetPosition() - obj->GetPosition()).LengthSq() < nh->distToCreateSq && nh->PeerVisStatus[peerId] == 0/* && u_GetRandom() >= 0.8f*/)
  2954. UpdateNetObjVisData(peerId, plr, obj);
  2955. }
  2956. }
  2957. }
  2958.  
  2959. void ServerGameLogic::ResetNetObjVisData(const obj_ServerPlayer* plr)
  2960. {
  2961. DWORD peerId = plr->peerId_;
  2962.  
  2963. // scan for all objects and reset their visibility of player
  2964. for(GameObject* obj=GameWorld().GetFirstObject(); obj; obj=GameWorld().GetNextObject(obj))
  2965. {
  2966. if(obj->GetNetworkID() == 0)
  2967. continue;
  2968.  
  2969. INetworkHelper* nh = obj->GetNetworkHelper();
  2970. if (nh)
  2971. {
  2972. nh->PeerVisStatus[peerId] = 0;
  2973. }
  2974. }
  2975.  
  2976. extern ObjectManager ServerDummyWorld;
  2977. for(GameObject* obj=ServerDummyWorld.GetFirstObject(); obj; obj=ServerDummyWorld.GetNextObject(obj))
  2978. {
  2979. INetworkHelper* nh = obj->GetNetworkHelper();
  2980. if (nh)
  2981. {
  2982. nh->PeerVisStatus[peerId] = 0;
  2983. }
  2984. }
  2985. }
  2986.  
  2987. void ServerGameLogic::DoExplosion(GameObject* fromObj, GameObject* sourceObj, r3dVector& forwVector, r3dVector& lastCollisionNormal, float direction, float damageArea, float damageAmount, STORE_CATEGORIES damageCategory, uint32_t damageItemId, bool isFromVehicle) // const WeaponConfig* wpnConfig)
  2988. {
  2989. r3d_assert(sourceObj);
  2990.  
  2991. r3dVector explosionPos = sourceObj->GetPosition();
  2992. if (!isFromVehicle)
  2993. {
  2994. r3dOutToLog("Explosion for grenade %d\n", sourceObj->GetSafeID()); CLOG_INDENT;
  2995. PKT_S2C_Explosion_s n;
  2996. n.spawnID = toP2pNetId(sourceObj->GetNetworkID());
  2997. n.explosion_pos = explosionPos;
  2998. n.forwVector = forwVector;
  2999. n.lastCollisionNormal = lastCollisionNormal;
  3000. n.direction = direction;
  3001.  
  3002. gServerLogic.p2pBroadcastToActive(sourceObj, &n, sizeof(n));
  3003. }
  3004.  
  3005. // apply damage within a radius
  3006. ObjectManager& GW = GameWorld();
  3007. for(GameObject* obj = GW.GetFirstObject(); obj; obj = GW.GetNextObject(obj))
  3008. {
  3009. if(obj->GetNetworkID() == 0)
  3010. continue;
  3011. if(obj->ObjFlags & OBJFLAG_JustCreated)
  3012. continue;
  3013. if(!obj->isActive())
  3014. continue;
  3015.  
  3016. if(!CanDamageThisObject(obj))
  3017. continue;
  3018.  
  3019. float dist_to_obj = (obj->GetPosition() - explosionPos).Length();
  3020. if(dist_to_obj > damageArea) // wpnConfig->m_AmmoArea)
  3021. continue;
  3022.  
  3023. // raycast to make sure that player isn't behind a wall
  3024. r3dPoint3D orig = r3dPoint3D(obj->GetPosition().x, obj->GetPosition().y+1.6f, obj->GetPosition().z);
  3025. r3dPoint3D dir = r3dPoint3D(explosionPos.x-obj->GetPosition().x, explosionPos.y-(obj->GetPosition().y+1.6f), explosionPos.z - obj->GetPosition().z);
  3026. float rayLen = dir.Length();
  3027. if(rayLen < 0.0001f)
  3028. continue;
  3029. dir.Normalize();
  3030.  
  3031. BYTE damagePercentage = 100;
  3032. float minDotDirection = cos( R3D_DEG2RAD( direction ) );
  3033. const float FULL_AREA_EXPLOSION = 360; // from client
  3034. if(direction == FULL_AREA_EXPLOSION || dir.Dot( forwVector ) > minDotDirection)
  3035. {
  3036. PxRaycastHit hit;
  3037. PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK,0,0,0), PxSceneQueryFilterFlag::eDYNAMIC|PxSceneQueryFilterFlag::eSTATIC);
  3038. if(g_pPhysicsWorld->raycastSingle(PxVec3(orig.x, orig.y, orig.z), PxVec3(dir.x, dir.y, dir.z), rayLen, PxSceneQueryFlag::eIMPACT, hit, filter))
  3039. {
  3040. // check distance to collision
  3041. float len = r3dPoint3D(hit.impact.x-obj->GetPosition().x, hit.impact.y-(obj->GetPosition().y+2.0f), hit.impact.z-obj->GetPosition().z).Length();
  3042. if((len+0.01f) < rayLen)
  3043. {
  3044. // human is behind a wall
  3045. PhysicsCallbackObject* target;
  3046. if( hit.shape && (target = static_cast<PhysicsCallbackObject*>(hit.shape->getActor().userData)))
  3047. {
  3048. // this currently only handles one piercable object between the player and explosion. More complexity might be valid here.
  3049. GameObject* hitobj = target->isGameObject();
  3050. if ( hitobj )
  3051. {
  3052. damagePercentage = hitobj->m_BulletPierceable;
  3053. }
  3054. }
  3055. }
  3056. }
  3057. // wpnConfig->m_AmmoDamage
  3058. float damage = damageAmount * (1.0f - (dist_to_obj / damageArea)); // wpnConfig->m_AmmoArea));
  3059. damage *= damagePercentage / 100.0f; // damage through wall
  3060.  
  3061. //r3dOutToLog("Explosion from %s to %s, damage=%.2f\n", fromObj->Name.c_str(), obj->Name.c_str(), damage); CLOG_INDENT;
  3062.  
  3063. ApplyDamage(fromObj, obj, explosionPos, damage, false, damageCategory, damageItemId); // wpnConfig->category, wpnConfig->m_itemID);
  3064. }
  3065. }
  3066. }
  3067.  
  3068. int ServerGameLogic::ProcessChatCommand(obj_ServerPlayer* plr, const char* cmd)
  3069. {
  3070. r3dOutToLog("cmd: %s admin:%d\n", cmd, plr->profile_.ProfileData.isDevAccount);
  3071. if(strncmp(cmd, "/tp", 3) == 0 && (plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_TELEPORT))
  3072. return Cmd_Teleport(plr, cmd);
  3073.  
  3074. if(strncmp(cmd, "/gi", 3) == 0 && (plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_SPAWN_ITEM))
  3075. return Cmd_GiveItem(plr, cmd);
  3076.  
  3077. if(strncmp(cmd, "/ammo", 5) == 0 && (plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_SPAWN_ITEM))//AlexRedd:: Give ammo
  3078. return Cmd_Ammo(plr, cmd);
  3079.  
  3080. if(strncmp(cmd, "/sv", 3) == 0 && plr->profile_.ProfileData.isDevAccount)
  3081. return Cmd_SetVitals(plr, cmd);
  3082.  
  3083. if(strncmp(cmd, "/kick", 5) == 0 && ((plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_KICK) || plr->profile_.CustomerID == creatorID_))
  3084. return Cmd_Kick(plr, cmd);
  3085.  
  3086. if(strncmp(cmd, "/ban", 4) == 0 && plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_BAN)
  3087. return Cmd_Ban(plr, cmd);
  3088.  
  3089. if(strncmp(cmd, "/chatban", 8) == 0 && plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_BAN)//AlexRedd:: Ban chat
  3090. return Cmd_BanChat(plr, cmd);
  3091.  
  3092. if(strncmp(cmd, "/ttp", 4) == 0 && plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_TELEPORT)
  3093. return Cmd_TeleportToPlayer(plr, cmd);
  3094.  
  3095. if(strncmp(cmd, "/ttyl", 5) == 0 &&
  3096. (plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_TELEPORT))
  3097. return Cmd_TeleportPlayerToDev(plr, cmd);
  3098.  
  3099. if(strncmp(cmd, "/loc", 4) == 0 && plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_TELEPORT)
  3100. return Cmd_Loc(plr, cmd);
  3101.  
  3102. /*if (strncmp(cmd, "/airdrop", 8) == 0 && plr->profile_.ProfileData.isDevAccount)
  3103. return Cmd_AirDrop(plr, cmd);*/
  3104.  
  3105. if(strncmp(cmd, "/god", 4) == 0 && plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_GOD)
  3106. {
  3107. plr->m_isAdmin_GodMode = !plr->m_isAdmin_GodMode; // once turned on, you cannot disable it (to prevent abuse)
  3108.  
  3109. PKT_C2C_ChatMessage_s n2;
  3110. n2.userFlag = 0;
  3111. n2.msgChannel = 1;
  3112. if (plr->m_isAdmin_GodMode)
  3113. {
  3114. sprintf(n2.msg, "God Mode ON");
  3115. }
  3116. else {
  3117. sprintf(n2.msg, "God Mode OFF");
  3118. }
  3119. r3dscpy(n2.gamertag, "[System]");
  3120. p2pSendToPeer(plr->peerId_, plr, &n2, sizeof(n2));
  3121.  
  3122. return 0;
  3123. }
  3124. #ifdef MISSIONS
  3125. if(strncmp(cmd, "/resetmd", 8) == 0 && plr->profile_.ProfileData.isDevAccount)
  3126. return Cmd_ResetMissionData(plr, cmd);
  3127. #endif
  3128.  
  3129. #ifdef VEHICLES_ENABLED
  3130. if (strncmp(cmd, "/vspawn", 7) == 0 && plr->profile_.ProfileData.isDevAccount)
  3131. return Cmd_VehicleSpawn(plr, cmd);
  3132. #endif
  3133. if (strncmp(cmd, "/zspawn", 7) == 0 && plr->profile_.ProfileData.isDevAccount)
  3134. return Cmd_ZombieSpawn(plr, cmd, false);
  3135. if (strncmp(cmd, "/szspawn", 8) == 0 && plr->profile_.ProfileData.isDevAccount)
  3136. return Cmd_ZombieSpawn(plr, cmd, true);
  3137. //
  3138. if (strncmp(cmd, "/start", 8) == 0 && plr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_DEV_ICON && ginfo_.IsGameBR() && !m_isGameHasStarted)
  3139. return Cmd_StartBR(plr, cmd);
  3140.  
  3141. return 1;
  3142. }
  3143.  
  3144. int ServerGameLogic::admin_TeleportPlayer(obj_ServerPlayer* plr, float x, float z)
  3145. {
  3146. r3d_assert(plr);
  3147.  
  3148. // cast ray down and find where we should place mine. should be in front of character, facing away from him
  3149. PxRaycastHit hit;
  3150. PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK, 0, 0, 0), PxSceneQueryFilterFlag::eSTATIC);
  3151. if(!g_pPhysicsWorld->raycastSingle(PxVec3(x, 5000.0f, z), PxVec3(0, -1, 0), 10000.0f, PxSceneQueryFlag::eIMPACT, hit, filter))
  3152. {
  3153. r3dOutToLog("unable to teleport - no collision\n");
  3154. return 2;
  3155. }
  3156.  
  3157. r3dPoint3D pos = AdjustPositionToFloor(r3dPoint3D(x, 0, z));
  3158.  
  3159. PKT_S2C_MoveTeleport_s n;
  3160. n.teleport_pos = pos;
  3161. p2pBroadcastToActive(plr, &n, sizeof(n));
  3162. plr->SetLatePacketsBarrier("teleport");
  3163. plr->TeleportPlayer(pos);
  3164. //r3dOutToLog("%s teleported to %f, %f, %f\n", plr->userName, pos.x, pos.y, pos.z);
  3165.  
  3166. return 0;
  3167. }
  3168.  
  3169. int ServerGameLogic::admin_TeleportPlayer(obj_ServerPlayer* plr, float x, float y, float z)
  3170. {
  3171. r3d_assert(plr);
  3172.  
  3173. r3dPoint3D pos(x, y+0.1f, z);
  3174. PKT_S2C_MoveTeleport_s n;
  3175. n.teleport_pos = pos;
  3176. p2pBroadcastToActive(plr, &n, sizeof(n));
  3177. plr->SetLatePacketsBarrier("teleport");
  3178. plr->TeleportPlayer(pos);
  3179. r3dOutToLog("%s teleported to %f, %f, %f\n", plr->userName, pos.x, pos.y, pos.z);
  3180.  
  3181. return 0;
  3182. }
  3183.  
  3184.  
  3185. int ServerGameLogic::Cmd_Teleport(obj_ServerPlayer* plr, const char* cmd)
  3186. {
  3187. char buf[128];
  3188. float x, z;
  3189.  
  3190. if(3 != sscanf(cmd, "%s %f %f", buf, &x, &z))
  3191. return 2;
  3192.  
  3193. return admin_TeleportPlayer(plr, x, z);
  3194. }
  3195.  
  3196. int ServerGameLogic::Cmd_TeleportToPlayer(obj_ServerPlayer* plr, const char* cmd)
  3197. {
  3198. char buf[64]={0};
  3199. char plrName[64]={0};
  3200.  
  3201. const char* beginNameStr = strchr(cmd, '"');
  3202. const char* endNameStr = strrchr(cmd, '"');
  3203. if(!beginNameStr || !endNameStr || beginNameStr==endNameStr)
  3204. return 2;
  3205.  
  3206. memcpy(plrName, beginNameStr+1, int((endNameStr)-(beginNameStr))-1);
  3207.  
  3208. for(int i=0; i<curPlayers_; ++i)
  3209. {
  3210. obj_ServerPlayer* pl = plrList_[i];
  3211. if(stricmp(pl->userName, plrName)==0)
  3212. {
  3213. float distanceToPlayer = 1.0f;
  3214. #ifdef VEHICLES_ENABLED
  3215. if (pl->IsInVehicle())
  3216. distanceToPlayer = 3.0f;
  3217. #endif
  3218. return admin_TeleportPlayer(plr, pl->GetPosition().x-distanceToPlayer, pl->GetPosition().y, pl->GetPosition().z);
  3219. }
  3220. }
  3221.  
  3222. return 1;
  3223. }
  3224.  
  3225. int ServerGameLogic::Cmd_TeleportPlayerToDev(obj_ServerPlayer* plr, const char* cmd)
  3226. {
  3227. char buf[64]={0};
  3228. char plrName[64]={0};
  3229.  
  3230. const char* beginNameStr = strchr(cmd, '"');
  3231. const char* endNameStr = strrchr(cmd, '"');
  3232. if(!beginNameStr || !endNameStr || beginNameStr==endNameStr)
  3233. return 2;
  3234.  
  3235. memcpy(plrName, beginNameStr+1, int((endNameStr)-(beginNameStr))-1);
  3236.  
  3237. for(int i=0; i<curPlayers_; ++i)
  3238. {
  3239. obj_ServerPlayer* pl = plrList_[i];
  3240. if(stricmp(pl->userName, plrName)==0)
  3241. {
  3242. #ifdef VEHICLES_ENABLED
  3243. if (pl->IsInVehicle())
  3244. pl->ExitVehicle(true, false);
  3245. #endif
  3246.  
  3247. #ifdef ENABLE_GAMEBLOCKS
  3248. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  3249. {
  3250. g_GameBlocks_Client->PrepareEventForSending("DevIssuedTeleport", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(pl->profile_.CustomerID)));
  3251. g_GameBlocks_Client->SendEvent();
  3252. }
  3253. #endif
  3254. return admin_TeleportPlayer(pl, plr->GetPosition().x-1, plr->GetPosition().y, plr->GetPosition().z);
  3255. }
  3256. }
  3257.  
  3258. return 1;
  3259. }
  3260.  
  3261. int ServerGameLogic::Cmd_GiveItem(obj_ServerPlayer* plr, const char* cmd)//AlexRedd:: Give ammo
  3262. {
  3263. char buf[128];
  3264. int itemid;
  3265. int count = 1;
  3266.  
  3267. if(2 > sscanf(cmd, "%s %d %d", buf, &itemid, &count))
  3268. return 2;
  3269.  
  3270. if(g_pWeaponArmory->getConfig(itemid) == NULL) {
  3271. r3dOutToLog("Cmd_GiveItem: no item %d\n", itemid);
  3272. return 3;
  3273. }
  3274.  
  3275. bool logGiveItem=true;
  3276.  
  3277. #ifdef DISABLE_GI_ACCESS_ON_PTE_MAP
  3278. if(ginfo_.channel==6) // don't care about PTE maps, as nothing there is saved
  3279. logGiveItem=false;
  3280. #endif
  3281. #ifdef DISABLE_GI_ACCESS_ON_PTE_STRONGHOLD_MAP
  3282. if(ginfo_.channel==6 && ginfo_.mapId==GBGameInfo::MAPID_WZ_Cliffside) // don't care about PTE maps, as nothing there is saved
  3283. logGiveItem=false;
  3284. #endif
  3285. #ifdef DISABLE_GI_ACCESS_FOR_CALI_SERVER
  3286. if(gServerLogic.ginfo_.mapId==GBGameInfo::MAPID_WZ_California)
  3287. logGiveItem=false;
  3288. #endif
  3289. #ifdef DISABLE_GI_ACCESS_FOR_DEV_EVENT_SERVER
  3290. if(ginfo_.channel==6)
  3291. logGiveItem=false;
  3292. #endif
  3293.  
  3294. if(ginfo_.IsGameBR())//
  3295. logGiveItem=false;
  3296.  
  3297.  
  3298. if(logGiveItem)
  3299. LogCheat(plr->peerId_, PKT_S2C_CheatWarning_s::CHEAT_AdminGiveItem, 0, "Admin Spawn Item", "%d (%s) spawned %d with quantity %d on server %s\n", plr->profile_.CustomerID, plr->userName, itemid, count, ginfo_.name);
  3300.  
  3301. wiInventoryItem wi;
  3302. wi.itemID = itemid;
  3303. wi.quantity = count;
  3304. plr->BackpackAddItem(wi);
  3305.  
  3306. return 0;
  3307. }
  3308.  
  3309. int ServerGameLogic::Cmd_Ammo(obj_ServerPlayer* plr, const char* cmd)
  3310. {
  3311. //lets get the weapon config from the selected weapon
  3312. ServerWeapon* wpn = plr->m_WeaponArray[plr->m_SelectedWeapon];
  3313.  
  3314. //statements, you might want to add more?
  3315. if(wpn && wpn->getCategory() != storecat_MELEE)
  3316. {
  3317. //get clip config from wpn
  3318. const WeaponAttachmentConfig* clip = wpn->getClipConfig();
  3319.  
  3320. //basicly lets just take the weapon item for our clip item
  3321. wiInventoryItem wi;
  3322. wi = plr->loadout_->Items[plr->loadout_->CHAR_LOADOUT_WEAPON1];
  3323.  
  3324.  
  3325. wi.itemID = clip->m_itemID; //now overrides with clip item id
  3326. wi.quantity = 3; //set how many mags per command you want!
  3327. wi.Var1 = clip->m_Clipsize; //set max clipsize from the clip config
  3328.  
  3329. //add it to the backpack
  3330. plr->BackpackAddItem(wi);
  3331.  
  3332. }
  3333.  
  3334.  
  3335. return 0;
  3336. }
  3337.  
  3338. int ServerGameLogic::Cmd_SetVitals(obj_ServerPlayer* plr, const char* cmd)
  3339. {
  3340. char buf[128];
  3341. int v1, v2, v3, v4;
  3342.  
  3343. if(5 != sscanf(cmd, "%s %d %d %d %d", buf, &v1, &v2, &v3, &v4))
  3344. return 2;
  3345.  
  3346. plr->loadout_->Health = (float)v1;
  3347. plr->loadout_->Hunger = (float)v2;
  3348. plr->loadout_->Thirst = (float)v3;
  3349. plr->loadout_->Toxic = (float)v4;
  3350. plr->loadout_->MedBleeding = 0.0f;
  3351. plr->loadout_->MedBloodInfection = 0.0f;
  3352.  
  3353. return 0;
  3354. }
  3355.  
  3356. int ServerGameLogic::Cmd_Kick(obj_ServerPlayer* plr, const char* cmd)
  3357. {
  3358. char buf[64]={0};
  3359. char plrName[64]={0};
  3360. char reason[256]={0};
  3361.  
  3362. const char* beginNameStr = strchr(cmd, '"');
  3363. const char* endNameStr = strrchr(cmd, '"');
  3364. if(!beginNameStr || !endNameStr || beginNameStr==endNameStr)
  3365. return 2;
  3366.  
  3367. memcpy(plrName, beginNameStr+1, int((endNameStr)-(beginNameStr))-1);
  3368. memcpy(reason, endNameStr+1, strlen(endNameStr+1));
  3369.  
  3370. if(strlen(reason) < 5)
  3371. return 0;
  3372.  
  3373. for(int i=0; i<curPlayers_; ++i)
  3374. {
  3375. obj_ServerPlayer* pl = plrList_[i];
  3376. if(stricmp(pl->userName, plrName)==0)
  3377. {
  3378. // Kicking players from private servers should give that player a 30 minute ban
  3379. //if(ginfo_.IsRentedGame() && plr->profile_.CustomerID == creatorID_)
  3380. //{
  3381. float banTime = r3dGetTime() + 30*60;
  3382. TKickedPlayers::iterator it = kickedPlayers_.find(pl->profile_.CustomerID);
  3383. if(it == kickedPlayers_.end())
  3384. {
  3385. kickedPlayers_.insert(std::pair<DWORD, float>(pl->profile_.CustomerID, banTime));
  3386. }
  3387. else
  3388. {
  3389. it->second = banTime;
  3390. }
  3391. //}
  3392.  
  3393. // info player that he was kicked
  3394. PKT_S2C_CustomKickMsg_s n;
  3395. r3dscpy(n.msg, "You were kicked from server");
  3396. p2pSendToPeer(pl->peerId_, pl, &n, sizeof(n));
  3397.  
  3398. #ifdef VEHICLES_ENABLED
  3399. if (pl->IsInVehicle())
  3400. pl->ExitVehicle(true, true, true);
  3401. #endif
  3402. LogInfo(pl->peerId_, "kicked by dev", "kicked by dev '%s' (custID:%d) for reason '%s'", plr->userName, plr->profile_.CustomerID, reason);
  3403. DisconnectPeer(pl->peerId_, false, "disconnected by developer");
  3404. return 0;
  3405. }
  3406. }
  3407.  
  3408. return 1;
  3409. }
  3410.  
  3411. int ServerGameLogic::Cmd_Ban(obj_ServerPlayer* plr, const char* cmd)
  3412. {
  3413. char buf[64]={0};
  3414. char plrName[64]={0};
  3415. char reason[256]={0};
  3416.  
  3417. const char* beginNameStr = strchr(cmd, '"');
  3418. const char* endNameStr = strrchr(cmd, '"');
  3419. if(!beginNameStr || !endNameStr || beginNameStr==endNameStr)
  3420. return 2;
  3421.  
  3422. memcpy(plrName, beginNameStr+1, int((endNameStr)-(beginNameStr))-1);
  3423. memcpy(reason, endNameStr+1, strlen(endNameStr+1));
  3424.  
  3425. if(strlen(reason) < 5)
  3426. return 0;
  3427.  
  3428. for(int i=0; i<curPlayers_; ++i)
  3429. {
  3430. obj_ServerPlayer* pl = plrList_[i];
  3431. if(stricmp(pl->userName, plrName)==0)
  3432. {
  3433. CJobBanUser* job = new CJobBanUser(pl);
  3434. char tmpStr[256];
  3435. sprintf(tmpStr, "Banned from in-game by dev %s for reason: %s", plr->userName, reason);
  3436. LogInfo(pl->peerId_, "banned by dev", tmpStr);
  3437. r3dscpy(job->BanReason, tmpStr);
  3438. g_AsyncApiMgr->AddJob(job);
  3439. return 0;
  3440. }
  3441. }
  3442.  
  3443. return 1;
  3444. }
  3445.  
  3446. int ServerGameLogic::Cmd_BanChat(obj_ServerPlayer* plr, const char* cmd)//AlexRedd:: Ban chat
  3447. {
  3448. char buf[64]={0};
  3449. char plrName[64]={0};
  3450. char reason[256]={0};
  3451.  
  3452. const char* beginNameStr = strchr(cmd, '"');
  3453. const char* endNameStr = strrchr(cmd, '"');
  3454. if(!beginNameStr || !endNameStr || beginNameStr==endNameStr)
  3455. return 2;
  3456.  
  3457. memcpy(plrName, beginNameStr+1, int((endNameStr)-(beginNameStr))-1);
  3458. memcpy(reason, endNameStr+1, strlen(endNameStr+1));
  3459.  
  3460. if(strlen(reason) < 5)
  3461. return 0;
  3462.  
  3463. for(int i=0; i<curPlayers_; ++i)
  3464. {
  3465. obj_ServerPlayer* pl = plrList_[i];
  3466. if(stricmp(pl->userName, plrName)==0)
  3467. {
  3468. if(pl->profile_.ProfileData.isDevAccount == 0)//skip for dev
  3469. {
  3470. CJobBanChatUser* job = new CJobBanChatUser(pl);
  3471. char tmpStr[256];
  3472. sprintf(tmpStr, "Banned chat in-game by dev %s for reason: %s", plr->userName, reason);
  3473. LogInfo(pl->peerId_, "banned chat by dev", tmpStr);
  3474. r3dscpy(job->BanReason, tmpStr);
  3475. g_AsyncApiMgr->AddJob(job);
  3476. #ifdef VEHICLES_ENABLED
  3477. if (pl->IsInVehicle())
  3478. pl->ExitVehicle(true, true, true);
  3479. #endif
  3480. // info player that he was banned from chat
  3481. PKT_S2C_CustomKickMsg_s n;
  3482. if(strlen(reason) > 8)
  3483. sprintf(n.msg, "You are banned from chat\n%s", reason);
  3484. else
  3485. r3dscpy(n.msg, "You are banned from chat");
  3486. p2pSendToPeer(pl->peerId_, pl, &n, sizeof(n));
  3487.  
  3488. LogCheat(pl->peerId_, PKT_S2C_CheatWarning_s::CHEAT_Data, 0, "Admin banned chat in-game", "User: '%s' chat banned by DEV: '%s' (CustomerID: %d) for reason: '%s'", pl->userName, plr->userName, plr->profile_.CustomerID, reason);
  3489. return 0;
  3490. }
  3491. }
  3492. }
  3493. return 1;
  3494. }
  3495.  
  3496. int ServerGameLogic::Cmd_Loc(obj_ServerPlayer* plr, const char* cmd)
  3497. {
  3498. char buf[64]={0};
  3499. char plrName[64]={0};
  3500.  
  3501. const char* beginNameStr = strchr(cmd, '"');
  3502. const char* endNameStr = strrchr(cmd, '"');
  3503. if(!beginNameStr || !endNameStr || beginNameStr==endNameStr)
  3504. return 2;
  3505.  
  3506. memcpy(plrName, beginNameStr+1, int((endNameStr)-(beginNameStr))-1);
  3507.  
  3508. for(int i=0; i<curPlayers_; ++i)
  3509. {
  3510. obj_ServerPlayer* pl = plrList_[i];
  3511. if(stricmp(pl->userName, plrName)==0)
  3512. {
  3513. // send message to dev
  3514. PKT_C2C_ChatMessage_s locN;
  3515. locN.FromID = toP2pNetId(plr->GetNetworkID());
  3516. locN.msgChannel = 1;
  3517. locN.userFlag = 2;
  3518. r3dscpy(locN.gamertag, "<SYSTEM>");
  3519. char tmpStr[64];
  3520. sprintf(tmpStr, "Player %s location: x:%.2f, y:%.2f, z:%.2f", pl->userName, pl->GetPosition().x, pl->GetPosition().y, pl->GetPosition().z);
  3521. r3dscpy(locN.msg, tmpStr);
  3522. p2pSendToPeer(plr->peerId_, plr, &locN, sizeof(locN), 1);
  3523. return 0;
  3524. }
  3525. }
  3526.  
  3527. return 1;
  3528. }
  3529.  
  3530. int ServerGameLogic::Cmd_AirDrop(obj_ServerPlayer* plr, const char* cmd)
  3531. {
  3532. if (AirDropsPos.size() < 1)
  3533. return 5;
  3534.  
  3535. char buf[128];
  3536. char option[128];
  3537. bool ToMyPosition = false;
  3538.  
  3539. if(2 == sscanf(cmd, "%s %s %d %d %d", buf, &option))
  3540. {
  3541. if (strcmp(option,"me") == 0)
  3542. ToMyPosition = true;
  3543. else
  3544. ToMyPosition = false;
  3545. }
  3546.  
  3547. wiInventoryItem wi;
  3548. wi.itemID = 'ARDR';
  3549. wi.quantity = 1;
  3550. // create network object
  3551. r3dPoint3D AirDropSpawn(0,0,0);
  3552. uint32_t AirDropRand = 1;
  3553.  
  3554. if (ToMyPosition == false)
  3555. {
  3556. if (Terrain3)
  3557. {
  3558. AirDropSpawn.y = Terrain3->GetHeight(AirDropSpawn)+300.0f;
  3559. }
  3560.  
  3561. if (AirDropsPos.size()>1)
  3562. {
  3563. AirDropRand = rand() % AirDropsPos.size()+1;
  3564. }
  3565.  
  3566. AirDropSpawn.x = AirDropsPos[AirDropRand].m_location.x + u_GetRandom(-AirDropsPos[AirDropRand].m_radius,AirDropsPos[AirDropRand].m_radius);
  3567. AirDropSpawn.z = AirDropsPos[AirDropRand].m_location.z+ + u_GetRandom(-AirDropsPos[AirDropRand].m_radius,AirDropsPos[AirDropRand].m_radius);
  3568.  
  3569. }
  3570. else {
  3571. AirDropSpawn.x = plr->GetPosition().x;
  3572. AirDropSpawn.y = plr->GetPosition().y+300.0f;
  3573. AirDropSpawn.z = plr->GetPosition().z;
  3574. }
  3575.  
  3576. obj_DroppedItem* obj = (obj_DroppedItem*)srv_CreateGameObject("obj_DroppedItem", "obj_DroppedItem", AirDropSpawn);
  3577. obj->AirDropPos = AirDropSpawn;
  3578. obj->m_FirstTime = 1;
  3579. obj->ExpireFirstTime= r3dGetTime() + 5.0f;
  3580. obj->SetPosition(AirDropSpawn);
  3581. plr->SetupPlayerNetworkItem(obj);
  3582. // vars
  3583. obj->m_Item = wi;
  3584. obj->m_Item.quantity = 1;
  3585.  
  3586. char msg[512]="";
  3587.  
  3588. sprintf(msg,"Spawned at position %.2f %.2f",AirDropSpawn.x,AirDropSpawn.z);
  3589. PKT_C2C_ChatMessage_s n;
  3590. n.userFlag = 0;
  3591. n.msgChannel = 1;
  3592. r3dscpy(n.msg, msg);
  3593. r3dscpy(n.gamertag, "[AIRDROP]");
  3594. p2pBroadcastToAll(&n, sizeof(n), true);
  3595.  
  3596. //r3dOutToLog("#######Position X:%f Y:%f Z:%f\n",AirDropSpawn.x,AirDropSpawn.y,AirDropSpawn.z);
  3597. return 0;
  3598. }
  3599.  
  3600. #if MISSIONS
  3601. int ServerGameLogic::Cmd_ResetMissionData(obj_ServerPlayer* plr, const char* cmd)
  3602. {
  3603. char plrName[64]={0};
  3604.  
  3605. const char* beginNameStr = strchr(cmd, '"');
  3606. const char* endNameStr = strrchr(cmd, '"');
  3607. if(!beginNameStr || !endNameStr || beginNameStr==endNameStr)
  3608. return 2;
  3609.  
  3610. memcpy(plrName, beginNameStr+1, int((endNameStr)-(beginNameStr))-1);
  3611.  
  3612. for(int i=0; i<curPlayers_; ++i)
  3613. {
  3614. obj_ServerPlayer* pl = plrList_[i];
  3615. if(stricmp(pl->userName, plrName)==0)
  3616. {
  3617. Mission::g_pMissionMgr->ResetMissionData( pl );
  3618. return 0;
  3619. }
  3620. }
  3621. r3dOutToLog("!!! FAILED to Reset Mission Data for '%s'.\n", plrName);
  3622. return 1;
  3623. }
  3624. #endif
  3625.  
  3626. #ifdef VEHICLES_ENABLED
  3627. int ServerGameLogic::Cmd_VehicleSpawn(obj_ServerPlayer* plr, const char* cmd)
  3628. {
  3629. char buf[128];
  3630. int vehicleType = 0;
  3631.  
  3632. if(2 != sscanf(cmd, "%s %d", buf, &vehicleType))
  3633. return 1;
  3634.  
  3635. if (vehicleType < 0 || vehicleType > 7)
  3636. return 1;
  3637.  
  3638. r3dVector position = plr->GetPosition();
  3639. position.x += 3.0f;
  3640.  
  3641. char name[28];
  3642. sprintf(name, "Vehicle_%d_%p", obj_Vehicle::s_ListOfAllActiveVehicles.size() + 1, this);
  3643.  
  3644. obj_Vehicle* vehicle = (obj_Vehicle*)srv_CreateGameObject("obj_Vehicle", name, position);
  3645. vehicle->SetNetworkID(gServerLogic.GetFreeNetId());
  3646. vehicle->NetworkLocal = true;
  3647. vehicle->spawnObject = 0;
  3648. vehicle->spawnIndex = -1;
  3649. vehicle->SetVehicleType((obj_Vehicle::VehicleTypes)vehicleType);
  3650. vehicle->SetRotationVector(plr->GetRotationVector());
  3651. vehicle->OnCreate();
  3652.  
  3653. r3dOutToLog("[%s] Admin has spawned a vehicle.\n", plr->userName);
  3654.  
  3655. return 0;
  3656. }
  3657. #endif
  3658.  
  3659. //
  3660. int ServerGameLogic::Cmd_StartBR(obj_ServerPlayer* plr, const char* cmd)
  3661. {
  3662. if (!m_isGameHasStarted)
  3663. {
  3664. char msg[128]="";
  3665. ForceStarGame = true;
  3666. sprintf(msg,"The Match is started by DEV: %s",plr->loadout_->Gamertag);
  3667. r3dOutToLog("[BattleRoyale] -- The Match is started by DEV: %s\n", plr->loadout_->Gamertag);
  3668. PKT_C2C_ChatMessage_s n;
  3669. n.userFlag = 200; // battle royale
  3670. n.msgChannel = 1; // global
  3671. r3dscpy(n.msg, msg);
  3672. r3dscpy(n.gamertag, "<BattleRoyale>");
  3673. p2pBroadcastToAll(&n, sizeof(n), true);
  3674. StartCountdown();//Start counting down
  3675. }
  3676. return 0;
  3677. }
  3678.  
  3679. int ServerGameLogic::Cmd_ZombieSpawn(obj_ServerPlayer* plr, const char* cmd, bool isSuperZombie)
  3680. {
  3681. char buf[128];
  3682. int zombieCount = 0;
  3683.  
  3684. if(sscanf(cmd, "%s %d", buf, &zombieCount) != 2)
  3685. zombieCount = 1;
  3686.  
  3687. if (zombieCount > 50)
  3688. zombieCount = 50;
  3689. else if (zombieCount < 1)
  3690. zombieCount = 1;
  3691.  
  3692. if (isSuperZombie)
  3693. zombieCount = 1;
  3694.  
  3695. obj_ZombieSpawn* spawnObject = obj_ZombieSpawn::GetClosestToPosition(plr->GetPosition());
  3696.  
  3697. r3dVector centerPosition = plr->GetPosition();
  3698. r3dVector position = centerPosition;
  3699. position.x += 3.0f;
  3700.  
  3701. for (int i = 0; i < zombieCount; ++i)
  3702. {
  3703. if (zombieCount > 1)
  3704. {
  3705. position.x = u_GetRandom(centerPosition.x - 5.0f, centerPosition.x + 5.0f);
  3706. position.z = u_GetRandom(centerPosition.z - 5.0f, centerPosition.z + 5.0f);
  3707.  
  3708. if (Terrain3)
  3709. position.y = Terrain3->GetHeight(position);
  3710. }
  3711.  
  3712. char name[28];
  3713. sprintf(name, "Zombie_%d_%p", spawnObject->numSpawnedZombies++, this);
  3714.  
  3715. obj_Zombie* z = (obj_Zombie*)srv_CreateGameObject("obj_Zombie", name, position);
  3716. z->SetNetworkID(gServerLogic.GetFreeNetId());
  3717. z->NetworkLocal = true;
  3718. z->spawnObject = spawnObject;
  3719. z->DetectRadius = 0;
  3720. z->SetRotationVector(r3dVector(u_GetRandom(0, 360), 0, 0));
  3721. z->CanCallForHelp = false;
  3722. z->isSuperZombieForced = isSuperZombie;
  3723.  
  3724. spawnObject->zombies.push_back(z);
  3725. }
  3726.  
  3727. LogCheat(plr->peerId_, PKT_S2C_CheatWarning_s::CHEAT_AdminGiveItem, 0, "Admin Spawn Zombie", "%d (%s) spawned %d zombies\n", plr->profile_.CustomerID, plr->userName, zombieCount);
  3728.  
  3729. return 0;
  3730. }
  3731.  
  3732. void ServerGameLogic::SendSystemChatMessageToPeer(DWORD peerId, const obj_ServerPlayer* fromPlr, const char* msg)
  3733. {
  3734. r3d_assert(msg);
  3735.  
  3736. PKT_C2C_ChatMessage_s n2;
  3737. n2.userFlag = 0;
  3738. n2.msgChannel = 1;
  3739. r3dscpy(n2.msg, msg);
  3740. r3dscpy(n2.gamertag, "<system>");
  3741. p2pSendToPeer(peerId, fromPlr, &n2, sizeof(n2));
  3742. }
  3743.  
  3744. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2C_ChatMessage)
  3745. {
  3746. if(!IsNullTerminated(n.gamertag, sizeof(n.gamertag))) {
  3747. DisconnectPeer(peerId, true, "invalid PKT_C2C_ChatMessage #1");
  3748. return;
  3749. }
  3750. if(!IsNullTerminated(n.msg, sizeof(n.msg))) {
  3751. DisconnectPeer(peerId, true, "invalid PKT_C2C_ChatMessage #1");
  3752. return;
  3753. }
  3754. if(n.userFlag != 0) {
  3755. DisconnectPeer(peerId, true, "invalid PKT_C2C_ChatMessage #1 - flags");
  3756. return;
  3757. }
  3758.  
  3759. // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  3760. obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  3761. if(!fromPlr) {
  3762. return;
  3763. }
  3764.  
  3765. PKT_C2C_ChatMessage_s* n_non_const = const_cast<PKT_C2C_ChatMessage_s*>(&n);
  3766.  
  3767. // overwrite gamertag in packet, as hacker can send any crap he wants and post messages as someone else
  3768. r3dscpy(n_non_const->gamertag, fromPlr->userName);
  3769.  
  3770. // trim new lines
  3771. {
  3772. char tmpMsg[sizeof(n.msg) + 1 ] = {0};
  3773. size_t strLen = strlen(n.msg);
  3774. int c=0;
  3775. for(size_t i=0; i<strLen; ++i)
  3776. {
  3777. if(n.msg[i]=='\t')
  3778. tmpMsg[c++]=' ';
  3779. else if(n.msg[i]=='\n' || n.msg[i]=='\r')
  3780. continue;
  3781. else
  3782. tmpMsg[c++]=n.msg[i];
  3783. }
  3784. tmpMsg[c++] = 0;
  3785. r3dscpy(n_non_const->msg, tmpMsg);
  3786. }
  3787.  
  3788. // set userflag
  3789. n_non_const->userFlag = 0;
  3790. if(fromPlr->profile_.ProfileData.AccountType == 0)
  3791. {
  3792. n_non_const->userFlag |= 1;
  3793. }
  3794. if(fromPlr->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_DEV_ICON)
  3795. {
  3796. n_non_const->userFlag |= 2;
  3797. }
  3798.  
  3799. const float curTime = r3dGetTime();
  3800.  
  3801. if(n.msg[0] == '/')
  3802. {
  3803. if(int res = ProcessChatCommand(fromPlr, n.msg) == 0)
  3804. {
  3805. SendSystemChatMessageToPeer(peerId, fromPlr, "command executed");
  3806. }
  3807. else if(res == 2)
  3808. {
  3809. SendSystemChatMessageToPeer(peerId, fromPlr, "Player Reported");
  3810. }
  3811. else if(res == 4)
  3812. {
  3813. SendSystemChatMessageToPeer(peerId, fromPlr, "Player not found");
  3814. }
  3815. else if(res == 5)
  3816. {
  3817. SendSystemChatMessageToPeer(peerId, fromPlr, "AirDropSpawn not found on this server");
  3818. }
  3819. else
  3820. {
  3821. PKT_C2C_ChatMessage_s n2;
  3822. n2.userFlag = 0;
  3823. n2.msgChannel = 1;
  3824. sprintf(n2.msg, "no such command, %d", res);
  3825. r3dscpy(n2.gamertag, "<system>");
  3826. p2pSendToPeer(peerId, fromPlr, &n2, sizeof(n2));
  3827. }
  3828. return;
  3829. }
  3830.  
  3831. // check for chat spamming
  3832. const float CHAT_DELAY_BETWEEN_MSG = 1.0f; // expected delay between message
  3833. const int CHAT_NUMBER_TO_SPAM = 60; // number of messages below delay time to be considered spam
  3834. float diff = curTime - fromPlr->lastChatTime_;
  3835.  
  3836. if(diff > CHAT_DELAY_BETWEEN_MSG)
  3837. {
  3838. fromPlr->numChatMessages_ = 0;
  3839. fromPlr->lastChatTime_ = curTime;
  3840. }
  3841. else
  3842. {
  3843. fromPlr->numChatMessages_++;
  3844. if(fromPlr->numChatMessages_ >= CHAT_NUMBER_TO_SPAM)
  3845. {
  3846. DisconnectPeer(peerId, true, "invalid PKT_C2C_ChatMessage #3 - spam");
  3847. return;
  3848. }
  3849. }
  3850.  
  3851.  
  3852. #ifdef ENABLE_GAMEBLOCKS
  3853. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  3854. {
  3855. g_GameBlocks_Client->PrepareEventForSending("Chat", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(fromPlr->profile_.CustomerID)));
  3856. g_GameBlocks_Client->AddKeyValueString("PlayerName", fromPlr->loadout_->Gamertag);
  3857. g_GameBlocks_Client->AddKeyValueInt("Channel", n.msgChannel);
  3858. g_GameBlocks_Client->AddKeyValueString("Text", n.msg);
  3859. g_GameBlocks_Client->SendEvent();
  3860. }
  3861. #endif
  3862.  
  3863. // do not broadcast fairfight reporting messages
  3864. /* if(strncmp(n.msg, "FairFight ", 10) == 0)
  3865. {
  3866. #ifdef ENABLE_GAMEBLOCKS
  3867. // those strings should be big enough to hold whole n.msg!!! otherwise attacker can construct such a message that will cause buffer overrun.
  3868. char buf[256]={0};
  3869. char plrName[256]={0};
  3870.  
  3871. const char* beginNameStr = strchr(n.msg, '"');
  3872. const char* endNameStr = strrchr(n.msg, '"');
  3873. if(!beginNameStr || !endNameStr || beginNameStr==endNameStr)
  3874. return;
  3875.  
  3876. memcpy(plrName, beginNameStr+1, int((endNameStr)-(beginNameStr))-1);
  3877.  
  3878. for(int i=0; i<curPlayers_; ++i)
  3879. {
  3880. obj_ServerPlayer* pl = plrList_[i];
  3881. if(stricmp(pl->userName, plrName)==0)
  3882. {
  3883. g_GameBlocks_Client->PrepareEventForSending("ReportPlayer", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(pl->profile_.CustomerID)));
  3884. g_GameBlocks_Client->AddKeyValueInt("ReportedByID", fromPlr->profile_.CustomerID);
  3885. g_GameBlocks_Client->SendEvent();
  3886. break;
  3887. }
  3888. }
  3889. #endif
  3890. return;
  3891. }*/
  3892.  
  3893. // note
  3894. // do not use p2p function here as they're visibility based now
  3895.  
  3896. switch( n.msgChannel )
  3897. {
  3898. case 3: // group
  3899. {
  3900. if(fromPlr->groupID != 0)
  3901. {
  3902. for(int i=0; i<MAX_PEERS_COUNT; i++) {
  3903. if(peers_[i].status_ >= PEER_PLAYING && i != peerId && peers_[i].player) {
  3904. if(fromPlr->groupID == peers_[i].player->groupID)
  3905. net_->SendToPeer(&n, sizeof(n), i, true);
  3906. }
  3907. }
  3908. }
  3909. }
  3910. break;
  3911.  
  3912. case 2: // clan
  3913. {
  3914. if(fromPlr->loadout_->ClanID != 0)
  3915. {
  3916. for(int i=0; i<MAX_PEERS_COUNT; i++) {
  3917. if(peers_[i].status_ >= PEER_PLAYING && i != peerId && peers_[i].player) {
  3918. if(fromPlr->loadout_->ClanID == peers_[i].player->loadout_->ClanID)
  3919. net_->SendToPeer(&n, sizeof(n), i, true);
  3920. }
  3921. }
  3922. }
  3923. }
  3924. break;
  3925.  
  3926. case 1: // global
  3927. {
  3928. for(int i=0; i<MAX_PEERS_COUNT; i++) {
  3929. if(peers_[i].status_ >= PEER_PLAYING && i != peerId && peers_[i].player) {
  3930. net_->SendToPeer(&n, sizeof(n), i, true);
  3931. }
  3932. }
  3933. }
  3934. break;
  3935.  
  3936. case 0: // proximity
  3937. for(int i=0; i<MAX_PEERS_COUNT; i++) {
  3938. if(peers_[i].status_ >= PEER_PLAYING && i != peerId && peers_[i].player) {
  3939. if((peers_[i].player->GetPosition() - fromPlr->GetPosition()).Length() < 200.0f)
  3940. net_->SendToPeer(&n, sizeof(n), i, true);
  3941. }
  3942. }
  3943. break;
  3944. default:
  3945. {
  3946. DisconnectPeer(peerId, true, "invalid PKT_C2C_ChatMessage #4 - wrong msgChannel");
  3947. return;
  3948. }
  3949. break;
  3950.  
  3951. }
  3952. }
  3953.  
  3954. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_DataUpdateReq)
  3955. {
  3956. r3dOutToLog("got PKT_C2S_DataUpdateReq\n");
  3957.  
  3958. // relay that event to master server.
  3959. //gMasterServerLogic.RequestDataUpdate();
  3960. }
  3961.  
  3962. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_Admin_GiveItem)
  3963. {
  3964. peerInfo_s& peer = GetPeer(peerId);
  3965.  
  3966. // check if received from legitimate admin account
  3967. if(!peer.player || !(peer.temp_profile.ProfileData.isDevAccount & wiUserProfile::DAA_SPAWN_ITEM))
  3968. return;
  3969.  
  3970. if(g_pWeaponArmory->getConfig(n.Item.itemID) == NULL) {
  3971. r3dOutToLog("PKT_C2S_Admin_GiveItem: no item %d\n", n.Item.itemID);
  3972. return;
  3973. }
  3974.  
  3975. peer.player->BackpackAddItem(n.Item);
  3976. }
  3977.  
  3978. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_ClientConnection)
  3979. {
  3980. const float curTime = r3dGetTime();
  3981. peerInfo_s& peer = GetPeer(peerId);
  3982. if(peer.player == NULL)
  3983. return;
  3984.  
  3985. if(n.isHightPing == true)
  3986. {
  3987. peer.player->isHighPing = true;
  3988. }
  3989.  
  3990. m_LastConnectionRep = curTime;
  3991. return;
  3992. }
  3993.  
  3994. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_SecurityRep)
  3995. {
  3996. const float curTime = r3dGetTime();
  3997. peerInfo_s& peer = GetPeer(peerId);
  3998. if(peer.player==NULL) // cheat?? ptumik: keep in mind that after calling LogCheat below that peer.player will be null again!
  3999. return;
  4000.  
  4001. if(!r3d_float_isFinite(n.EnvironmentCurTime) || !r3d_float_isFinite(n.gameTime) )
  4002. {
  4003. #ifdef ENABLE_GAMEBLOCKS
  4004. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  4005. {
  4006. g_GameBlocks_Client->PrepareEventForSending("GodModeCheatAttempt", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(peer.player->profile_.CustomerID)));
  4007. g_GameBlocks_Client->SendEvent();
  4008. }
  4009. #endif
  4010. return;
  4011. }
  4012.  
  4013.  
  4014. if(peer.secRepGameTime < 0)
  4015. {
  4016. // first call.
  4017. peer.secRepRecvTime = curTime;
  4018. peer.secRepGameTime = n.gameTime;
  4019. //r3dOutToLog("peer%02d, CustomerID:%d SecRep started\n");
  4020. return;
  4021. }
  4022.  
  4023. float delta1 = n.gameTime - peer.secRepGameTime;
  4024. float delta2 = curTime - peer.secRepRecvTime;
  4025.  
  4026. //@ ignore small values for now, until we resolve how that can happens without cheating.
  4027. if(delta2 > ((float)PKT_C2S_SecurityRep_s::REPORT_PERIOD - 0.3f) && delta2 < PKT_C2S_SecurityRep_s::REPORT_PERIOD)
  4028. delta2 = PKT_C2S_SecurityRep_s::REPORT_PERIOD;
  4029.  
  4030. // account for late packets
  4031. peer.secRepRecvAccum -= (delta2 - PKT_C2S_SecurityRep_s::REPORT_PERIOD);
  4032.  
  4033. float k = delta1 - delta2;
  4034. bool isLag = (k > 1.0f || k < -1.0f);
  4035.  
  4036. /*
  4037. r3dOutToLog("peer%02d, CID:%d SecRep: %f %f %f %f %s\n",
  4038. peerId, peer.CustomerID, delta1, delta2, k, peer.secRepRecvAccum,
  4039. isLag ? "net_lag" : "");*/
  4040.  
  4041. // check for client timer
  4042. if(fabs(delta1 - PKT_C2S_SecurityRep_s::REPORT_PERIOD) > 1.0f)
  4043. {
  4044. LogInfo(peerId, "client_lag?", "%f, %f, %f", delta1, delta2, peer.secRepRecvAccum);
  4045. }
  4046.  
  4047. // check if client was sending packets faster that he should, 20% limit
  4048. if(peer.secRepRecvAccum > ((float)PKT_C2S_SecurityRep_s::REPORT_PERIOD * 0.2f))
  4049. {
  4050. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_SpeedHack, true, "speedhack",
  4051. "%f, %f, %f", delta1, delta2, peer.secRepRecvAccum
  4052. );
  4053.  
  4054. peer.secRepRecvAccum = 0;
  4055. }
  4056.  
  4057. if((GPP_Data.GetCrc32() ^ GPP_Seed) != n.GPP_Crc32)
  4058. {
  4059. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_GPP, true, "GPP cheat");
  4060. }
  4061.  
  4062. // check for gametime manipulation
  4063. if(peer.player && peer.player->profile_.ProfileData.isDevAccount == 0 && gServerLogic.ginfo_.channel!=7) // do not log gametime cheat on Trade server
  4064. {
  4065. __int64 gameTimeDelta = R3D_ABS(GetUtcGameTime() - n.gameUtcTime);
  4066.  
  4067. if(gameTimeDelta > 1000 && !peer.player->security_utcGameTimeSent)
  4068. {
  4069. //r3dOutToLog("!!! @@@ Utc delta = %d\n", int(gameTimeDelta));
  4070. peer.player->security_utcGameTimeSent = true;
  4071. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_GametimeCheat, false, "utc gametime", "delta=%d", int(gameTimeDelta));
  4072. }
  4073.  
  4074. // @@@ Environment Cur Time Sync Point @@@
  4075. if(peer.player)
  4076. {
  4077. float EnvCurTime = getInGameTime();
  4078.  
  4079. float envtimeDelta = R3D_ABS(EnvCurTime-n.EnvironmentCurTime);
  4080.  
  4081. if(envtimeDelta > 2.0f && envtimeDelta < 22.0f && !peer.player->security_GameTimeSent) // sometimes delta could be equal 24, which is ok. check for it by <23.
  4082. {
  4083. //r3dOutToLog("!!! @@@@ Env time diff: %.2f\n", envtimeDelta);
  4084. peer.player->security_GameTimeSent = true;
  4085. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_GametimeCheat, false, "gametime", "delta=%.2f", envtimeDelta);
  4086. #ifdef ENABLE_GAMEBLOCKS
  4087. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  4088. {
  4089. g_GameBlocks_Client->PrepareEventForSending("GametimeCheat", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(peer.CustomerID)));
  4090. g_GameBlocks_Client->SendEvent();
  4091. }
  4092. #endif
  4093. }
  4094. }
  4095. }
  4096.  
  4097. if(n.InsertKeyPressedNumber)
  4098. {
  4099. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_MaybeEnabledCheatMenu, false, "insert key", "pressed=%d", n.InsertKeyPressedNumber);
  4100. #ifdef ENABLE_GAMEBLOCKS
  4101. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  4102. {
  4103. g_GameBlocks_Client->PrepareEventForSending("InsertKeyPressed", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(peer.CustomerID)));
  4104. g_GameBlocks_Client->SendEvent();
  4105. }
  4106. #endif
  4107. }
  4108. if(n.DeleteKeyPressedNumber)
  4109. {
  4110. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_MaybeEnabledCheatMenu, false, "delete key", "pressed=%d", n.DeleteKeyPressedNumber);
  4111. #ifdef ENABLE_GAMEBLOCKS
  4112. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  4113. {
  4114. g_GameBlocks_Client->PrepareEventForSending("DeleteKeyPressed", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(peer.CustomerID)));
  4115. g_GameBlocks_Client->SendEvent();
  4116. }
  4117. #endif
  4118. }
  4119. if(n.MinusKeyPressedNumber)
  4120. {
  4121. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_MaybeEnabledCheatMenu, false, "minus key", "pressed=%d", n.MinusKeyPressedNumber);
  4122. #ifdef ENABLE_GAMEBLOCKS
  4123. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  4124. {
  4125. g_GameBlocks_Client->PrepareEventForSending("MinusKeyPressed", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(peer.CustomerID)));
  4126. g_GameBlocks_Client->SendEvent();
  4127. }
  4128. #endif
  4129. }
  4130.  
  4131. if(n.NVGHack && peer.player)
  4132. {
  4133. if(!peer.player->security_NVGSent)
  4134. {
  4135. peer.player->security_NVGSent = true;
  4136. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_NVG, false, "nvg", "");
  4137. #ifdef ENABLE_GAMEBLOCKS
  4138. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  4139. {
  4140. g_GameBlocks_Client->PrepareEventForSending("NVGCheatDetected", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(peer.CustomerID)));
  4141. g_GameBlocks_Client->SendEvent();
  4142. }
  4143. #endif
  4144. }
  4145. }
  4146.  
  4147.  
  4148. peer.secRepRecvTime = curTime;
  4149. peer.secRepGameTime = n.gameTime;
  4150. return;
  4151. }
  4152.  
  4153. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_CameraPos)
  4154. {
  4155. const float curTime = r3dGetTime();
  4156. peerInfo_s& peer = GetPeer(peerId);
  4157. if(peer.player==NULL) // cheat?? ptumik: keep in mind that after calling LogCheat below that peer.player will be null again!
  4158. return;
  4159.  
  4160. if(!r3d_vector_isFinite(n.camPos))
  4161. {
  4162. #ifdef ENABLE_GAMEBLOCKS
  4163. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  4164. {
  4165. g_GameBlocks_Client->PrepareEventForSending("GodModeCheatAttempt", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(peer.player->profile_.CustomerID)));
  4166. g_GameBlocks_Client->SendEvent();
  4167. }
  4168. #endif
  4169. return;
  4170. }
  4171.  
  4172.  
  4173. float dist = (peer.player->GetPosition() - n.camPos).Length();
  4174. bool cheated = false;
  4175.  
  4176. float maxDistance = 10.0f;
  4177. #ifdef VEHICLES_ENABLED
  4178. if (peer.player->IsInVehicle())
  4179. maxDistance = 45.0f;
  4180. #endif
  4181.  
  4182. if(peer.player->loadout_->Health > 0 && dist > maxDistance)
  4183. {
  4184. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_CameraHack, 0, "camerahack",
  4185. "%f", dist);
  4186. cheated = true;
  4187. }
  4188. if(peer.player->loadout_->Health == 0 && dist > 50.0f)
  4189. {
  4190. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_CameraHack, 0, "camerahack2",
  4191. "%f", dist);
  4192. cheated = true;
  4193. }
  4194.  
  4195. #ifdef ENABLE_GAMEBLOCKS
  4196. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected() && cheated)
  4197. {
  4198. g_GameBlocks_Client->PrepareEventForSending("CheatCameraPos", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(peer.CustomerID)));
  4199. g_GameBlocks_Client->SendEvent();
  4200. }
  4201. #endif
  4202.  
  4203. return;
  4204. }
  4205.  
  4206. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_UseNetObject)
  4207. {
  4208. //LogInfo(peerId, "PKT_C2S_UseNetObject", "%d", n.spawnID); CLOG_INDENT;
  4209.  
  4210. // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  4211. obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  4212. if(!fromPlr) {
  4213. return;
  4214. }
  4215.  
  4216. if(fromPlr->loadout_->Alive == 0) {
  4217. // he might be dead on server, but still didn't know that on client
  4218. return;
  4219. }
  4220.  
  4221. if(fromPlr->inventoryOpActive_) {
  4222. return;
  4223. }
  4224.  
  4225. GameObject* base = GameWorld().GetNetworkObject(n.spawnID);
  4226. if(!base) {
  4227. // this is valid situation, as network item might be already despawned
  4228. return;
  4229. }
  4230.  
  4231. // multiple players can try to activate it
  4232. if(!base->isActive())
  4233. return;
  4234.  
  4235. // r3dOutToLog("UseNetObject(%d): plrPos: %.2f, %.2f, %.2f\n", peerId, fromPlr->GetPosition().x, fromPlr->GetPosition().y, fromPlr->GetPosition().z);
  4236.  
  4237. // validate range (without Y)
  4238. {
  4239. r3dPoint3D bpos = base->GetPosition(); bpos.y = 0.0f;
  4240. r3dPoint3D ppos = fromPlr->GetPosition(); ppos.y = 0.0f;
  4241. float dist = (bpos - ppos).Length();
  4242. //r3dOutToLog("UseNetObject(%d): dist=%.2f\n", peerId, dist);
  4243. if(dist > 5.0f)
  4244. {
  4245. gServerLogic.LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Protocol, true, "UseNetObject",
  4246. "dist %f", dist);
  4247. return;
  4248. }
  4249. }
  4250.  
  4251. #ifdef ENABLE_GAMEBLOCKS
  4252. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  4253. {
  4254. uint32_t itemID = 0;
  4255. int spawned = 0;
  4256. int isHackerDecoy = 0;
  4257. if(base->Class->Name == "obj_SpawnedItem")
  4258. {
  4259. itemID = ((obj_SpawnedItem*)base)->m_Item.itemID;
  4260. spawned = 1;
  4261. isHackerDecoy = ((obj_SpawnedItem*)base)->m_isHackerDecoy?1:0;
  4262. }
  4263. else if(base->Class->Name == "obj_DroppedItem")
  4264. itemID = ((obj_DroppedItem*)base)->m_Item.itemID;
  4265. else if(base->Class->Name == "obj_ServerLockbox")
  4266. itemID = 0; // do not send anything to FF
  4267. else if(base->Class->Name == "obj_ServerFarmBlock")
  4268. itemID = 0; // do not send anything to FF
  4269.  
  4270. if(itemID)
  4271. {
  4272. g_GameBlocks_Client->PrepareEventForSending("ItemPickup", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(fromPlr->profile_.CustomerID)));
  4273. g_GameBlocks_Client->AddKeyValueInt("SpawnedItem", spawned);
  4274. g_GameBlocks_Client->AddKeyValueInt("HackerDecoy", isHackerDecoy);
  4275. g_GameBlocks_Client->AddKeyValueInt("ItemID", itemID);
  4276. g_GameBlocks_Client->AddKeyValueVector3D("Position", base->GetPosition().x, base->GetPosition().y, base->GetPosition().z);
  4277. const BaseItemConfig* cfg = g_pWeaponArmory->getConfig(itemID);
  4278. int cat = storecat_INVALID;
  4279. if(cfg)
  4280. cat = cfg->category;
  4281. g_GameBlocks_Client->AddKeyValueInt("Category", cat);
  4282. g_GameBlocks_Client->SendEvent();
  4283.  
  4284. // log into our DB too
  4285. if(isHackerDecoy)
  4286. LogCheat(fromPlr->peerId_, PKT_S2C_CheatWarning_s::CHEAT_HackerDecoyPickup, false, "player picked up decoy item, using ESP 100%",
  4287. "item: %d, loc: %.2f,%.2f,%.2f", itemID, base->GetPosition().x, base->GetPosition().y, base->GetPosition().z);
  4288. }
  4289. }
  4290. #endif
  4291.  
  4292. // check notify time
  4293. float timeSinceNotify = n.clientTime - fromPlr->lastPickupNotifyTime;
  4294. //r3dOutToLog("!!! @@@@ notifyTime = %.3f\n", timeSinceNotify);
  4295. if(timeSinceNotify < 0.3f) // client side check, so increased tolerance. client sends pickup only 1 second after fromPlr->lastPickupNotifyTime
  4296. {
  4297. // collect data for now
  4298. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_QuickPickupItem, false, "Improved detection: item was picked up too fast, time should be more than 1.0", "time=%.2f", timeSinceNotify);
  4299. #ifdef ENABLE_GAMEBLOCKS
  4300. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  4301. {
  4302. g_GameBlocks_Client->PrepareEventForSending("ItemPickupTooFast", g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(fromPlr->profile_.CustomerID)));
  4303. g_GameBlocks_Client->SendEvent();
  4304. }
  4305. #endif
  4306. }
  4307.  
  4308. if(base->Class->Name == "obj_SpawnedItem")
  4309. {
  4310. obj_SpawnedItem* obj = (obj_SpawnedItem*)base;
  4311. if(fromPlr->BackpackAddItem(obj->m_Item))
  4312. {
  4313. #ifdef MISSIONS
  4314. if( fromPlr->m_MissionsProgress )
  4315. fromPlr->m_MissionsProgress->PerformItemAction( Mission::ITEM_Collect, obj->m_Item.itemID, obj->GetHashID() );
  4316. #endif
  4317. obj->setActiveFlag(0);
  4318. }
  4319. }
  4320. else if(base->Class->Name == "obj_DroppedItem")
  4321. {
  4322. obj_DroppedItem* obj = (obj_DroppedItem*)base;
  4323. if(fromPlr->BackpackAddItem(obj->m_Item))
  4324. {
  4325. #ifdef MISSIONS
  4326. if( fromPlr->m_MissionsProgress )
  4327. fromPlr->m_MissionsProgress->PerformItemAction( Mission::ITEM_Collect, obj->m_Item.itemID, obj->GetHashID() );
  4328. #endif
  4329. obj->setActiveFlag(0);
  4330. }
  4331. }
  4332. #if defined(MISSIONS) && defined(MISSION_TRIGGERS)
  4333. else if(base->Class->Name == "obj_MissionTrigger")
  4334. {
  4335. r3d_assert( false && "Mission Triggers are disabled, since no UI exists for them atm." );
  4336. Mission::obj_MissionTrigger* obj = (Mission::obj_MissionTrigger*)base;
  4337. obj->NetShowMissionTrigger(peerId);
  4338. }
  4339. #endif
  4340. else if(base->Class->Name == "obj_Note")
  4341. {
  4342. obj_Note* obj = (obj_Note*)base;
  4343. obj->NetSendNoteData(peerId);
  4344. }
  4345. else if(base->Class->Name == "obj_ServerFarmBlock")
  4346. {
  4347. obj_ServerFarmBlock* farm = (obj_ServerFarmBlock*)base;
  4348. farm->TryToHarvest(fromPlr);
  4349. }
  4350. else if(base->Class->Name == "obj_ServerLockbox")
  4351. {
  4352. obj_ServerLockbox* lockbox = TryToOpenLockbox(fromPlr, toP2pNetId(base->GetNetworkID()), "");
  4353. if (lockbox)
  4354. {
  4355. lockbox->UpdateServerData();
  4356. lockbox->SendContentToPlayer(fromPlr);
  4357. }
  4358.  
  4359. // disabled - only owner can access lock box now
  4360. /*
  4361. if(!lockbox->m_IsLocked)
  4362. {
  4363. PKT_S2C_LockboxOpReq_s n2;
  4364. n2.op = PKT_S2C_LockboxOpReq_s::LBOR_SetNewCode;
  4365. n2.lockboxID = toP2pNetId(lockbox->GetNetworkID());
  4366. gServerLogic.p2pSendToPeer(fromPlr->peerId_, fromPlr, &n2, sizeof(n2));
  4367. }
  4368. else
  4369. {
  4370. if(lockbox->IsLockdownActive(fromPlr))
  4371. {
  4372. n2.op = PKT_S2C_LockboxOpReq_s::LBOR_SecurityLockdown;
  4373. n2.lockboxID = 0;
  4374. }
  4375. else
  4376. {
  4377. n2.op = PKT_S2C_LockboxOpReq_s::LBOR_AskForCode;
  4378. n2.lockboxID = toP2pNetId(lockbox->GetNetworkID());
  4379. }
  4380. gServerLogic.p2pSendToPeer(fromPlr->peerId_, fromPlr, &n2, sizeof(n2));
  4381. }
  4382. */
  4383. }
  4384. else
  4385. {
  4386. LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Protocol, false, "UseNetObject",
  4387. "obj %s", base->Class->Name.c_str());
  4388. }
  4389.  
  4390. return;
  4391. }
  4392.  
  4393. obj_ServerLockbox* ServerGameLogic::TryToOpenLockbox(obj_ServerPlayer* fromPlr, gp2pnetid_t lockboxID, const char* AccessCodeS)
  4394. {
  4395. if(fromPlr->loadout_->Alive == 0) {
  4396. // he might be dead on server, but still didn't know that on client
  4397. return NULL;
  4398. }
  4399.  
  4400. GameObject* obj = GameWorld().GetNetworkObject(lockboxID);
  4401. if(obj == NULL)
  4402. return NULL;
  4403. if(obj->Class->Name != "obj_ServerLockbox")
  4404. return NULL;
  4405. obj_ServerLockbox* lockbox = (obj_ServerLockbox*)obj;
  4406.  
  4407. if((fromPlr->GetPosition() - lockbox->GetPosition()).Length() > 5.0f)
  4408. return NULL; // cheat?
  4409.  
  4410. // important- first access to lockbox will set it code
  4411. //if(!lockbox->m_IsLocked)
  4412. // lockbox->setAccessCode(AccessCodeS);
  4413.  
  4414. //if(lockbox->IsLockdownActive(fromPlr))
  4415. //{
  4416. // PKT_S2C_LockboxOpReq_s n2;
  4417. // n2.op = PKT_S2C_LockboxOpReq_s::LBOR_SecurityLockdown;
  4418. // n2.lockboxID = 0;
  4419. // gServerLogic.p2pSendToPeer(fromPlr->peerId_, fromPlr, &n2, sizeof(n2));
  4420. // return NULL;
  4421. //}
  4422.  
  4423. //if(strcmp(lockbox->m_AccessCodeS, AccessCodeS)==0)
  4424. if (lockbox->lockboxOwnerId == fromPlr->profile_.CustomerID || fromPlr->profile_.ProfileData.isDevAccount)
  4425. {
  4426. return lockbox;
  4427. }
  4428. else
  4429. {
  4430. //lockbox->SetLockdown(fromPlr->profile_.CustomerID);
  4431.  
  4432. PKT_S2C_LockboxOpReq_s n2;
  4433. n2.op = PKT_S2C_LockboxOpReq_s::LBOR_NotOwner;
  4434. n2.lockboxID = 0;
  4435. gServerLogic.p2pSendToPeer(fromPlr->peerId_, fromPlr, &n2, sizeof(n2));
  4436. return NULL;
  4437. }
  4438. }
  4439.  
  4440. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_LockboxOpAns)
  4441. {
  4442. if(!IsNullTerminated(n.AccessCodeS, sizeof(n.AccessCodeS))) {
  4443. gServerLogic.DisconnectPeer(peerId, true, "invalid PKT_C2S_LockboxOpAns");
  4444. return;
  4445. }
  4446.  
  4447. // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  4448. obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  4449. if(!fromPlr) {
  4450. return;
  4451. }
  4452.  
  4453. obj_ServerLockbox* lockbox = TryToOpenLockbox(fromPlr, n.lockboxID, n.AccessCodeS);
  4454. if(lockbox)
  4455. {
  4456. lockbox->UpdateServerData();
  4457. // send lockbox content
  4458. lockbox->SendContentToPlayer(fromPlr);
  4459. }
  4460. }
  4461.  
  4462. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_LockboxKeyReset)
  4463. {
  4464. if(!IsNullTerminated(n.old_AccessCodeS, sizeof(n.old_AccessCodeS))) {
  4465. gServerLogic.DisconnectPeer(peerId, true, "invalid PKT_C2S_LockboxItemBackpackToLockbox_s");
  4466. return;
  4467. }
  4468. if(!IsNullTerminated(n.new_AccessCodeS, sizeof(n.new_AccessCodeS))) {
  4469. gServerLogic.DisconnectPeer(peerId, true, "invalid PKT_C2S_LockboxItemBackpackToLockbox_s");
  4470. return;
  4471. }
  4472.  
  4473. // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  4474. obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  4475. if(!fromPlr) {
  4476. return;
  4477. }
  4478.  
  4479. obj_ServerLockbox* lockbox = TryToOpenLockbox(fromPlr, n.lockboxID, n.old_AccessCodeS);
  4480. if(lockbox)
  4481. {
  4482. lockbox->setAccessCode(n.new_AccessCodeS);
  4483. PKT_S2C_LockboxOpReq_s n2;
  4484. n2.op = PKT_S2C_LockboxOpReq_s::LBOR_CodeChanged;
  4485. n2.lockboxID = 0;
  4486. gServerLogic.p2pSendToPeer(fromPlr->peerId_, fromPlr, &n2, sizeof(n2));
  4487. }
  4488. }
  4489.  
  4490. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_PreparingUseNetObject)
  4491. {
  4492. // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  4493. obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  4494. if(!fromPlr) {
  4495. return;
  4496. }
  4497.  
  4498. if(fromPlr->loadout_->Alive == 0) {
  4499. // he might be dead on server, but still didn't know that on client
  4500. return;
  4501. }
  4502.  
  4503. fromPlr->lastPickupNotifyTime = n.clientTime; // yes, this is hackable, but otherwise server side check is not going to work due to latency in packet arrival
  4504.  
  4505. return;
  4506. }
  4507.  
  4508. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_CreateNote)
  4509. {
  4510. // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  4511. obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  4512. if(!fromPlr) {
  4513. return;
  4514. }
  4515.  
  4516. if(!IsNullTerminated(n.TextFrom, sizeof(n.TextFrom)) || !IsNullTerminated(n.TextSubj, sizeof(n.TextSubj))) {
  4517. gServerLogic.LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Protocol, true, "PKT_C2S_CreateNote",
  4518. "no null in text");
  4519. return;
  4520. }
  4521.  
  4522. // relay logic to player
  4523. fromPlr->UseItem_CreateNote(n);
  4524. return;
  4525. }
  4526.  
  4527. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_TEST_SpawnDummyReq)
  4528. {
  4529. r3dOutToLog("!!!!!!! NOPE: dummies not implemented\n");
  4530. r3d_assert(fromObj);
  4531. r3d_assert(IsServerPlayer(fromObj));
  4532.  
  4533. return;
  4534. }
  4535.  
  4536. #ifdef MISSIONS
  4537. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_AcceptMission)
  4538. {
  4539. // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  4540. obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  4541. if(!fromPlr) {
  4542. return;
  4543. }
  4544.  
  4545. if( Mission::g_pMissionMgr )
  4546. {
  4547. if( !Mission::g_pMissionMgr->IsMissionActive( n.missionID ) ) {
  4548. gServerLogic.LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Protocol, true, "PKT_C2S_AcceptMission", "Mission(%d): Invalid mission accepted", n.missionID);
  4549. return;
  4550. }
  4551.  
  4552. if( fromPlr->m_MissionsProgress )
  4553. if( fromPlr->m_MissionsProgress->AddMission( n.missionID ) )
  4554. g_AsyncApiMgr->AddJob(new CJobUpdateMissionsData( fromPlr ));
  4555. }
  4556. }
  4557.  
  4558. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_AbandonMission)
  4559. {
  4560. // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  4561. obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  4562. if(!fromPlr) {
  4563. return;
  4564. }
  4565.  
  4566. if( Mission::g_pMissionMgr )
  4567. {
  4568. if( !Mission::g_pMissionMgr->IsMissionActive( n.missionID ) ) {
  4569. gServerLogic.LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Protocol, true, "PKT_C2S_AbandonMission", "invalid mission abandoned");
  4570. return;
  4571. }
  4572.  
  4573. if( fromPlr->m_MissionsProgress )
  4574. if( fromPlr->m_MissionsProgress->RemoveMission( n.missionID, Mission::RMV_MissionAbandoned ) )
  4575. g_AsyncApiMgr->AddJob(new CJobUpdateMissionsData( fromPlr ));
  4576. }
  4577. }
  4578.  
  4579. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_MissionStateObjectUse)
  4580. {
  4581. // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  4582. obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  4583. if(!fromPlr)
  4584. return;
  4585.  
  4586. if( Mission::g_pMissionMgr )
  4587. {
  4588. GameObject* obj = GameWorld().GetObjectByHash( n.objHash );
  4589. if( !obj )
  4590. {
  4591. gServerLogic.LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Protocol, true, "PKT_C2S_MissionStateObjectUse", "invalid object hash");
  4592. return;
  4593. }
  4594.  
  4595. float distance = (obj->GetPosition() - fromPlr->GetPosition()).Length();
  4596. if( distance > 5.0f )
  4597. {
  4598. gServerLogic.LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Protocol, false, "PKT_C2S_MissionStateObjectUse", "player %s is standing too far (%.2f m) from Mission State Object with HashID %d", fromPlr->Name, distance, n.objHash);
  4599. return;
  4600. }
  4601.  
  4602. if( fromPlr->m_MissionsProgress )
  4603. {
  4604. fromPlr->m_MissionsProgress->IncState( obj );
  4605. }
  4606. }
  4607. }
  4608. #endif
  4609.  
  4610. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_DBG_LogMessage)
  4611. {
  4612. // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  4613. obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  4614. if(!fromPlr) {
  4615. return;
  4616. }
  4617.  
  4618. // log that packet with temp cheat code
  4619. LogCheat(fromPlr->peerId_, 98, false, "clientlog",
  4620. "%s",
  4621. n.msg
  4622. );
  4623. return;
  4624. }
  4625.  
  4626. void ServerGameLogic::OnPKT_C2S_ScreenshotData(DWORD peerId, const int size, const char* data)
  4627. {
  4628. //char fname[MAX_PATH];
  4629.  
  4630. const peerInfo_s& peer = GetPeer(peerId);
  4631. if(peer.player == NULL)
  4632. {
  4633. return;
  4634. }
  4635. /*else
  4636. {
  4637. sprintf(fname, "logss\\JPG_%d_%d_%d_%x.jpg", ginfo_.gameServerId, peer.player->profile_.CustomerID, peer.player->loadout_->LoadoutID, GetTickCount());
  4638. }
  4639.  
  4640. r3dOutToLog("peer%02d received screenshot, fname:%s\n", peerId, fname);
  4641.  
  4642. FILE* f = fopen(fname, "wb");
  4643. if(f == NULL) {
  4644. LogInfo(peerId, "SaveScreenshot", "unable to save fname:%s", fname);
  4645. }
  4646. else
  4647. {
  4648. fwrite(data, 1, size, f);
  4649. fclose(f);
  4650. }*/
  4651.  
  4652. peer.player->security_screenshotRequestSentAt = 0; // reset
  4653.  
  4654. #ifdef ENABLE_GAMEBLOCKS
  4655. if(g_GameBlocks_Client && g_GameBlocks_Client->Connected())
  4656. {
  4657. GameBlocks::Event_PlayerScreenShotJpg_Send(g_GameBlocks_Client, g_GameBlocks_ServerID, GameBlocks::GBPublicPlayerId(uint32_t(peer.player->profile_.CustomerID)), data, size);
  4658. }
  4659. #endif
  4660. return;
  4661. }
  4662.  
  4663. void ServerGameLogic::OnPKT_C2S_PunkBuster(DWORD peerId, const int size, const char* data)
  4664. {
  4665. const peerInfo_s& peer = GetPeer(peerId);
  4666. if(peer.player == NULL) {
  4667. return;
  4668. }
  4669.  
  4670. #ifdef __WITH_PB__
  4671. if ( memcmp ( data, "\xff\xff\xff\xffPB_", 7 ) )
  4672. return ;
  4673.  
  4674. PbSvAddEvent ( PB_EV_PACKET, peer.playerIdx, size-4, (char*)data+4 ) ;
  4675. #endif
  4676.  
  4677. return;
  4678. }
  4679.  
  4680.  
  4681. int ServerGameLogic::ProcessWorldEvent(GameObject* fromObj, DWORD eventId, DWORD peerId, const void* packetData, int packetSize)
  4682. {
  4683. // do version check and game join request
  4684. peerInfo_s& peer = GetPeer(peerId);
  4685.  
  4686. switch(peer.status_)
  4687. {
  4688. // check version in connected state
  4689. case PEER_CONNECTED:
  4690. switch(eventId)
  4691. {
  4692. DEFINE_PACKET_HANDLER(PKT_C2S_ValidateConnectingPeer);
  4693. }
  4694. DisconnectPeer(peerId, true, "bad packet ID %d in connected state", eventId);
  4695. return TRUE;
  4696.  
  4697. // process join request in validated state
  4698. case PEER_VALIDATED1:
  4699. switch(eventId)
  4700. {
  4701. DEFINE_PACKET_HANDLER(PKT_C2S_JoinGameReq);
  4702. }
  4703. DisconnectPeer(peerId, true, "bad packet ID %d in validated1 state", eventId);
  4704. return TRUE;
  4705.  
  4706. case PEER_LOADING:
  4707. switch(eventId)
  4708. {
  4709. DEFINE_PACKET_HANDLER(PKT_C2S_StartGameReq);
  4710. }
  4711. DisconnectPeer(peerId, true, "bad packet ID %d in loading state", eventId);
  4712. return TRUE;
  4713. }
  4714.  
  4715. r3d_assert(peer.status_ == PEER_PLAYING);
  4716.  
  4717. // validation and relay client code
  4718. switch(eventId)
  4719. {
  4720. DEFINE_PACKET_HANDLER(PKT_C2C_ChatMessage);
  4721. DEFINE_PACKET_HANDLER(PKT_C2S_DataUpdateReq);
  4722. DEFINE_PACKET_HANDLER(PKT_C2S_ClientConnection);
  4723. DEFINE_PACKET_HANDLER(PKT_C2S_SecurityRep);
  4724. DEFINE_PACKET_HANDLER(PKT_C2S_CameraPos);
  4725. DEFINE_PACKET_HANDLER(PKT_C2S_Admin_GiveItem);
  4726. DEFINE_PACKET_HANDLER(PKT_C2S_UseNetObject);
  4727. DEFINE_PACKET_HANDLER(PKT_C2S_PreparingUseNetObject);
  4728. DEFINE_PACKET_HANDLER(PKT_C2S_CreateNote);
  4729. DEFINE_PACKET_HANDLER(PKT_C2S_LockboxOpAns);
  4730. DEFINE_PACKET_HANDLER(PKT_C2S_LockboxKeyReset);
  4731. DEFINE_PACKET_HANDLER(PKT_C2S_TEST_SpawnDummyReq);
  4732. #ifdef MISSIONS
  4733. DEFINE_PACKET_HANDLER(PKT_C2S_AcceptMission);
  4734. DEFINE_PACKET_HANDLER(PKT_C2S_AbandonMission);
  4735. DEFINE_PACKET_HANDLER(PKT_C2S_MissionStateObjectUse);
  4736. #endif
  4737.  
  4738. DEFINE_PACKET_HANDLER(PKT_C2S_DBG_LogMessage);
  4739. #ifdef VEHICLES_ENABLED
  4740. DEFINE_PACKET_HANDLER(PKT_C2S_VehicleEnter);
  4741. DEFINE_PACKET_HANDLER(PKT_C2S_VehicleExit);
  4742. DEFINE_PACKET_HANDLER(PKT_C2S_VehicleHitTarget);
  4743. DEFINE_PACKET_HANDLER(PKT_C2S_VehicleStopZombie);
  4744. #endif
  4745. // special packet case with variable length
  4746. case PKT_C2S_ScreenshotData:
  4747. {
  4748. const PKT_C2S_ScreenshotData_s& n = *(PKT_C2S_ScreenshotData_s*)packetData;
  4749. if(packetSize < sizeof(n)) {
  4750. LogInfo(peerId, "PKT_C2S_ScreenshotData", "packetSize %d < %d", packetSize, sizeof(n));
  4751. return TRUE;
  4752. }
  4753. if(n.errorCode != 0)
  4754. {
  4755. LogInfo(peerId, "PKT_C2S_ScreenshotData", "screenshot grab failed: %d", n.errorCode);
  4756. return TRUE;
  4757. }
  4758.  
  4759. if(packetSize != sizeof(n) + n.dataSize) {
  4760. LogInfo(peerId, "PKT_C2S_ScreenshotData", "dataSize %d != %d+%d", packetSize, sizeof(n), n.dataSize);
  4761. return TRUE;
  4762. }
  4763.  
  4764. OnPKT_C2S_ScreenshotData(peerId, n.dataSize, (char*)packetData + sizeof(n));
  4765. return TRUE;
  4766. }
  4767.  
  4768. // special packet case with variable length
  4769. case PKT_C2S_PunkBuster:
  4770. {
  4771. const PKT_C2S_PunkBuster_s& n = *(PKT_C2S_PunkBuster_s*)packetData;
  4772. if(packetSize < sizeof(n)) {
  4773. LogInfo(peerId, "PKT_C2S_PunkBuster", "packetSize %d < %d", packetSize, sizeof(n));
  4774. return TRUE;
  4775. }
  4776. if(n.errorCode != 0)
  4777. {
  4778. LogInfo(peerId, "PKT_C2S_PunkBuster", "screenshot grab failed: %d", n.errorCode);
  4779. return TRUE;
  4780. }
  4781.  
  4782. if(packetSize != sizeof(n) + n.dataSize) {
  4783. LogInfo(peerId, "PKT_C2S_PunkBuster", "dataSize %d != %d+%d", packetSize, sizeof(n), n.dataSize);
  4784. return TRUE;
  4785. }
  4786.  
  4787. OnPKT_C2S_PunkBuster(peerId, n.dataSize, (char*)packetData + sizeof(n));
  4788. return TRUE;
  4789. }
  4790. }
  4791.  
  4792. return FALSE;
  4793. }
  4794.  
  4795. void ServerGameLogic::TrackWeaponUsage(uint32_t ItemID, int ShotsFired, int ShotsHits, int Kills)
  4796. {
  4797. WeaponStats_s* ws = NULL;
  4798. for(size_t i = 0, size = weaponStats_.size(); i < size; ++i)
  4799. {
  4800. if(weaponStats_[i].ItemID == ItemID)
  4801. {
  4802. ws = &weaponStats_[i];
  4803. break;
  4804. }
  4805. }
  4806.  
  4807. if(ws == NULL)
  4808. {
  4809. weaponStats_.push_back(WeaponStats_s());
  4810. ws = &weaponStats_.back();
  4811. ws->ItemID = ItemID;
  4812. }
  4813.  
  4814. r3d_assert(ws);
  4815. ws->ShotsFired += ShotsFired;
  4816. ws->ShotsHits += ShotsHits;
  4817. ws->Kills += Kills;
  4818. return;
  4819. }
  4820.  
  4821. void ServerGameLogic::StartHibernate()
  4822. {
  4823. r3d_assert(!hibernateStarted_);
  4824. hibernateStarted_ = true;
  4825.  
  4826. r3dOutToLog("Hibernate starting\n"); CLOG_INDENT;
  4827.  
  4828. CJobHibernate* job = new CJobHibernate();
  4829.  
  4830. // server state
  4831. job->jobs.push_back(new CJobSetSavedServerState());
  4832.  
  4833. // dynamic objects
  4834. ObjectManager& GW = GameWorld();
  4835. for(GameObject* obj = GW.GetFirstObject(); obj; obj = GW.GetNextObject(obj))
  4836. {
  4837. if(obj->GetNetworkID() == 0)
  4838. continue;
  4839. if(obj->ObjFlags & OBJFLAG_JustCreated)
  4840. continue;
  4841. if(!obj->isActive())
  4842. continue;
  4843.  
  4844. INetworkHelper* nh = obj->GetNetworkHelper();
  4845. switch(nh->GetServerObjectSerializationType())
  4846. {
  4847. case 0:
  4848. break;
  4849.  
  4850. case 1: // static object
  4851. {
  4852. if(!nh->srvObjParams_.IsDirty)
  4853. break;
  4854.  
  4855. CJobUpdateServerObject* job2 = new CJobUpdateServerObject(obj);
  4856. job->jobs.push_back(job2);
  4857. break;
  4858. }
  4859.  
  4860. case 2: // hibernated object
  4861. {
  4862. CJobAddServerObject* job2 = new CJobAddServerObject(obj);
  4863. job->jobs.push_back(job2);
  4864. break;
  4865. }
  4866. }
  4867. }
  4868. r3dOutToLog("hibernating %d objects\n", job->jobs.size());
  4869.  
  4870. g_AsyncApiMgr->AddJob(job);
  4871. }
  4872.  
  4873. void ServerGameLogic::UpdateHibernate()
  4874. {
  4875. if(curPeersConnected == 0) secsWithoutPlayers_ += r3dGetFrameTime();
  4876. else secsWithoutPlayers_ = 0;
  4877.  
  4878. if(!ginfo_.IsRentedGame())
  4879. return;
  4880.  
  4881. if(hibernateStarted_)
  4882. return;
  4883.  
  4884. // 5 min on gameservers, 60 sec on strongholds.
  4885. float secToWait = ginfo_.IsGameworld() ? (5 * 60.0f) : 60;
  4886.  
  4887. // start hibernate
  4888. if(secsWithoutPlayers_ > secToWait)
  4889. {
  4890. int jobs = g_AsyncApiMgr->GetActiveJobs();
  4891. if(jobs > 0)
  4892. {
  4893. // delay hibernate to 30 secs, report about that
  4894. secsWithoutPlayers_ = secToWait - 30;
  4895. r3dOutToLog("!!! warning: JobsOnHibernate: %d\n", jobs);
  4896.  
  4897. AsyncJobAddServerLogInfo(PKT_S2C_CheatWarning_s::CHEAT_Jobs, 0, 0,
  4898. "JobsOnHibernate", "n: %d",
  4899. jobs);
  4900.  
  4901. g_AsyncApiMgr->DumpJobs();
  4902. return;
  4903. }
  4904.  
  4905.  
  4906. StartHibernate();
  4907. }
  4908. }
  4909.  
  4910. void ServerGameLogic::Tick()
  4911. {
  4912. //r3dOutToLog("ServerGameLogic::Tick\n");
  4913. //CLOG_INDENT;
  4914. r3d_assert(ginfo_.maxPlayers > 0);
  4915.  
  4916. //
  4917. if (ginfo_.IsGameBR())
  4918. BattleRoyaleTick();
  4919. //
  4920.  
  4921. {
  4922. const float t1 = r3dGetTime();
  4923. net_->Update();
  4924. const float t2 = r3dGetTime() - t1;
  4925. //r3dOutToLog("net update %f sec\n", t2);
  4926. }
  4927.  
  4928. {
  4929. const float t1 = r3dGetTime();
  4930. #ifdef ENABLE_GAMEBLOCKS
  4931. if(g_GameBlocks_Client)
  4932. {
  4933. {
  4934. const float t3 = r3dGetTime();
  4935. g_GameBlocks_Client->Tick();
  4936. const float t4 = r3dGetTime() - t3;
  4937. //r3dOutToLog("FF tick: %f\n", t4);
  4938. }
  4939.  
  4940. // aim bot detection. YO! :D
  4941. {
  4942. const float t3 = r3dGetTime();
  4943. {
  4944. g_GameBlocks_Client->AimBotDetector_BeginFrame();
  4945. {
  4946. const float t5 = r3dGetTime();
  4947. for(int i=0; i<curPlayers_; ++i)
  4948. {
  4949. obj_ServerPlayer* pl = plrList_[i];
  4950. uint32_t currentWeaponID = 0;
  4951. if(pl->m_WeaponArray[pl->m_SelectedWeapon])
  4952. currentWeaponID = pl->m_WeaponArray[pl->m_SelectedWeapon]->getConfig()->m_itemID;
  4953. g_GameBlocks_Client->AimBotDetector_Add(GameBlocks::GBPublicPlayerId(uint32_t(pl->profile_.CustomerID)), currentWeaponID, 0, pl->GetPosition().x, pl->GetPosition().y+0.9f, pl->GetPosition().z,
  4954. pl->lastCamPos.x, pl->lastCamPos.y, pl->lastCamPos.z,
  4955. pl->lastCamDir.x, pl->lastCamDir.y, pl->lastCamDir.z);
  4956. }
  4957. const float t6 = r3dGetTime() - t5;
  4958. //r3dOutToLog("FF aimbot 1: %f\n", t6);
  4959. }
  4960.  
  4961. {
  4962. const float t5 = r3dGetTime();
  4963. int c=0;
  4964. for(std::list<obj_Zombie*>::iterator it = obj_Zombie::s_ListOfAllActiveZombies.begin(); it!=obj_Zombie::s_ListOfAllActiveZombies.end(); ++it)
  4965. {
  4966. obj_Zombie* z = *it;
  4967. if(z->ZombieState != EZombieStates::ZState_Dead)
  4968. {
  4969. c++;
  4970. g_GameBlocks_Client->AimBotDetector_Add(GameBlocks::GBPublicPlayerId(uint32_t(z->ZombieUniqueIDForFF)), 0, 0, z->GetPosition().x, z->GetPosition().y+0.9f, z->GetPosition().z,
  4971. 0, 0, 0,
  4972. 0, 0, 0);
  4973. }
  4974. }
  4975. const float t6 = r3dGetTime() - t5;
  4976. //r3dOutToLog("FF aimbot 2: %f, z:%d\n", t6, c);
  4977. }
  4978.  
  4979. g_GameBlocks_Client->AimBotDetector_EndFrame();
  4980. }
  4981. const float t4 = r3dGetTime() - t3;
  4982. //r3dOutToLog("FF aimbot: %f\n", t4);
  4983. }
  4984.  
  4985. if(g_GameBlocks_Client->Connected())
  4986. {
  4987. static bool logConnectedToGB = true;
  4988. if(logConnectedToGB)
  4989. {
  4990. r3dOutToLog("Connected to Gameblocks server!\n");
  4991. logConnectedToGB = false;
  4992. }
  4993.  
  4994. {
  4995. const float t3 = r3dGetTime();
  4996. if(!g_GameBlocks_SentServerInfo)
  4997. {
  4998. g_GameBlocks_SentServerInfo = true;
  4999. g_GameBlocks_Client->Source_SetProperty(g_GameBlocks_ServerID, GB_RESERVED_EVENT_SOURCEINFO_KEY_PROP_MAP_NEW, ginfo_.mapId);
  5000. g_GameBlocks_Client->Source_SetProperty(g_GameBlocks_ServerID, "ServerName", ginfo_.name);
  5001. }
  5002. const float t4 = r3dGetTime() - t3;
  5003. //r3dOutToLog("FF1 tick: %f\n", t4);
  5004. }
  5005. {
  5006. const float t3 = r3dGetTime();
  5007. if (g_GameBlocks_Client->Incoming_EventCount() > 0) // process one message at a time
  5008. {
  5009. g_GameBlocks_Client->Incoming_PrepareEventForReading();
  5010.  
  5011. //get incoming message information
  5012. const char* messageName = g_GameBlocks_Client->Incoming_GetName();
  5013. const GameBlocks::GBPublicPlayerId playerID = g_GameBlocks_Client->Incoming_GetPlayerId();
  5014. uint32_t plrID = 0;
  5015. if(playerID.IsValid())
  5016. plrID = playerID;
  5017.  
  5018. r3dOutToLog("Received message from Gameblocks: '%s' for playerID:%d, numPairValues: %d\n", messageName?messageName:"none", plrID, g_GameBlocks_Client->Incoming_GetNumPairs());
  5019.  
  5020. char reason[512] = {0};
  5021. if(g_GameBlocks_Client->Incoming_HasPairValueString(0))
  5022. g_GameBlocks_Client->Incoming_GetPairValueString(reason, 512, 0);
  5023.  
  5024. if(strcmp(messageName, "Kick")==0 && reason[0])
  5025. {
  5026. for(int i=0; i<curPlayers_; ++i)
  5027. {
  5028. obj_ServerPlayer* pl = plrList_[i];
  5029. if(pl->profile_.CustomerID == plrID)
  5030. {
  5031. LogInfo(pl->peerId_, "kicked by gameblocks", "kicked by gameblocks, reason %s", reason);
  5032. DisconnectPeer(pl->peerId_, false, "disconnected by gameblocks");
  5033. break;
  5034. }
  5035. }
  5036. }
  5037. else if(strcmp(messageName, "KickMsg")==0 && reason[0])
  5038. {
  5039. for(int i=0; i<curPlayers_; ++i)
  5040. {
  5041. obj_ServerPlayer* pl = plrList_[i];
  5042. if(pl->profile_.CustomerID == plrID)
  5043. {
  5044. PKT_S2C_CustomKickMsg_s n;
  5045. r3dscpy(n.msg, reason);
  5046. p2pSendToPeer(pl->peerId_, pl, &n, sizeof(n));
  5047. break;
  5048. }
  5049. }
  5050. }
  5051. else if(strcmp(messageName, "Message")==0 && reason[0])
  5052. {
  5053. for(int i=0; i<curPlayers_; ++i)
  5054. {
  5055. obj_ServerPlayer* pl = plrList_[i];
  5056. if(pl->profile_.CustomerID == plrID)
  5057. {
  5058. PKT_C2C_ChatMessage_s chatPacket;
  5059. chatPacket.FromID = toP2pNetId(pl->GetNetworkID());
  5060. r3dscpy(chatPacket.gamertag, "<SYSTEM>");
  5061. chatPacket.msgChannel = 1; // global
  5062. chatPacket.userFlag = 2; // mark as dev, so color is red
  5063. r3dscpy(chatPacket.msg, reason);
  5064. net_->SendToPeer(&chatPacket, sizeof(chatPacket), pl->peerId_, true);
  5065. break;
  5066. }
  5067. }
  5068. }
  5069. else if(strcmp(messageName, "GlobalMessage")==0 && reason[0])
  5070. {
  5071. for(int i=0; i<curPlayers_; ++i)
  5072. {
  5073. obj_ServerPlayer* pl = plrList_[i];
  5074.  
  5075. PKT_C2C_ChatMessage_s chatPacket;
  5076. chatPacket.FromID = toP2pNetId(pl->GetNetworkID());
  5077. r3dscpy(chatPacket.gamertag, "<SYSTEM>");
  5078. chatPacket.msgChannel = 1; // global
  5079. chatPacket.userFlag = 2; // mark as dev, so color is red
  5080. r3dscpy(chatPacket.msg, reason);
  5081. net_->SendToPeer(&chatPacket, sizeof(chatPacket), pl->peerId_, true);
  5082. }
  5083. }
  5084. else if(strcmp(messageName, "Kill")==0 && reason[0])
  5085. {
  5086. for(int i=0; i<curPlayers_; ++i)
  5087. {
  5088. obj_ServerPlayer* pl = plrList_[i];
  5089. if(pl->profile_.CustomerID == plrID)
  5090. {
  5091. LogInfo(pl->peerId_, "killed by gameblocks", "killed by gameblocks, reason %s", reason);
  5092. DoKillPlayer(pl, pl, storecat_INVALID, true);
  5093. break;
  5094. }
  5095. }
  5096. }
  5097. else if(strcmp(messageName, "Screenshot")==0)
  5098. {
  5099. for(int i=0; i<curPlayers_; ++i)
  5100. {
  5101. obj_ServerPlayer* pl = plrList_[i];
  5102. if(pl->profile_.CustomerID == plrID)
  5103. {
  5104. pl->security_screenshotRequestSentAt = r3dGetTime();
  5105. PKT_S2C_CheatWarning_s sn;
  5106. sn.cheatId = 255;
  5107. p2pSendToPeer(pl->peerId_, pl, &sn, sizeof(sn),true);
  5108. break;
  5109. }
  5110. }
  5111. }
  5112. else if(strcmp(messageName, "ScreenshotFront")==0)
  5113. {
  5114. for(int i=0; i<curPlayers_; ++i)
  5115. {
  5116. obj_ServerPlayer* pl = plrList_[i];
  5117. if(pl->profile_.CustomerID == plrID)
  5118. {
  5119. pl->security_screenshotRequestSentAt = r3dGetTime();
  5120. PKT_S2C_CheatWarning_s sn;
  5121. sn.cheatId = 254;
  5122. p2pSendToPeer(pl->peerId_, pl, &sn, sizeof(sn),true);
  5123. break;
  5124. }
  5125. }
  5126. }
  5127. else if(strcmp(messageName, "ScreenshotBack")==0)
  5128. {
  5129. for(int i=0; i<curPlayers_; ++i)
  5130. {
  5131. obj_ServerPlayer* pl = plrList_[i];
  5132. if(pl->profile_.CustomerID == plrID)
  5133. {
  5134. pl->security_screenshotRequestSentAt = r3dGetTime();
  5135. PKT_S2C_CheatWarning_s sn;
  5136. sn.cheatId = 253;
  5137. p2pSendToPeer(pl->peerId_, pl, &sn, sizeof(sn),true);
  5138. break;
  5139. }
  5140. }
  5141. }
  5142. else if(strcmp(messageName, "Teleport")==0 && g_GameBlocks_Client->Incoming_HasPairValueFloat(0)
  5143. && g_GameBlocks_Client->Incoming_HasPairValueFloat(1)
  5144. && g_GameBlocks_Client->Incoming_HasPairValueFloat(2)) // should be used by gameblocks guys only
  5145. {
  5146. float tx, ty, tz;
  5147. g_GameBlocks_Client->Incoming_GetPairValueFloat(tx, 0);
  5148. g_GameBlocks_Client->Incoming_GetPairValueFloat(ty, 1);
  5149. g_GameBlocks_Client->Incoming_GetPairValueFloat(tz, 2);
  5150.  
  5151. for(int i=0; i<curPlayers_; ++i)
  5152. {
  5153. obj_ServerPlayer* pl = plrList_[i];
  5154. if(pl->profile_.CustomerID == plrID)
  5155. {
  5156. admin_TeleportPlayer(pl, tx, tz);
  5157. break;
  5158. }
  5159. }
  5160. }
  5161. //remove this message from the queue
  5162. g_GameBlocks_Client->Incoming_PopMessage();
  5163. }
  5164. const float t4 = r3dGetTime() - t3;
  5165. //r3dOutToLog("FF2 tick: %f\n", t4);
  5166. }
  5167.  
  5168. {
  5169. const float t3 = r3dGetTime();
  5170. static float nextPlayerListUpdate = 0.0f;
  5171. if(r3dGetTime() > nextPlayerListUpdate)
  5172. {
  5173. nextPlayerListUpdate = r3dGetTime() + 30.0f; // update every 30 seconds as recommended by SDK
  5174.  
  5175. GameBlocks::Event_PlayerList_Prepare(g_GameBlocks_Client, g_GameBlocks_ServerID);
  5176. for(int i=0; i<curPlayers_; ++i)
  5177. {
  5178. obj_ServerPlayer* plr = plrList_[i];
  5179.  
  5180. DWORD ip = net_->GetPeerIp(plr->peerId_);
  5181. GameBlocks::Event_PlayerList_Push(g_GameBlocks_Client, GameBlocks::GBPublicPlayerId(uint32_t(plr->profile_.CustomerID)), plr->userName, inet_ntoa(*(in_addr*)&ip), 0, int(r3dGetTime()-plr->startPlayTime_), 0);
  5182. }
  5183. GameBlocks::Event_PlayerList_Send(g_GameBlocks_Client);
  5184. }
  5185. const float t4 = r3dGetTime() - t3;
  5186. //r3dOutToLog("FF3 tick: %f\n", t4);
  5187. }
  5188.  
  5189. {
  5190. const float t3 = r3dGetTime();
  5191. static float nextPlayerCountUpdate = 0.0f;
  5192. if(r3dGetTime() > nextPlayerCountUpdate)
  5193. {
  5194. nextPlayerCountUpdate = r3dGetTime() + 120.0f;
  5195. GameBlocks::Event_PlayerCount_Send(g_GameBlocks_Client, g_GameBlocks_ServerID, curPlayers_);
  5196.  
  5197. g_GameBlocks_Client->PrepareEventForSending("GameTime", g_GameBlocks_ServerID, 0);
  5198. g_GameBlocks_Client->AddKeyValueFloat("ServerTime", getInGameTime());
  5199. g_GameBlocks_Client->SendEvent();
  5200. }
  5201. const float t4 = r3dGetTime() - t3;
  5202. //r3dOutToLog("FF4 tick: %f\n", t4);
  5203. }
  5204.  
  5205. {
  5206. const float t3 = r3dGetTime();
  5207. static float nextMaxPlayerCountUpdate = 0.0f;
  5208. if(r3dGetTime() > nextMaxPlayerCountUpdate)
  5209. {
  5210. nextMaxPlayerCountUpdate = r3dGetTime() + 600.0f;
  5211. GameBlocks::Event_MaxPlayerCount_Send(g_GameBlocks_Client, g_GameBlocks_ServerID, maxLoggedPlayers_);
  5212. }
  5213.  
  5214. static float nextPlayerMoveUpdate = 0.0f;
  5215. if(r3dGetTime() > nextPlayerMoveUpdate)
  5216. {
  5217. nextPlayerMoveUpdate = r3dGetTime() + 1.0f; // update every 1 second
  5218.  
  5219. GameBlocks::Event_PlayerLocationList_Prepare(g_GameBlocks_Client, g_GameBlocks_ServerID);
  5220. for(int i=0; i<curPlayers_; ++i)
  5221. {
  5222. obj_ServerPlayer* plr = plrList_[i];
  5223. r3dPoint3D pos = plr->GetPosition();
  5224. GameBlocks::Event_PlayerLocationList_Push(g_GameBlocks_Client, GameBlocks::GBPublicPlayerId(uint32_t(plr->profile_.CustomerID)),
  5225. pos.x, pos.y, pos.z,
  5226. 0, 0, 0,
  5227. #ifdef VEHICLES_ENABLED
  5228. plr->IsInVehicle()?(plr->GetVehicleType()+1):0, //+1 because vehicle type is 0 based
  5229. plr->IsInVehicle()?(plr->seatPosition==0?1:2):0 // 0-on foot, 1-driver, 2-passenger
  5230. #else
  5231. 0,
  5232. 0
  5233. #endif
  5234. );
  5235. }
  5236. GameBlocks::Event_PlayerLocationList_Send(g_GameBlocks_Client);
  5237. }
  5238. const float t4 = r3dGetTime() - t3;
  5239. //r3dOutToLog("FF5 tick: %f\n", t4);
  5240. }
  5241. }
  5242. }
  5243. #endif //ENABLE_GAMEBLOCKS
  5244. const float t2 = r3dGetTime() - t1;
  5245. //r3dOutToLog("FF update %f sec\n", t2);
  5246. }
  5247. const float curTime = r3dGetTime();
  5248.  
  5249. {
  5250. const float t1 = r3dGetTime();
  5251. #ifdef MISSIONS
  5252. // update mission data
  5253. {
  5254. static float nextTimeUpdateMissions = 0.0f;
  5255. if( Mission::g_pMissionMgr && curTime > nextTimeUpdateMissions )
  5256. {
  5257. nextTimeUpdateMissions = r3dGetTime() + 2.0f;
  5258. Mission::g_pMissionMgr->Update();
  5259. }
  5260. }
  5261. #endif
  5262. const float t2 = r3dGetTime() - t1;
  5263. //r3dOutToLog("mission update %f sec\n", t2);
  5264. }
  5265.  
  5266. {
  5267. const float t1 = r3dGetTime();
  5268. // send player status updates
  5269. {
  5270. static float nextTimeUpdatePlayerStatus = 0.0f;
  5271. if(curTime > nextTimeUpdatePlayerStatus)
  5272. {
  5273. nextTimeUpdatePlayerStatus = r3dGetTime() + 30.0f;
  5274. // go through all players, and send info to them about players that are in the same group\clan as them
  5275. for(int i=0; i<curPlayers_; ++i)
  5276. {
  5277. obj_ServerPlayer* srcPlr = plrList_[i];
  5278.  
  5279. for(int k=0; k<curPlayers_; ++k)
  5280. {
  5281. obj_ServerPlayer* pl = plrList_[k];
  5282. if(pl!=srcPlr && ((pl->groupID==srcPlr->groupID && pl->groupID!=0) || (pl->loadout_->ClanID==srcPlr->loadout_->ClanID && pl->loadout_->ClanID!=0)))
  5283. {
  5284. if(!(pl->profile_.ProfileData.isDevAccount & wiUserProfile::DAA_HIDDEN))
  5285. {
  5286. PKT_S2C_PlayerStatusUpdate_s n;
  5287. n.playerIdx = (WORD)(pl->GetNetworkID() - NETID_PLAYERS_START);
  5288. n.posX = pl->GetPosition().x;
  5289. n.posZ = pl->GetPosition().z;
  5290. p2pSendToPeer(srcPlr->peerId_, srcPlr, &n, sizeof(n));
  5291. }
  5292. }
  5293. }
  5294. }
  5295.  
  5296. }
  5297. }
  5298. const float t2 = r3dGetTime() - t1;
  5299. //r3dOutToLog("player status update %f sec\n", t2);
  5300. }
  5301.  
  5302.  
  5303. {
  5304. const float t1 = r3dGetTime();
  5305. // update spawn points danger indicator
  5306. {
  5307. static float nextTimeUpdateSpawnPointsDanger = 0.0f;
  5308. if(curTime > nextTimeUpdateSpawnPointsDanger)
  5309. {
  5310. nextTimeUpdateSpawnPointsDanger = r3dGetTime() + 60.0f; // once a minute
  5311.  
  5312. for(int i=0; i<gCPMgr.numControlPoints_; i++)
  5313. {
  5314. BasePlayerSpawnPoint* spawn = gCPMgr.controlPoints_[i];
  5315. for(int j=0; j<spawn->m_NumSpawnPoints; j++)
  5316. {
  5317. if(spawn->m_SpawnPoints[j].danger>0)
  5318. {
  5319. if(curTime > (spawn->m_SpawnPoints[j].lastTimeDangerUpdated+900))
  5320. {
  5321. spawn->m_SpawnPoints[j].danger--;
  5322. spawn->m_SpawnPoints[j].lastTimeDangerUpdated = curTime;
  5323. }
  5324. }
  5325. }
  5326. }
  5327. }
  5328. }
  5329. const float t2 = r3dGetTime() - t1;
  5330. //r3dOutToLog("spawn point update %f sec\n", t2);
  5331. }
  5332.  
  5333. // shutdown notify logic
  5334. if(gMasterServerLogic.shuttingDown_)
  5335. {
  5336. if(curPeersConnected == 0)
  5337. {
  5338. r3dOutToLog("Shutting down gracefully\n");
  5339. gameFinished_ = 1;
  5340. return;
  5341. }
  5342.  
  5343. static float lastSent = 999999;
  5344. // send note every X sec
  5345. float sentEachSec=1.0f;
  5346. if(gMasterServerLogic.shutdownLeft_ > 60)
  5347. sentEachSec = 15.0f; //send every 15 sec to prevent spam
  5348. else
  5349. sentEachSec = 5.0f; // send every 5 sec
  5350.  
  5351. if(fabs(lastSent - gMasterServerLogic.shutdownLeft_) > sentEachSec)
  5352. {
  5353. lastSent = gMasterServerLogic.shutdownLeft_;
  5354. r3dOutToLog("sent shutdown note\n");
  5355.  
  5356. PKT_S2C_ShutdownNote_s n;
  5357. n.reason = gMasterServerLogic.shuttingDown_;
  5358. n.timeLeft = gMasterServerLogic.shutdownLeft_;
  5359. p2pBroadcastToAll(&n, sizeof(n), true);
  5360. }
  5361.  
  5362. // close game when shutdown
  5363. if(gMasterServerLogic.shutdownLeft_ < 0)
  5364. throw "shutting down....";
  5365. }
  5366.  
  5367. {
  5368. const float t1 = r3dGetTime();
  5369. CheckPeerValidity();
  5370. const float t2 = r3dGetTime() - t1;
  5371. //r3dOutToLog("peer valid update %f sec\n", t2);
  5372. }
  5373.  
  5374. {
  5375. const float t1 = r3dGetTime();
  5376. g_AsyncApiMgr->Tick();
  5377. const float t2 = r3dGetTime() - t1;
  5378. //r3dOutToLog("async manager update %f sec\n", t2);
  5379. }
  5380.  
  5381. if(gameFinished_)
  5382. return;
  5383.  
  5384. // AUTOMATIC AIRDROP ON SERVER
  5385. if(ginfo_.IsGameBR() && m_isGameHasStarted)//
  5386. {
  5387. if (AirDropsPos.size()>0)
  5388. {
  5389. if(r3dGetTime() > AirDropSpawnTime)
  5390. {
  5391. AirDropSpawnTime = r3dGetTime() + RESPAWN_TIME_AIRDROPBR;
  5392.  
  5393. wiInventoryItem wi;
  5394. wi.itemID = 'ARDR';
  5395. wi.quantity = 1;
  5396.  
  5397. // create network object
  5398. r3dPoint3D AirDropSpawn(0,0,0);
  5399.  
  5400. if (Terrain3)
  5401. {
  5402. AirDropSpawn.y = Terrain3->GetHeight(AirDropSpawn)+300.0f;
  5403. }
  5404.  
  5405. uint32_t AirDropRand = 1;
  5406.  
  5407. if (AirDropsPos.size()>1)
  5408. {
  5409. AirDropRand = rand() % AirDropsPos.size()+1;
  5410. }
  5411.  
  5412. AirDropSpawn.x = AirDropsPos[AirDropRand].m_location.x + u_GetRandom(-AirDropsPos[AirDropRand].m_radius,AirDropsPos[AirDropRand].m_radius);
  5413. AirDropSpawn.z = AirDropsPos[AirDropRand].m_location.z+ + u_GetRandom(-AirDropsPos[AirDropRand].m_radius,AirDropsPos[AirDropRand].m_radius);
  5414.  
  5415. obj_DroppedItem* obj = (obj_DroppedItem*)srv_CreateGameObject("obj_DroppedItem", "obj_DroppedItem", AirDropSpawn);
  5416. obj->AirDropPos = AirDropSpawn;
  5417. obj->m_FirstTime = 1;
  5418. obj->ExpireFirstTime= r3dGetTime() + 5.0f;
  5419. obj->SetPosition(AirDropSpawn);
  5420. obj->SetNetworkID(gServerLogic.GetFreeNetId());
  5421. obj->NetworkLocal = true;
  5422. // vars
  5423. obj->m_Item = wi;
  5424. obj->m_Item.quantity = 1;
  5425.  
  5426. char msg[512]="";
  5427. sprintf(msg,"Spawned, the next Spawn is on 5 minutes");
  5428. PKT_C2C_ChatMessage_s n;
  5429. n.userFlag = 0;
  5430. n.msgChannel = 1;
  5431. r3dscpy(n.msg, msg);
  5432. r3dscpy(n.gamertag, "[AIRDROP]");
  5433. p2pBroadcastToAll(&n, sizeof(n), true);
  5434. }
  5435. }
  5436. }
  5437. /*else if(!ginfo_.IsGameBR())
  5438. {
  5439. if (AirDropsPos.size()>0)
  5440. {
  5441. if(r3dGetTime() > AirDropSpawnTime)
  5442. {
  5443. AirDropSpawnTime = r3dGetTime() + RESPAWN_TIME_AIRDROP;
  5444.  
  5445. wiInventoryItem wi;
  5446. wi.itemID = 'ARDR';
  5447. wi.quantity = 1;
  5448.  
  5449. // create network object
  5450. r3dPoint3D AirDropSpawn(0,0,0);
  5451.  
  5452. if (Terrain3)
  5453. {
  5454. AirDropSpawn.y = Terrain3->GetHeight(AirDropSpawn)+300.0f;
  5455. }
  5456.  
  5457. uint32_t AirDropRand = 1;
  5458.  
  5459. if (AirDropsPos.size()>1)
  5460. {
  5461. AirDropRand = rand() % AirDropsPos.size()+1;
  5462. }
  5463.  
  5464. AirDropSpawn.x = AirDropsPos[AirDropRand].m_location.x + u_GetRandom(-AirDropsPos[AirDropRand].m_radius,AirDropsPos[AirDropRand].m_radius);
  5465. AirDropSpawn.z = AirDropsPos[AirDropRand].m_location.z+ + u_GetRandom(-AirDropsPos[AirDropRand].m_radius,AirDropsPos[AirDropRand].m_radius);
  5466.  
  5467. obj_DroppedItem* obj = (obj_DroppedItem*)srv_CreateGameObject("obj_DroppedItem", "obj_DroppedItem", AirDropSpawn);
  5468. obj->AirDropPos = AirDropSpawn;
  5469. obj->m_FirstTime = 1;
  5470. obj->ExpireFirstTime= r3dGetTime() + 5.0f;
  5471. obj->SetPosition(AirDropSpawn);
  5472. obj->SetNetworkID(gServerLogic.GetFreeNetId());
  5473. obj->NetworkLocal = true;
  5474. // vars
  5475. obj->m_Item = wi;
  5476. obj->m_Item.quantity = 1;
  5477.  
  5478. char msg[512]="";
  5479. sprintf(msg,"Spawned, the next Spawn is on 4 hours");
  5480. PKT_C2C_ChatMessage_s n;
  5481. n.userFlag = 0;
  5482. n.msgChannel = 1;
  5483. r3dscpy(n.msg, msg);
  5484. r3dscpy(n.gamertag, "[AIRDROP]");
  5485. p2pBroadcastToAll(&n, sizeof(n), true);
  5486. }
  5487. }
  5488. }*/
  5489.  
  5490. /*DISABLED, as it complicate things a bit.
  5491. if(gMasterServerLogic.gotWeaponUpdate_)
  5492. {
  5493. gMasterServerLogic.gotWeaponUpdate_ = false;
  5494.  
  5495. weaponDataUpdates_++;
  5496. SendWeaponsInfoToPlayer(true, 0);
  5497. }*/
  5498.  
  5499. if(gMasterServerLogic.kickReqCharID_)
  5500. {
  5501. DWORD CharID = gMasterServerLogic.kickReqCharID_;
  5502. gMasterServerLogic.kickReqCharID_ = 0;
  5503.  
  5504. for(int i=0; i<curPlayers_; i++)
  5505. {
  5506. obj_ServerPlayer* plr = plrList_[i];
  5507. if(plr->loadout_->LoadoutID == CharID)
  5508. {
  5509. if(plr->profile_.ProfileData.isDevAccount == 0) // do not kick admins
  5510. DisconnectPeer(plr->peerId_, false, "kicked by server owner");
  5511. break;
  5512. }
  5513. }
  5514. }
  5515.  
  5516. // check for jobs overflow
  5517. {
  5518. static float lastReport = -999;
  5519. static int JOBS_THRESHOLD_TO_REPORT = 200;
  5520.  
  5521. int jobs = g_AsyncApiMgr->GetActiveJobs();
  5522. if(jobs > JOBS_THRESHOLD_TO_REPORT && curTime > lastReport + 60.0f)
  5523. {
  5524. lastReport = curTime;
  5525. r3dOutToLog("!!! warning: JobsOverflow: %d\n", jobs);
  5526.  
  5527. AsyncJobAddServerLogInfo(PKT_S2C_CheatWarning_s::CHEAT_Jobs, 0, 0,
  5528. "JobsOverflow", "n: %d",
  5529. jobs);
  5530.  
  5531. g_AsyncApiMgr->DumpJobs();
  5532. return;
  5533. }
  5534. }
  5535.  
  5536. // debug keys
  5537. static float lastKeyPress = -999;
  5538. if(curTime > lastKeyPress + 0.3f)
  5539. {
  5540. //@@@ kill all players
  5541. /*if(GetAsyncKeyState(VK_F11) & 0x8000)
  5542. {
  5543. lastKeyPress = curTime;
  5544.  
  5545. r3dOutToLog("trying to kill all players\n");
  5546. for(int i=0; i<curPlayers_; i++) {
  5547. obj_ServerPlayer* plr = plrList_[i];
  5548. if(plr->loadout_->Alive == 0)
  5549. continue;
  5550.  
  5551. DoKillPlayer(plr, plr, storecat_INVALID, true);
  5552. }
  5553. }*/
  5554.  
  5555. if(GetAsyncKeyState(VK_F12) & 0x8000)
  5556. {
  5557. lastKeyPress = curTime;
  5558. }
  5559. }
  5560.  
  5561. //CheckBattleZone();//
  5562.  
  5563. {
  5564. const float t1 = r3dGetTime();
  5565. // pereodically update loot box content
  5566. if(curTime > nextLootboxUpdate_)
  5567. {
  5568. nextLootboxUpdate_ = curTime + u_GetRandom(10*60, 15*60); // spread lootbox update a bit across all servers
  5569. g_AsyncApiMgr->AddJob(new CJobGetLootboxData());
  5570. }
  5571. const float t2 = r3dGetTime() - t1;
  5572. //r3dOutToLog("loot update %f sec\n", t2);
  5573. }
  5574.  
  5575. {
  5576. const float t1 = r3dGetTime();
  5577. // hibernate logic
  5578. UpdateHibernate();
  5579. const float t2 = r3dGetTime() - t1;
  5580. //r3dOutToLog("hiber update %f sec\n", t2);
  5581. }
  5582.  
  5583. static float nextDebugLog_ = 0;
  5584. if(curTime > nextDebugLog_)
  5585. {
  5586. char apiStatus[128];
  5587. g_AsyncApiMgr->GetStatus(apiStatus);
  5588.  
  5589. nextDebugLog_ = curTime + 60.0f;
  5590. r3dOutToLog("time: %.0f, plrs:%d/%d, net_lastFreeId: %d, objects: %d, async:%s\n",
  5591. r3dGetTime() - gameStartTime_,
  5592. curPlayers_, ginfo_.maxPlayers,
  5593. net_lastFreeId,
  5594. GameWorld().GetNumObjects(),
  5595. apiStatus);
  5596.  
  5597. //
  5598. if(ginfo_.IsGameBR() && curPeersConnected == 0)// reset all stats if no players
  5599. {
  5600. m_isGameHasStarted = false;
  5601. ForceStarGame = false;
  5602. isCountingDown = false;
  5603. canFinishMatch = false;
  5604. haveWinningPlayer = false;
  5605. playersTeleported = false;
  5606. isGasSuspended = true;
  5607. winningPlr = NULL;
  5608. suspendTimer = 0;
  5609. gasint = 0;
  5610. canCheckPlayers = r3dGetTime();
  5611. gastimer = r3dGetTime();
  5612. SetNewGameInfo(60, 0);
  5613. ResetGasAreaBattleRoyale();// reset gas radius to default
  5614. r3dOutToLog("[BattleRoyale] -- Match stats resetted.\n");
  5615. }
  5616. }
  5617.  
  5618. return;
  5619. }
  5620.  
  5621. void ServerGameLogic::DumpPacketStatistics()
  5622. {
  5623. __int64 totsent = 0;
  5624. __int64 totrecv = 0;
  5625.  
  5626. for(int i=0; i<R3D_ARRAYSIZE(netRecvPktSize); i++) {
  5627. totsent += netSentPktSize[i];
  5628. totrecv += netRecvPktSize[i];
  5629. }
  5630.  
  5631. r3dOutToLog("Packet Statistics: out:%I64d in:%I64d, k:%f\n", totsent, totrecv, (float)totsent/(float)totrecv);
  5632. CLOG_INDENT;
  5633.  
  5634. for(int i=0; i<R3D_ARRAYSIZE(netRecvPktSize); i++) {
  5635. if(netSentPktSize[i] == 0 && netRecvPktSize[i] == 0)
  5636. continue;
  5637.  
  5638. r3dOutToLog("%3d: out:%10I64d in:%10I64d out%%:%.1f%%\n",
  5639. i,
  5640. netSentPktSize[i],
  5641. netRecvPktSize[i],
  5642. (float)netSentPktSize[i] * 100.0f / float(totsent));
  5643. }
  5644.  
  5645. }
  5646.  
  5647. __int64 ServerGameLogic::GetUtcGameTime()
  5648. {
  5649. // "world time start" offset, so gametime at 1st sep 2012 will be in 2018 range
  5650. struct tm toff = {0};
  5651. toff.tm_year = 2011-1900;
  5652. toff.tm_mon = 6;
  5653. toff.tm_mday = 1;
  5654. toff.tm_isdst = -1; // A value less than zero to have the C run-time library code compute whether standard time or daylight saving time is in effect.
  5655. __int64 secs0 = _mkgmtime64(&toff); // world start time
  5656. __int64 secs1 = _time64(&secs1); // current UTC time
  5657.  
  5658. // reassemble time, with speedup factor
  5659. return secs0 + (secs1 - secs0) * (__int64)GPP_Data.c_iGameTimeCompression + gameStartTimeAdminOffset;
  5660. }
  5661.  
  5662. void ServerGameLogic::SendWeaponsInfoToPlayer(DWORD peerId)
  5663. {
  5664. //r3dOutToLog("sending weapon info to peer %d\n", peerId);
  5665.  
  5666. const peerInfo_s& peer = GetPeer(peerId);
  5667.  
  5668. g_pWeaponArmory->startItemSearch();
  5669. while(g_pWeaponArmory->searchNextItem())
  5670. {
  5671. uint32_t itemID = g_pWeaponArmory->getCurrentSearchItemID();
  5672. const WeaponConfig* weaponConfig = g_pWeaponArmory->getWeaponConfig(itemID);
  5673. if(weaponConfig)
  5674. {
  5675. PKT_S2C_UpdateWeaponData_s n;
  5676. n.itemId = weaponConfig->m_itemID;
  5677. weaponConfig->copyParametersTo(n.wi);
  5678. p2pSendRawToPeer(peerId, &n, sizeof(n), true);
  5679. }
  5680.  
  5681. const WeaponAttachmentConfig* attmConfig = g_pWeaponArmory->getAttachmentConfig(itemID);
  5682. if(attmConfig)
  5683. {
  5684. PKT_S2C_UpdateAttmData_s n;
  5685. n.itemId = attmConfig->m_itemID;
  5686. attmConfig->copyParametersTo(n.ai);
  5687. p2pSendRawToPeer(peerId, &n, sizeof(n), true);
  5688. }
  5689.  
  5690. const GearConfig* gearConfig = g_pWeaponArmory->getGearConfig(itemID);
  5691. if(gearConfig)
  5692. {
  5693. PKT_S2C_UpdateGearData_s n;
  5694. n.itemId = gearConfig->m_itemID;
  5695. gearConfig->copyParametersTo(n.gi);
  5696. p2pSendRawToPeer(peerId, &n, sizeof(n), true);
  5697. }
  5698. }
  5699.  
  5700. return;
  5701. }
  5702.  
  5703. uint32_t ServerGameLogic::getNumPlayersInGroup(uint32_t groupID)
  5704. {
  5705. r3d_assert(groupID);
  5706.  
  5707. uint32_t numPl = 0;
  5708. for(int i=0; i<curPlayers_; ++i)
  5709. {
  5710. obj_ServerPlayer* pl = plrList_[i];
  5711. if(pl->groupID == groupID)
  5712. {
  5713. ++numPl;
  5714. }
  5715. }
  5716. return numPl;
  5717. }
  5718.  
  5719. void ServerGameLogic::joinPlayerToGroup(obj_ServerPlayer* plr, uint32_t groupID)
  5720. {
  5721. r3d_assert(plr);
  5722. r3d_assert(groupID);
  5723. r3d_assert(plr->groupID==0);
  5724.  
  5725. PKT_S2C_GroupAddMember_s n2;
  5726. n2.groupID = groupID;
  5727. n2.isLeader = 0;
  5728. r3dscpy(n2.gamertag, plr->userName);
  5729.  
  5730. for(int i=0; i<curPlayers_; ++i)
  5731. {
  5732. obj_ServerPlayer* pl = plrList_[i];
  5733. if(pl->groupID == groupID)
  5734. {
  5735. // send current group info to new member
  5736. PKT_S2C_GroupAddMember_s n;
  5737. n.groupID = groupID;
  5738. n.isLeader = pl->isGroupLeader?1:0;
  5739. r3dscpy(n.gamertag, pl->userName);
  5740. p2pSendToPeer(plr->peerId_, plr, &n, sizeof(n));
  5741.  
  5742. // send new member to the group
  5743. p2pSendToPeer(pl->peerId_, pl, &n2, sizeof(n2));
  5744. }
  5745. }
  5746.  
  5747. plr->groupID = groupID;
  5748. plr->isGroupLeader = false;
  5749. // send yourself info about us being in new group
  5750. p2pSendToPeer(plr->peerId_, plr, &n2, sizeof(n2));
  5751.  
  5752. cleanPlayerGroupInvites(plr); // remove any invites that he had
  5753. }
  5754.  
  5755. void ServerGameLogic::createNewPlayerGroup(obj_ServerPlayer* leader, obj_ServerPlayer* plr, uint32_t groupID)
  5756. {
  5757. r3d_assert(leader);
  5758. r3d_assert(plr);
  5759. r3d_assert(plr->groupID==0);
  5760. r3d_assert(leader->groupID==0);
  5761. r3d_assert(groupID);
  5762.  
  5763. leader->groupID = groupID;
  5764. leader->isGroupLeader = true;
  5765.  
  5766. plr->groupID = groupID;
  5767. plr->isGroupLeader = false;
  5768.  
  5769. cleanPlayerGroupInvites(plr); // remove any outstanding invites from other player
  5770.  
  5771. // send into to each other
  5772. PKT_S2C_GroupAddMember_s n;
  5773. n.groupID = groupID;
  5774. n.isLeader = 1;
  5775. r3dscpy(n.gamertag, leader->userName);
  5776. p2pSendToPeer(leader->peerId_, leader, &n, sizeof(n));
  5777. p2pSendToPeer(plr->peerId_, plr, &n, sizeof(n));
  5778.  
  5779. n.isLeader = 0;
  5780. r3dscpy(n.gamertag, plr->userName);
  5781. p2pSendToPeer(leader->peerId_, leader, &n, sizeof(n));
  5782. p2pSendToPeer(plr->peerId_, plr, &n, sizeof(n));
  5783. }
  5784.  
  5785. bool ServerGameLogic::SetAirDrop( const AirDropPositions& AirDrop )
  5786. {
  5787. AirDropsPos[ AirDropsPos.size() + 1 ] = AirDrop;
  5788. r3dOutToLog("AirDropSystem - DB Spawn Number: %d\n",AirDropsPos.size());
  5789. return true;
  5790. }
  5791.  
  5792. void ServerGameLogic::leavePlayerFromGroup(obj_ServerPlayer* plr)
  5793. {
  5794. r3d_assert(plr);
  5795.  
  5796. plr->m_LeaveGroupAtTime = -1;
  5797.  
  5798. if(plr->groupID == 0) // not sure how it happens
  5799. {
  5800. return;
  5801. }
  5802.  
  5803. uint32_t curNumPlInGroup = getNumPlayersInGroup(plr->groupID);
  5804. r3d_assert(curNumPlInGroup>=2); // group should only exist with at least two players in it
  5805.  
  5806. bool deleteGroup = curNumPlInGroup == 2; // if in group of two someone leaves, then group deletes itself
  5807. bool reassignLeader = !deleteGroup && plr->isGroupLeader;
  5808.  
  5809. // remove everyone from group for plr
  5810. for(int i=0; i<curPlayers_; ++i)
  5811. {
  5812. obj_ServerPlayer* pl = plrList_[i];
  5813. if(pl->groupID == plr->groupID)
  5814. {
  5815. PKT_S2C_GroupRemoveMember_s n;
  5816. r3dscpy(n.gamertag, pl->userName);
  5817. p2pSendToPeer(plr->peerId_, plr, &n, sizeof(n));
  5818. }
  5819. }
  5820. uint32_t groupID = plr->groupID;
  5821. plr->groupID = 0;
  5822. plr->isGroupLeader = false;
  5823. PKT_S2C_GroupRemoveMember_s n;
  5824. r3dscpy(n.gamertag, plr->userName);
  5825.  
  5826. // now remove that player for rest of the group
  5827. for(int i=0; i<curPlayers_; ++i)
  5828. {
  5829. obj_ServerPlayer* pl = plrList_[i];
  5830. if(pl->groupID == groupID)
  5831. {
  5832. p2pSendToPeer(pl->peerId_, pl, &n, sizeof(n));
  5833. if(deleteGroup)
  5834. {
  5835. pl->groupID = 0;
  5836. pl->isGroupLeader = false;
  5837. PKT_S2C_GroupRemoveMember_s n2;
  5838. r3dscpy(n2.gamertag, pl->userName);
  5839. p2pSendToPeer(pl->peerId_, pl, &n2, sizeof(n2));
  5840. }
  5841. }
  5842. }
  5843.  
  5844. // also remove any outstanding invites
  5845. cleanPlayerGroupInvites(plr);
  5846.  
  5847. if(reassignLeader)
  5848. {
  5849. PKT_S2C_GroupNewLeader_s n2;
  5850. for(int i=0; i<curPlayers_; ++i)
  5851. {
  5852. obj_ServerPlayer* pl = plrList_[i];
  5853. if(pl && pl->groupID == groupID)
  5854. {
  5855. if(reassignLeader)
  5856. {
  5857. // assign leadership to first player in the list
  5858. r3d_assert(pl->isGroupLeader==false);
  5859. pl->isGroupLeader = true;
  5860. r3dscpy(n2.gamertag, pl->userName);
  5861. reassignLeader = false;
  5862. }
  5863. p2pSendToPeer(pl->peerId_, pl, &n2, sizeof(n2));
  5864. }
  5865. }
  5866. }
  5867. }
  5868.  
  5869. void ServerGameLogic::cleanPlayerGroupInvites(obj_ServerPlayer* plr)
  5870. {
  5871. // remove player invites from other players
  5872. {
  5873. for(int i=0; i<curPlayers_; ++i)
  5874. {
  5875. obj_ServerPlayer* pl = plrList_[i];
  5876. if(pl!=plr)
  5877. {
  5878. // look for invite from plr
  5879. std::vector<obj_ServerPlayer::GroupInviteStruct>::iterator it;
  5880. for(it=pl->groupInvitesFrom.begin(); it!=pl->groupInvitesFrom.end(); )
  5881. {
  5882. if(it->fromID == plr->GetNetworkID())
  5883. {
  5884. it = pl->groupInvitesFrom.erase(it);
  5885. continue;
  5886. }
  5887. ++it;
  5888. }
  5889. }
  5890. }
  5891. }
  5892. }
  5893.  
  5894. void ServerGameLogic::PreloadDevEventLoadout()
  5895. {
  5896. devEventItemsCount = 0;
  5897. devEventBackpackId = 0;
  5898.  
  5899. const char* xmlPath = "Data\\Weapons\\DevEventLoadout.xml";
  5900.  
  5901. r3dFile* file = r3d_open(xmlPath, "rb");
  5902. if (!file)
  5903. {
  5904. r3dOutToLog("Failed to open Dev Event Loadout configuration file: %s\n", xmlPath);
  5905. return;
  5906. }
  5907.  
  5908. char* buffer = game_new char[file->size + 1];
  5909. fread(buffer, file->size, 1, file);
  5910. buffer[file->size] = 0;
  5911.  
  5912. pugi::xml_document xmlDoc;
  5913. pugi::xml_parse_result parseResult = xmlDoc.load_buffer_inplace(buffer, file->size);
  5914. fclose(file);
  5915.  
  5916. if (!parseResult)
  5917. r3dError("Failed to parse Dev Event Loadout XML file, error: %s", parseResult.description());
  5918.  
  5919. pugi::xml_node loadout = xmlDoc.child("loadout");
  5920. devEventBackpackId = loadout.attribute("backpackId").as_int();
  5921.  
  5922. pugi::xml_node item = loadout.child("item");
  5923.  
  5924. devEventItemsCount = -1;
  5925. while (item)
  5926. {
  5927. wiInventoryItem tempItem;
  5928. tempItem.InventoryID = 0;
  5929. tempItem.itemID = item.attribute("id").as_uint();
  5930. tempItem.quantity = item.attribute("qty").as_int();
  5931. tempItem.Var2 = item.attribute("slot").as_int();
  5932.  
  5933. devEventItems[++devEventItemsCount] = tempItem;
  5934.  
  5935. item = item.next_sibling();
  5936. }
  5937.  
  5938. delete [] buffer;
  5939.  
  5940. r3dOutToLog("Dev Event Loadout configuration has been loaded with: %d items.\n", devEventItemsCount);
  5941. }
  5942.  
  5943. void ServerGameLogic::GiveDevEventLoadout(DWORD peerId)
  5944. {
  5945. peerInfo_s& peer = GetPeer(peerId);
  5946.  
  5947. // give player backpack
  5948. const BackpackConfig* cfg = g_pWeaponArmory->getBackpackConfig(devEventBackpackId);
  5949. if (cfg == NULL)
  5950. {
  5951. r3dOutToLog("The specified dev event backpack is not valid. itemId: %d\n", devEventBackpackId);
  5952. return;
  5953. }
  5954.  
  5955. peer.temp_profile.ProfileData.ArmorySlots[0].BackpackID = cfg->m_itemID;
  5956. peer.temp_profile.ProfileData.ArmorySlots[0].BackpackSize = cfg->m_maxSlots;
  5957.  
  5958. int useIndex = 0;
  5959. for (int i = 0; i < devEventItemsCount+1; ++i)
  5960. {
  5961. wiInventoryItem tempItem;
  5962. tempItem.InventoryID = useIndex+1;
  5963. tempItem.itemID = devEventItems[i].itemID;
  5964. tempItem.quantity = devEventItems[i].quantity;
  5965. tempItem.Var2 = 0;
  5966.  
  5967. if (devEventItems[i].Var2 == -1)
  5968. {
  5969. peer.temp_profile.ProfileData.ArmorySlots[0].Items[useIndex+8] = tempItem;
  5970. useIndex++;
  5971. }
  5972. else
  5973. peer.temp_profile.ProfileData.ArmorySlots[0].Items[devEventItems[i].Var2] = tempItem;
  5974. }
  5975. }
  5976.  
  5977. void ServerGameLogic::PreloadDevEventLoadoutSnipersMode()
  5978. {
  5979. devEventItemsCount2 = 0;
  5980. devEventBackpackId2 = 0;
  5981.  
  5982. const char* xmlPath2 = "Data\\Weapons\\DevEventLoadoutSnipersMode.xml";
  5983.  
  5984. r3dFile* file2 = r3d_open(xmlPath2, "rb");
  5985. if (!file2)
  5986. {
  5987. r3dOutToLog("Failed to open Dev Event Loadout Snipers Mode configuration file: %s\n", xmlPath2);
  5988. return;
  5989. }
  5990.  
  5991. char* buffer = game_new char[file2->size + 1];
  5992. fread(buffer, file2->size, 1, file2);
  5993. buffer[file2->size] = 0;
  5994.  
  5995. pugi::xml_document xmlDoc;
  5996. pugi::xml_parse_result parseResult = xmlDoc.load_buffer_inplace(buffer, file2->size);
  5997. fclose(file2);
  5998.  
  5999. if (!parseResult)
  6000. r3dError("Failed to parse Dev Event Loadout Snipers Mode XML file, error: %s", parseResult.description());
  6001.  
  6002. pugi::xml_node loadout = xmlDoc.child("loadout");
  6003. devEventBackpackId2 = loadout.attribute("backpackId").as_int();
  6004.  
  6005. pugi::xml_node item2 = loadout.child("item");
  6006.  
  6007. devEventItemsCount2 = -1;
  6008. while (item2)
  6009. {
  6010. wiInventoryItem tempItem;
  6011. tempItem.InventoryID = 0;
  6012. tempItem.itemID = item2.attribute("id").as_uint();
  6013. tempItem.quantity = item2.attribute("qty").as_int();
  6014. tempItem.Var2 = item2.attribute("slot").as_int();
  6015.  
  6016. devEventItems2[++devEventItemsCount2] = tempItem;
  6017.  
  6018. item2 = item2.next_sibling();
  6019. }
  6020.  
  6021. delete [] buffer;
  6022.  
  6023. r3dOutToLog("Dev Event Loadout Snipers Mode configuration has been loaded with: %d items.\n", devEventItemsCount2);
  6024. }
  6025.  
  6026. void ServerGameLogic::GiveDevEventLoadoutSnipersMode(DWORD peerId)
  6027. {
  6028. peerInfo_s& peer2 = GetPeer(peerId);
  6029.  
  6030. // give player backpack
  6031. const BackpackConfig* cfg = g_pWeaponArmory->getBackpackConfig(devEventBackpackId2);
  6032. if (cfg == NULL)
  6033. {
  6034. r3dOutToLog("The specified dev event Snipers Mode backpack is not valid. itemId: %d\n", devEventBackpackId2);
  6035. return;
  6036. }
  6037.  
  6038. peer2.temp_profile.ProfileData.ArmorySlots[0].BackpackID = cfg->m_itemID;
  6039. peer2.temp_profile.ProfileData.ArmorySlots[0].BackpackSize = cfg->m_maxSlots;
  6040.  
  6041. int useIndex = 0;
  6042. for (int i = 0; i < devEventItemsCount2+1; ++i)
  6043. {
  6044. wiInventoryItem tempItem;
  6045. tempItem.InventoryID = useIndex+1;
  6046. tempItem.itemID = devEventItems2[i].itemID;
  6047. tempItem.quantity = devEventItems2[i].quantity;
  6048. tempItem.Var2 = 0;
  6049.  
  6050. if (devEventItems2[i].Var2 == -1)
  6051. {
  6052. peer2.temp_profile.ProfileData.ArmorySlots[0].Items[useIndex+8] = tempItem;
  6053. useIndex++;
  6054. }
  6055. else
  6056. peer2.temp_profile.ProfileData.ArmorySlots[0].Items[devEventItems2[i].Var2] = tempItem;
  6057. }
  6058. }
  6059.  
  6060. void ServerGameLogic::PreloadDevEventLoadoutNoSnipersMode()
  6061. {
  6062. devEventItemsCount3 = 0;
  6063. devEventBackpackId3 = 0;
  6064.  
  6065. const char* xmlPath3 = "Data\\Weapons\\DevEventLoadoutNoSnipersMode.xml";
  6066.  
  6067. r3dFile* file3 = r3d_open(xmlPath3, "rb");
  6068. if (!file3)
  6069. {
  6070. r3dOutToLog("Failed to open Dev Event Loadout No Snipers Mode configuration file: %s\n", xmlPath3);
  6071. return;
  6072. }
  6073.  
  6074. char* buffer = game_new char[file3->size + 1];
  6075. fread(buffer, file3->size, 1, file3);
  6076. buffer[file3->size] = 0;
  6077.  
  6078. pugi::xml_document xmlDoc;
  6079. pugi::xml_parse_result parseResult = xmlDoc.load_buffer_inplace(buffer, file3->size);
  6080. fclose(file3);
  6081.  
  6082. if (!parseResult)
  6083. r3dError("Failed to parse Dev Event Loadout No Snipers Mode XML file, error: %s", parseResult.description());
  6084.  
  6085. pugi::xml_node loadout = xmlDoc.child("loadout");
  6086. devEventBackpackId3 = loadout.attribute("backpackId").as_int();
  6087.  
  6088. pugi::xml_node item3 = loadout.child("item");
  6089.  
  6090. devEventItemsCount3 = -1;
  6091. while (item3)
  6092. {
  6093. wiInventoryItem tempItem;
  6094. tempItem.InventoryID = 0;
  6095. tempItem.itemID = item3.attribute("id").as_uint();
  6096. tempItem.quantity = item3.attribute("qty").as_int();
  6097. tempItem.Var2 = item3.attribute("slot").as_int();
  6098.  
  6099. devEventItems3[++devEventItemsCount3] = tempItem;
  6100.  
  6101. item3 = item3.next_sibling();
  6102. }
  6103.  
  6104. delete[] buffer;
  6105.  
  6106. r3dOutToLog("Dev Event Loadout No Snipers Mode configuration has been loaded with: %d items.\n", devEventItemsCount3);
  6107. }
  6108.  
  6109. void ServerGameLogic::GiveDevEventLoadoutNoSnipersMode(DWORD peerId)
  6110. {
  6111. peerInfo_s& peer3 = GetPeer(peerId);
  6112.  
  6113. // give player backpack
  6114. const BackpackConfig* cfg = g_pWeaponArmory->getBackpackConfig(devEventBackpackId3);
  6115. if (cfg == NULL)
  6116. {
  6117. r3dOutToLog("The specified dev event No Snipers Mode backpack is not valid. itemId: %d\n", devEventBackpackId3);
  6118. return;
  6119. }
  6120.  
  6121. peer3.temp_profile.ProfileData.ArmorySlots[0].BackpackID = cfg->m_itemID;
  6122. peer3.temp_profile.ProfileData.ArmorySlots[0].BackpackSize = cfg->m_maxSlots;
  6123.  
  6124. int useIndex = 0;
  6125. for (int i = 0; i < devEventItemsCount3 + 1; ++i)
  6126. {
  6127. wiInventoryItem tempItem;
  6128. tempItem.InventoryID = useIndex + 1;
  6129. tempItem.itemID = devEventItems3[i].itemID;
  6130. tempItem.quantity = devEventItems3[i].quantity;
  6131. tempItem.Var2 = 0;
  6132.  
  6133. if (devEventItems3[i].Var2 == -1)
  6134. {
  6135. peer3.temp_profile.ProfileData.ArmorySlots[0].Items[useIndex + 8] = tempItem;
  6136. useIndex++;
  6137. }
  6138. else
  6139. peer3.temp_profile.ProfileData.ArmorySlots[0].Items[devEventItems3[i].Var2] = tempItem;
  6140. }
  6141. }
  6142.  
  6143. // // need debug all stuff
  6144. /*===============================================================================*/
  6145. bool isOccupied;
  6146. void ServerGameLogic::PreloadDevEventLoadoutBR()
  6147. {
  6148. BRItemsCount = 0;
  6149. BRBackpackId = 0;
  6150.  
  6151. const char* xmlPathBR = "Data\\Weapons\\DevEventLoadoutBR.xml";
  6152.  
  6153. r3dFile* file4 = r3d_open(xmlPathBR, "rb");
  6154. if (!file4)
  6155. {
  6156. r3dOutToLog("[BattleRoyale] -- Failed to open Loadout configuration file: %s\n", xmlPathBR);
  6157. return;
  6158. }
  6159.  
  6160. char* buffer = game_new char[file4->size + 1];
  6161. fread(buffer, file4->size, 1, file4);
  6162. buffer[file4->size] = 0;
  6163.  
  6164. pugi::xml_document xmlDoc;
  6165. pugi::xml_parse_result parseResult = xmlDoc.load_buffer_inplace(buffer, file4->size);
  6166. fclose(file4);
  6167.  
  6168. if (!parseResult)
  6169. r3dError("[BattleRoyale] -- Failed to parse Loadout XML file, error: %s", parseResult.description());
  6170.  
  6171. pugi::xml_node loadout = xmlDoc.child("loadout");
  6172. BRBackpackId = loadout.attribute("backpackId").as_int();
  6173.  
  6174. pugi::xml_node item4 = loadout.child("item");
  6175.  
  6176. BRItemsCount = -1;
  6177. while (item4)
  6178. {
  6179. wiInventoryItem tempItem;
  6180. tempItem.InventoryID = 0;
  6181. tempItem.itemID = item4.attribute("id").as_uint();
  6182. tempItem.quantity = item4.attribute("qty").as_int();
  6183. tempItem.Var2 = item4.attribute("slot").as_int();
  6184.  
  6185. BRItems[++BRItemsCount] = tempItem;
  6186.  
  6187. item4 = item4.next_sibling();
  6188. }
  6189.  
  6190. delete[] buffer;
  6191.  
  6192. r3dOutToLog("[BattleRoyale] -- Loadout configuration has been loaded with: %d items.\n", BRItemsCount);
  6193. }
  6194.  
  6195. void ServerGameLogic::GiveDevEventLoadoutBR(DWORD peerId)
  6196. {
  6197. peerInfo_s& peer = GetPeer(peerId);
  6198.  
  6199. // give player backpack
  6200. const BackpackConfig* cfg = g_pWeaponArmory->getBackpackConfig(BRBackpackId);
  6201. if (cfg == NULL)
  6202. {
  6203. r3dOutToLog("[BattleRoyale] -- The specified backpack is not valid. itemId: %d\n", BRBackpackId);
  6204. return;
  6205. }
  6206.  
  6207. peer.temp_profile.ProfileData.ArmorySlots[0].BackpackID = cfg->m_itemID;
  6208. peer.temp_profile.ProfileData.ArmorySlots[0].BackpackSize = cfg->m_maxSlots;
  6209.  
  6210. obj_ServerPlayer* plr = IsServerPlayer(GetPeer(peerId).player);
  6211. int useIndex = 0;
  6212. for (int i = 0; i < BRItemsCount + 1; ++i)
  6213. {
  6214. wiInventoryItem tempItem;
  6215. tempItem.InventoryID = useIndex + 1;
  6216. tempItem.itemID = BRItems[i].itemID;
  6217. tempItem.quantity = BRItems[i].quantity;
  6218. tempItem.Var2 = 0;
  6219.  
  6220. if (BRItems[i].Var2 == -1)
  6221. {
  6222. peer.temp_profile.ProfileData.ArmorySlots[0].Items[useIndex + 8] = tempItem;
  6223. useIndex++;
  6224. }
  6225. else
  6226. peer.temp_profile.ProfileData.ArmorySlots[0].Items[BRItems[i].Var2] = tempItem;
  6227. }
  6228. r3dOutToLog("[BattleRoyale] -- Loadout configuration has been added with: %d items.\n", BRItemsCount);
  6229. }
  6230.  
  6231. void ServerGameLogic::BattleRoyaleTick()
  6232. {
  6233. for (int i = 0; i < curPlayers_; i++)
  6234. {
  6235. obj_ServerPlayer* pl = plrList_[i];
  6236. if(curPlayers_ == ginfo_.maxPlayers && !isCountingDown && !m_isGameHasStarted)
  6237. {
  6238. r3dOutToLog("Minimum required players achieved, starting match\n");
  6239. StartCountdown();
  6240. }
  6241.  
  6242. if (isCountingDown)
  6243. {
  6244. float diff = preGameTime - r3dGetTime();
  6245. int iDiff = (int)diff; // Time left util we start the game
  6246. if (/*iDiff == 60 || iDiff == 30 || iDiff == 15 ||*/ iDiff <= 5)
  6247. {
  6248. // Chat message to all players
  6249. if (diff > 1)
  6250. {
  6251. if (lastNumber != iDiff) // Check so that we send this message once every second
  6252. {
  6253. // Tell the players how much time we have left before we start the match
  6254. PKT_C2C_ChatMessage_s n2;
  6255. n2.msgChannel = 1; // global
  6256. n2.userFlag = 200; // battle royale
  6257. r3dscpy(n2.gamertag, "<BattleRoyale>");
  6258. char buffer[64];
  6259. sprintf_s(buffer, "Battle Royale will start in %i!", iDiff);
  6260. r3dscpy(n2.msg, buffer);
  6261. p2pBroadcastToAll(&n2, sizeof(n2), 1);
  6262. lastNumber = iDiff;
  6263. }
  6264. }
  6265. else if (iDiff == 0) // If the time left to start the match is smaller than or equal to 0
  6266. {
  6267. // We start the match
  6268. StartMatch();
  6269.  
  6270. // And send a message to all players that the match has started
  6271. PKT_C2C_ChatMessage_s n2;
  6272. n2.msgChannel = 1; // global
  6273. n2.userFlag = 200; // battle royale
  6274. r3dscpy(n2.gamertag, "<BattleRoyale>");
  6275. char buffer[64];
  6276. sprintf_s(buffer, "The Battle Royale has started, good luck!", diff);
  6277. r3dscpy(n2.msg, buffer);
  6278. p2pBroadcastToAll(&n2, sizeof(n2), 1);
  6279. }
  6280. }
  6281. }
  6282.  
  6283. // Check battle zone
  6284. if(!m_isGameHasStarted)
  6285. CheckBattleZone();//
  6286.  
  6287. // Gas scaner
  6288. if(m_isGameHasStarted && curPlayers_ > 0 && !isCountingDown && !haveWinningPlayer)
  6289. GasScanner();
  6290.  
  6291. //check winner
  6292. if (m_isGameHasStarted)
  6293. CheckBattleRoyaleWinner();
  6294.  
  6295. // we need reset all shit if match is finished
  6296. if (canFinishMatch && curPlayers_<1)
  6297. FinishMatch();
  6298. }
  6299. }
  6300.  
  6301. void ServerGameLogic::GetSpawnPositionBattleRoyale(const r3dPoint3D& GamePos, r3dPoint3D* pos, float* dir)
  6302. {
  6303. if(gCPMgr.numControlPoints_ == 0)
  6304. {
  6305. r3dError("!!!!!!!!!!!! THERE IS NO CONTROL POINT !!!!!!!\n");
  6306. *pos = r3dPoint3D(0, 0, 0);
  6307. *dir = 0;
  6308. return;
  6309. }
  6310.  
  6311. //Get random lobby spawn point
  6312. for(int i=0; i<gCPMgr.numControlPoints_; i++)
  6313. {
  6314. const BasePlayerSpawnPoint* spawn = gCPMgr.controlPoints_[i];
  6315. for(int j=0; j<spawn->m_NumSpawnPoints; j++)
  6316. {
  6317. int idx1 = u_random(j);// we need random spawn point
  6318. if(spawn->spawnType_!=1)//when player spawns first time, he spawns at those points
  6319. {
  6320. *pos = spawn->m_SpawnPoints[idx1].pos;
  6321. *dir = spawn->m_SpawnPoints[idx1].dir;
  6322. }
  6323. }
  6324. }
  6325.  
  6326. return;
  6327. }
  6328.  
  6329. void ServerGameLogic::ResetPositionBattleRoyale(obj_ServerPlayer* plr, int lbNum)// alex
  6330. {
  6331. //Get random lobby spawn point
  6332. r3dPoint3D pos;
  6333.  
  6334. for(int i=0; i<gCPMgr.numControlPoints_; i++)
  6335. {
  6336. const BasePlayerSpawnPoint* spawn = gCPMgr.controlPoints_[i];
  6337. for(int j=0; j<spawn->m_NumSpawnPoints; j++)
  6338. {
  6339. int idx1 = u_random(j);// we need random spawn point
  6340. if(spawn->spawnType_!=1)//when player spawns first time, he spawns at those points
  6341. pos = spawn->m_SpawnPoints[idx1].pos;
  6342. }
  6343. }
  6344. admin_TeleportPlayer(plr, pos.x, pos.z);
  6345. }
  6346. void ServerGameLogic::StartCountdown()
  6347. {
  6348. if(!gMasterServerLogic.shuttingDown_)// do not start match if server shutting down
  6349. {
  6350. isCountingDown = true;
  6351. ForceStarGame = false;
  6352. preGameTime = r3dGetTime() + 5.0f;
  6353. lastNumber = 0;
  6354. winningPlr = NULL;
  6355.  
  6356. //Report client about preparing for start the match
  6357. SetNewGameInfo(gServerLogic.ginfo_.flags |= GBGameInfo::SFLAGS_isAboutStartedBR, 0);
  6358. gMasterServerLogic.SetGameBRinfo(1);//send info about status to masterserver
  6359.  
  6360. PKT_C2C_ChatMessage_s n2;
  6361. n2.msgChannel = 1; // global
  6362. n2.userFlag = 200; // battle royale
  6363. r3dscpy(n2.gamertag, "<BattleRoyale>");
  6364. char buffer[64];
  6365. sprintf_s(buffer, "Battle Royale will start in 5 seconds");
  6366. r3dscpy(n2.msg, buffer);
  6367. p2pBroadcastToAll(&n2, sizeof(n2), 1);
  6368. r3dOutToLog("[BattleRoyale] -- Start counting down\n");
  6369. }
  6370. }
  6371.  
  6372. void ServerGameLogic::StartMatch()
  6373. {
  6374. isCountingDown = false;
  6375. m_isGameHasStarted = true;
  6376. gMasterServerLogic.SetGameBRinfo(1);//send info about status to masterserver
  6377. canFinishMatch = false;
  6378. bool DarSpawnProtection = false;
  6379. haveWinningPlayer = false;
  6380. isGasSuspended = true;
  6381. winningPlr = NULL;
  6382. suspendTimer = 0;
  6383. gasint = 0;
  6384. playersLeft = curPlayers_;
  6385. playersStarted = curPlayers_;
  6386. AirDropSpawnTime = r3dGetTime() + RESPAWN_TIME_AIRDROPBR;
  6387.  
  6388. // Set occupied false for all spawns
  6389. BasePlayerSpawnPoint* curSpawn;
  6390. int numSpawns = 0;
  6391.  
  6392. for (int i = 0; i < gCPMgr.numControlPoints_; i++)
  6393. {
  6394. curSpawn = gCPMgr.controlPoints_[i];
  6395. for (int j = 0; j < curSpawn->m_NumSpawnPoints; j++)
  6396. {
  6397. curSpawn->m_SpawnPoints[j].isOccupied = false;
  6398. numSpawns++;
  6399. }
  6400. }
  6401. r3dOutToLog("[BattleRoyale] -- Resetted %i spawns\n", numSpawns);
  6402.  
  6403. // Teleport players to their start positions
  6404. for (int i = 0; i < curPlayers_; ++i)
  6405. {
  6406. DarSpawnProtection = true;
  6407. obj_ServerPlayer* pl = plrList_[i];
  6408. pl->m_SpawnProtectedUntil = r3dGetTime() + 30.0f;
  6409. pl->loadout_->Health = 100.0f;
  6410. pl->loadout_->Hunger = 0.0f;
  6411. pl->loadout_->Thirst = 0.0f;
  6412. pl->loadout_->Toxic = 0.0f;
  6413. pl->loadout_->MedBleeding = 0.0f;
  6414. pl->loadout_->MedBloodInfection = 0.0f;
  6415. pl->m_Stamina = GPP_Data.c_fSprintMaxEnergy;
  6416. //GetStartPositionBattleRoyale(pl);
  6417. GetStartPositionBattleRoyale2(pl);
  6418. playersTeleported = true;
  6419. teleportTimer = r3dGetTime()+ 0.3f;//0.3f; // from 2.5
  6420. pl->GiveBattleRoyaleLoadout();//give loadout items
  6421. }
  6422.  
  6423. //Report client about already started the match
  6424. //@MrAcoustic: Just for tested.
  6425. //PKT_S2C_SetGameInfoFlags_s n;
  6426. //n.gameInfoFlags = ginfo_.flags |= GBGameInfo::SFLAGS_isStartedBR;
  6427. //p2pBroadcastToAll(&n, sizeof(n), true);
  6428. SetNewGameInfo(gServerLogic.ginfo_.flags |= GBGameInfo::SFLAGS_isStartedBR, 0);
  6429.  
  6430. //Get gas area radius
  6431. for (int l = 0; l < gGasAreaMngr.numGasArea_; l++)
  6432. {
  6433. obj_ServerGasArea* rbox = gGasAreaMngr.GasArea_[l];
  6434. // inform client about gas radius
  6435. PKT_S2C_SetGasRadius_s n;
  6436. n.gasRadius = rbox->useRadius;
  6437. n.gasStatus = 0;
  6438. isGasSuspended = true;
  6439. p2pBroadcastToAll(&n, sizeof(n));
  6440. break;
  6441. }
  6442. DestroyBarricadesBattleRoyale();// destroy all barricade // alex
  6443.  
  6444. r3dOutToLog("[BattleRoyale] -- Teleported and equipped %i players\n", curPlayers_);
  6445. r3dOutToLog("[BattleRoyale] -- The match has started!\n");
  6446. }
  6447.  
  6448. void ServerGameLogic::GetStartPositionBattleRoyale(obj_ServerPlayer* plr)
  6449. {
  6450. float posX, posZ;
  6451.  
  6452. // Right now we teleport players to the first empty spawn
  6453. BasePlayerSpawnPoint* curSpawn;
  6454.  
  6455. while (true)
  6456. {
  6457. srand((unsigned int)r3dGetTime());
  6458. int i = rand() % gCPMgr.numControlPoints_;
  6459. curSpawn = gCPMgr.controlPoints_[i];
  6460.  
  6461. int j = rand() % curSpawn->m_NumSpawnPoints;
  6462.  
  6463. if (!curSpawn->m_SpawnPoints[j].isOccupied)
  6464. {
  6465. curSpawn->m_SpawnPoints[j].isOccupied = true;
  6466. if(curSpawn->spawnType_!=0)// not spawn in lobby spawn points
  6467. {
  6468. posX = curSpawn->m_SpawnPoints[j].pos.x;
  6469. posZ = curSpawn->m_SpawnPoints[j].pos.z;
  6470. admin_TeleportPlayer(plr, posX, posZ);
  6471. break;
  6472. }
  6473. }
  6474. }
  6475. return;
  6476. }
  6477.  
  6478. void ServerGameLogic::GetStartPositionBattleRoyale2(obj_ServerPlayer* plr)
  6479. {
  6480. // Made by @MrAcoustic | Mr.Pakorn from TH xD.
  6481. r3dPoint3D pos;
  6482.  
  6483. for(int i=0; i<gCPMgr.numControlPoints_; i++)
  6484. {
  6485. const BasePlayerSpawnPoint* spawn = gCPMgr.controlPoints_[i];
  6486. for(int j=0; j<spawn->m_NumSpawnPoints; j++)
  6487. {
  6488. int idx1 = u_random(j);// we need random spawn point
  6489. if(spawn->spawnType_!=0)//when player spawns first time, he spawns at those points
  6490. pos = spawn->m_SpawnPoints[idx1].pos;
  6491. }
  6492. }
  6493. admin_TeleportPlayer(plr, pos.x, pos.z);
  6494. }
  6495.  
  6496.  
  6497.  
  6498. void ServerGameLogic::GasScanner()
  6499. {
  6500. const int timeToPrepare = 120;// 2 Minutes to start getting close before the Radiactive gas arrives
  6501.  
  6502. if (r3dGetTime() > gastimer)
  6503. {
  6504. if (m_isGameHasStarted && curPlayers_ > 0 && !haveWinningPlayer) // check for someone living
  6505. {
  6506. if(gasint == 0)
  6507. {
  6508. PKT_C2C_ChatMessage_s n2;
  6509. n2.msgChannel = 1; // global
  6510. n2.userFlag = 200; // battle royale
  6511. r3dscpy(n2.gamertag, "<BattleRoyale>");
  6512. char buffer[128];
  6513.  
  6514. sprintf_s(buffer, "The Safezone has been indicated on the map. You have 2 Minutes to start getting close before the Radiactive gas arrives.");
  6515. r3dscpy(n2.msg, buffer);
  6516. p2pBroadcastToAll(&n2, sizeof(n2));
  6517. }
  6518. else if(gasint == timeToPrepare)
  6519. {
  6520. PKT_C2C_ChatMessage_s n2;
  6521. n2.msgChannel = 1; // global
  6522. n2.userFlag = 200; // battle royale
  6523. r3dscpy(n2.gamertag, "<BattleRoyale>");
  6524. char buffer[64];
  6525. sprintf_s(buffer, "Radioactive gas released! Good Luck Survivors!");
  6526. r3dscpy(n2.msg, buffer);
  6527. p2pBroadcastToAll(&n2, sizeof(n2));
  6528. }
  6529.  
  6530. gasint++;
  6531. gastimer = r3dGetTime() + 1.0f;
  6532.  
  6533. if(gasint > timeToPrepare)
  6534. {
  6535. if(suspendTimer%30 == 0) // 30 + 60- 90+ 120-
  6536. {
  6537. isGasSuspended=!isGasSuspended;
  6538. ChangeGasAreaBattleRoyale();
  6539. }
  6540. suspendTimer++;
  6541.  
  6542. if(!isGasSuspended)
  6543. ChangeGasAreaBattleRoyale();
  6544. }
  6545. }
  6546. }
  6547. }
  6548.  
  6549. void ServerGameLogic::ChangeGasAreaBattleRoyale()
  6550. {
  6551. //Set new gas area radius
  6552. for (int l = 0; l < gGasAreaMngr.numGasArea_; l++)
  6553. {
  6554. obj_ServerGasArea* rbox = gGasAreaMngr.GasArea_[l];
  6555. if(rbox->useRadius>0)//Stop using the gas
  6556. {
  6557. if(!isGasSuspended)
  6558. rbox->useRadius -= 0.5f;// change radius
  6559.  
  6560. // inform client about changed gas radius
  6561. PKT_S2C_SetGasRadius_s n;
  6562. n.gasRadius = rbox->useRadius;
  6563. n.gasStatus = 1;
  6564. n.isGasSuspended = isGasSuspended;
  6565. p2pBroadcastToAll(&n, sizeof(n));
  6566. }
  6567. break;
  6568. }
  6569. }
  6570.  
  6571. void ServerGameLogic::ResetGasAreaBattleRoyale()
  6572. {
  6573. // Reset radius to default
  6574. float radius = 0;
  6575. for (int l = 0; l < gGasAreaMngr.numGasArea_; l++)
  6576. {
  6577. obj_ServerGasArea* rbox = gGasAreaMngr.GasArea_[l];
  6578. rbox->useRadius = rbox->defaultRadius;
  6579. radius = rbox->useRadius;
  6580. break;
  6581. }
  6582. //r3dOutToLog("[BattleRoyale] -- Gas area resetted! radius is : %.f\n", radius);
  6583. }
  6584.  
  6585. void ServerGameLogic::CheckBattleRoyaleWinner()
  6586. {
  6587. //scan alive players
  6588. int LivePlayers = 0;
  6589. int LiveID = 0;
  6590. for (GameObject* obj = GameWorld().GetFirstObject(); obj; obj = GameWorld().GetNextObject(obj))
  6591. {
  6592. if (obj->isObjType(OBJTYPE_Human))
  6593. {
  6594. obj_ServerPlayer* Player = (obj_ServerPlayer*)obj;
  6595. if (Player->loadout_->Alive > 0)
  6596. {
  6597. LivePlayers++;
  6598. LiveID = Player->GetNetworkID();
  6599. }
  6600. }
  6601. }
  6602.  
  6603. // detect winner player and give him GD bonus
  6604. if (LivePlayers == 1 && !haveWinningPlayer && m_isGameHasStarted)
  6605. {
  6606. winningPlr = (obj_ServerPlayer*)GameWorld().GetNetworkObject(LiveID);
  6607. if (winningPlr)
  6608. {
  6609. haveWinningPlayer = true;
  6610. winningPlr->profile_.ProfileData.GameDollars += rewardBR*playersStarted;
  6611. winningPlr->loadout_->Stats.VictorysBattleRoyale++;
  6612. ApiPlayerUpdateChar(winningPlr);
  6613. SetNewGameInfo(60, 0);
  6614.  
  6615. //add message to chat
  6616. char msg[512] = "";
  6617. sprintf(msg, "The winner is %s!!!\n and has won %d GD - Congratulations!", winningPlr->loadout_->Gamertag, rewardBR*playersStarted);
  6618. PKT_C2C_ChatMessage_s n;
  6619. n.userFlag = 200;// battle royale
  6620. n.msgChannel = 1;// global
  6621. r3dscpy(n.msg, msg);
  6622. r3dscpy(n.gamertag, "<BattleRoyale>");
  6623. p2pBroadcastToAll(&n, sizeof(n), true);
  6624.  
  6625. DoKillPlayer(winningPlr, winningPlr, storecat_INVALID, true);// we need kill winner player for finish match
  6626. canFinishMatch = true;
  6627.  
  6628. r3dOutToLog("[BattleRoyale] -- The winner is %s!!! he won %d GD\n", winningPlr->loadout_->Gamertag, rewardBR*playersStarted);
  6629. }
  6630. else
  6631. r3dOutToLog("[BattleRoyale] -- Something wrong happen WE NOT HAVE WINNER\n");
  6632. }
  6633. }
  6634.  
  6635. void ServerGameLogic::FinishMatch()
  6636. {
  6637. m_isGameHasStarted = false;
  6638. ForceStarGame = false;
  6639. isCountingDown = false;
  6640. canFinishMatch = false;
  6641. haveWinningPlayer = false;
  6642. playersTeleported = false;
  6643. isGasSuspended = true;
  6644. suspendTimer = 0;
  6645. winningPlr = NULL;
  6646. gasint = 0;
  6647. canCheckPlayers = r3dGetTime();
  6648. gastimer = r3dGetTime();
  6649. SetNewGameInfo(60, 0);
  6650. DestroyBarricadesBattleRoyale();// destroy all barricade
  6651. ReSpawnLootBattleRoyale(); //respawn all lootboxes
  6652. ResetGasAreaBattleRoyale();// reset gas radius to default
  6653. AirDropSpawnTime = r3dGetTime() + RESPAWN_TIME_AIRDROPBR;
  6654.  
  6655. r3dOutToLog("[BattleRoyale] -- Match is finished!\n");
  6656. }
  6657.  
  6658. void ServerGameLogic::DestroyBarricadesBattleRoyale()
  6659. {
  6660. //Destroy all barricades from BR map
  6661. for (GameObject* obj = GameWorld().GetFirstObject(); obj; obj = GameWorld().GetNextObject(obj))
  6662. {
  6663. if (obj->isObjType(OBJTYPE_Barricade))
  6664. {
  6665. obj_ServerBarricade* shield = (obj_ServerBarricade*)obj;
  6666. shield->DestroyBarricade();
  6667. }
  6668. }
  6669. r3dOutToLog("[BattleRoyale] -- barricades destroyed!\n");
  6670. }
  6671.  
  6672. void ServerGameLogic::ReSpawnLootBattleRoyale()
  6673. {
  6674. //Respawn loot from BR map
  6675. for (GameObject* obj = GameWorld().GetFirstObject(); obj; obj = GameWorld().GetNextObject(obj))
  6676. {
  6677. if (obj->isObjType(OBJTYPE_ItemSpawnPoint))
  6678. {
  6679. obj_ServerItemSpawnPoint* spawn = (obj_ServerItemSpawnPoint*)obj;
  6680. spawn->RespawnLootBattleRoyale();
  6681. }
  6682. }
  6683. r3dOutToLog("[BattleRoyale] -- Dropped item removed!\n");// log from obj_DroppedItem::Update()
  6684. r3dOutToLog("[BattleRoyale] -- loot respawned!\n");
  6685. }
  6686.  
  6687. void ServerGameLogic::RespawnPlayer(obj_ServerPlayer* plr)
  6688. {
  6689. //Get random respawn point
  6690. r3dPoint3D pos;
  6691. float dir;
  6692. if(ginfo_.IsGameBR())//BR MODE
  6693. {
  6694. for(int i=0; i<gCPMgr.numControlPoints_; i++)
  6695. {
  6696. const BasePlayerSpawnPoint* spawn = gCPMgr.controlPoints_[i];
  6697. if(spawn->spawnType_!=1)//when player spawns first time, he spawns at those points
  6698. {
  6699. for(int j=0; j<spawn->m_NumSpawnPoints; j++)
  6700. {
  6701. int idx1 = u_random(j);// get random spawn point
  6702. pos = spawn->m_SpawnPoints[idx1].pos;
  6703. dir = spawn->m_SpawnPoints[idx1].dir;
  6704. }
  6705. }
  6706. }
  6707. }
  6708. else if(ginfo_.channel==6)//DEV EVENT MODE
  6709. {
  6710. for(int i=0; i<gCPMgr.numControlPoints_; i++)
  6711. {
  6712. int idx = u_random(i);// get random control point
  6713. const BasePlayerSpawnPoint* spawn = gCPMgr.controlPoints_[idx];
  6714. for(int j=0; j<spawn->m_NumSpawnPoints; j++)
  6715. {
  6716. int idx1 = u_random(j);// get random spawn point
  6717. pos = spawn->m_SpawnPoints[idx1].pos;
  6718. dir = spawn->m_SpawnPoints[idx1].dir;
  6719. }
  6720. }
  6721. }
  6722.  
  6723. float respawnProtection = 10.0f;
  6724. plr->DoRespawn(pos, dir, respawnProtection);
  6725.  
  6726. PKT_S2C_RespawnPlayer_s n;
  6727. n.pos = plr->GetPosition();
  6728. n.dir = plr->m_PlayerRotation;
  6729. n.spawnProtection = respawnProtection;
  6730. p2pBroadcastToActive(plr, &n, sizeof(n));
  6731. plr->packetBarrierReason = "";
  6732.  
  6733. //Give loadout items
  6734. int useIndex = 0;
  6735. if(ginfo_.IsGameBR())//Battle Royale
  6736. {
  6737. for (int i = 0; i < BRItemsCount + 1; ++i)
  6738. {
  6739. wiInventoryItem tempItem;
  6740. tempItem.InventoryID = useIndex + 1;
  6741. tempItem.itemID = BRItems[i].itemID;
  6742. tempItem.quantity = BRItems[i].quantity;
  6743. tempItem.Var2 = 0;
  6744. plr->BackpackAddItem(tempItem);
  6745. }
  6746. }
  6747. else if(ginfo_.channel==6)//DEV EVENT MODE
  6748. {
  6749. if(gServerLogic.ginfo_.flags & GBGameInfo::SFLAGS_DisableASR)// Snipers Mode
  6750. {
  6751. for (int i = 0; i < devEventItemsCount2 + 1; ++i)
  6752. {
  6753. wiInventoryItem tempItem;
  6754. tempItem.InventoryID = useIndex + 1;
  6755. tempItem.itemID = devEventItems2[i].itemID;
  6756. tempItem.quantity = devEventItems2[i].quantity;
  6757. tempItem.Var2 = 0;
  6758. plr->BackpackAddItem(tempItem);
  6759. }
  6760. }
  6761. else if (gServerLogic.ginfo_.flags & GBGameInfo::SFLAGS_DisableSNP)// No Snipers Mode
  6762. {
  6763. for (int i = 0; i < devEventItemsCount3 + 1; ++i)
  6764. {
  6765. wiInventoryItem tempItem;
  6766. tempItem.InventoryID = useIndex + 1;
  6767. tempItem.itemID = devEventItems3[i].itemID;
  6768. tempItem.quantity = devEventItems3[i].quantity;
  6769. tempItem.Var2 = 0;
  6770. plr->BackpackAddItem(tempItem);
  6771. }
  6772. }
  6773. else // Normal Mode
  6774. {
  6775. for (int i = 0; i < devEventItemsCount + 1; ++i)
  6776. {
  6777. wiInventoryItem tempItem;
  6778. tempItem.InventoryID = useIndex + 1;
  6779. tempItem.itemID = devEventItems[i].itemID;
  6780. tempItem.quantity = devEventItems[i].quantity;
  6781. tempItem.Var2 = 0;
  6782. plr->BackpackAddItem(tempItem);
  6783. }
  6784. }
  6785. }
  6786.  
  6787. r3dOutToLog("Player: %s -- respawning\n", plr->userName); CLOG_INDENT;
  6788. return;
  6789. }
  6790.  
  6791. void ServerGameLogic::CheckBattleZone()
  6792. {
  6793. const float curTime = r3dGetTime();
  6794.  
  6795. for(int i=0; i<curPlayers_; i++)
  6796. {
  6797. obj_ServerPlayer* plr = plrList_[i];
  6798. if(!plr || plr->loadout_->Alive == 0 || m_isGameHasStarted)
  6799. continue;
  6800.  
  6801. if(g_BattleZone.IsInBattle(plr->GetPosition())) {
  6802. if(plr->bzOutTime > 0) {
  6803. //r3dOutToLog("%s entered battle zone\n", plr->Name.c_str());
  6804. plr->bzOutTime = -1;
  6805. }
  6806. continue;
  6807. }
  6808.  
  6809. if(plr->bzOutTime < 0) {
  6810. plr->bzOutTime = curTime;
  6811. //r3dOutToLog("%s left battle zone\n", plr->Name.c_str());
  6812. continue;
  6813. }
  6814.  
  6815. if(curTime > (plr->bzOutTime + _glm_bzOutKillTime)) {
  6816. //r3dOutToLog("%s disconnect outside battle zone\n", plr->Name.c_str());
  6817. DoKillPlayer(plr, plr, storecat_INVALID, true);
  6818. //DisconnectPeer(plr->peerId_, false, "Player: %s disconnect! Reason: outside battle zone", plr->Name.c_str());
  6819. continue;
  6820. }
  6821. }
  6822.  
  6823. return;
  6824. }
  6825.  
  6826. /*===============================================================================*/
Add Comment
Please, Sign In to add comment