Advertisement
jxsl13

Untitled

Apr 6th, 2015
258
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.83 KB | None | 0 0
  1. /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  2. /* If you are missing that file, acquire a complete release at teeworlds.com.                */
  3. /* Modified by Blindhero for 64 Client System                                                */
  4. #include <new>
  5. #include <engine/shared/config.h>
  6. #include "player.h"
  7.  
  8.  
  9. MACRO_ALLOC_POOL_ID_IMPL(CPlayer, MAX_CLIENTS)
  10.  
  11. IServer *CPlayer::Server() const { return m_pGameServer->Server(); }
  12.  
  13. CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, int Team)
  14. {
  15.     m_pGameServer = pGameServer;
  16.     m_RespawnTick = Server()->Tick();
  17.     m_DieTick = Server()->Tick();
  18.     m_ScoreStartTick = Server()->Tick();
  19.     m_pCharacter = 0;
  20.     m_ClientID = ClientID;
  21.     m_Team = GameServer()->m_pController->ClampTeam(Team);
  22.     m_SpectatorID = SPEC_FREEVIEW;
  23.     m_LastActionTick = Server()->Tick();
  24.     m_TeamChangeTick = Server()->Tick();
  25.    
  26.     //zCatch
  27.     m_CaughtBy = ZCATCH_NOT_CAUGHT;
  28.     m_SpecExplicit = false;
  29.     m_Kills = 0;
  30.     m_Deaths = 0;
  31.     m_LastKillTry = Server()->Tick();
  32.     m_TicksSpec = 0;
  33.     m_TicksIngame = 0;
  34.     m_ChatTicks = 0;
  35.    
  36.     // zCatch/TeeVi
  37.     m_ZCatchVictims = NULL;
  38.     m_zCatchNumVictims = 0;
  39.     m_zCatchNumKillsInARow = 0;
  40.    
  41.     // bot detection
  42.     m_IsAimBot = 0;
  43.     m_AimBotIndex = 0;
  44.     m_AimBotRange = 0;
  45.     m_AimBotLastDetection = 0;
  46.     m_AimBotTargetSpeed = .0;
  47.     m_CurrentTarget.x = 0;
  48.     m_CurrentTarget.y = 0;
  49.     m_LastTarget.x = 0;
  50.     m_LastTarget.y = 0;
  51.  
  52.     //64 System
  53.     int* idMap = Server()->GetIdMap(ClientID);
  54.     for (int i = 1;i < VANILLA_MAX_CLIENTS;i++)
  55.     {
  56.        
  57.         //jxsl13        idMap[i] = -1;
  58.                 idMap[i] = 0;
  59.     }
  60.     idMap[0] = ClientID;
  61.     zTeam = 0;
  62.  
  63.     m_pCommand = new CCommand(this);
  64.     replyID = -1;
  65.     m_TeamChangeDelay = 0;
  66. }
  67.  
  68. CPlayer::~CPlayer()
  69. {
  70.     while(m_ZCatchVictims != NULL)
  71.     {
  72.         CZCatchVictim *tmp = m_ZCatchVictims;
  73.         m_ZCatchVictims = tmp->prev;
  74.         delete tmp;
  75.     }
  76.    
  77.     delete m_pCharacter;
  78.     m_pCharacter = 0;
  79. }
  80.  
  81. void CPlayer::Tick()
  82. {
  83. #ifdef CONF_DEBUG
  84.     if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies)
  85. #endif
  86.     if(!Server()->ClientIngame(m_ClientID))
  87.         return;
  88.  
  89.     Server()->SetClientScore(m_ClientID, m_Score);
  90.    
  91.     /* begin zCatch*/
  92.    
  93.     if(m_Team == TEAM_SPECTATORS)
  94.         m_TicksSpec++;
  95.     else
  96.         m_TicksIngame++;
  97.    
  98.     if(m_ChatTicks > 0)
  99.         m_ChatTicks--;
  100.  
  101.     if((g_Config.m_SvAnticamper == 2 && g_Config.m_SvMode == 1) || (g_Config.m_SvAnticamper == 1))
  102.         Anticamper();
  103.     /* end zCatch*/
  104.  
  105.     // do latency stuff
  106.     {
  107.         IServer::CClientInfo Info;
  108.         //dbg_msg("PlayerTick", "ClientID: %d", m_ClientID);
  109.         if(Server()->GetClientInfo(m_ClientID, &Info))
  110.         {
  111.             m_Latency.m_Accum += Info.m_Latency;
  112.             m_Latency.m_AccumMax = max(m_Latency.m_AccumMax, Info.m_Latency);
  113.             m_Latency.m_AccumMin = min(m_Latency.m_AccumMin, Info.m_Latency);
  114.         }
  115.         // each second
  116.         if(Server()->Tick()%Server()->TickSpeed() == 0)
  117.         {
  118.             m_Latency.m_Avg = m_Latency.m_Accum/Server()->TickSpeed();
  119.             m_Latency.m_Max = m_Latency.m_AccumMax;
  120.             m_Latency.m_Min = m_Latency.m_AccumMin;
  121.             m_Latency.m_Accum = 0;
  122.             m_Latency.m_AccumMin = 1000;
  123.             m_Latency.m_AccumMax = 0;
  124.         }
  125.     }
  126.  
  127.     if(!GameServer()->m_World.m_Paused)
  128.     {
  129.         if(!m_pCharacter && m_Team == TEAM_SPECTATORS && m_SpectatorID == SPEC_FREEVIEW)
  130.             m_ViewPos -= vec2(clamp(m_ViewPos.x-m_LatestActivity.m_TargetX, -500.0f, 500.0f), clamp(m_ViewPos.y-m_LatestActivity.m_TargetY, -400.0f, 400.0f));
  131.  
  132.         if(!m_pCharacter && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick())
  133.             m_Spawning = true;
  134.  
  135.         if(m_pCharacter)
  136.         {
  137.             if(m_pCharacter->IsAlive())
  138.             {
  139.                 m_ViewPos = m_pCharacter->m_Pos;
  140.             }
  141.             else
  142.             {
  143.                 delete m_pCharacter;
  144.                 m_pCharacter = 0;
  145.             }
  146.         }
  147.         else if(m_Spawning && m_RespawnTick <= Server()->Tick())
  148.             TryRespawn();
  149.     }
  150.     else
  151.     {
  152.         ++m_RespawnTick;
  153.         ++m_DieTick;
  154.         ++m_ScoreStartTick;
  155.         ++m_LastActionTick;
  156.         ++m_TeamChangeTick;
  157.     }
  158.    
  159.     // bot detection
  160.     m_LastTarget = m_CurrentTarget;
  161.     m_CurrentTarget.x = m_LatestActivity.m_TargetX;
  162.     m_CurrentTarget.y = m_LatestActivity.m_TargetY;
  163.     m_AimBotTargetSpeed = abs(distance(m_CurrentTarget, m_LastTarget));
  164. }
  165.  
  166. void CPlayer::PostTick()
  167. {
  168.     // update latency value
  169.     if(m_PlayerFlags&PLAYERFLAG_SCOREBOARD)
  170.     {
  171.         for(int i = 0; i < MAX_CLIENTS; ++i)
  172.         {
  173.             if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
  174.                 m_aActLatency[i] = GameServer()->m_apPlayers[i]->m_Latency.m_Min;
  175.         }
  176.     }
  177.  
  178.     // update view pos for spectators
  179.     if(m_Team == TEAM_SPECTATORS && m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[m_SpectatorID])
  180.         m_ViewPos = GameServer()->m_apPlayers[m_SpectatorID]->m_ViewPos;
  181. }
  182.  
  183. void CPlayer::Snap(int SnappingClient)
  184. {
  185. #ifdef CONF_DEBUG
  186.     if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies)
  187. #endif
  188.     if(!Server()->ClientIngame(m_ClientID))
  189.         return;
  190.  
  191.     int id = m_ClientID;
  192.     if (!Server()->Translate(id, SnappingClient)) return;
  193.  
  194.     CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, id, sizeof(CNetObj_ClientInfo)));
  195.  
  196.     if(!pClientInfo)
  197.         return;
  198.  
  199.    
  200.     pClientInfo->m_Country = Server()->ClientCountry(m_ClientID);
  201.     StrToInts(&pClientInfo->m_Skin0, 6, m_TeeInfos.m_SkinName);
  202.     if(g_Config.m_SvUseTeamColors) {
  203.         pClientInfo->m_UseCustomColor = 1;
  204.         if(zTeam == 0) {
  205.             pClientInfo->m_ColorBody = 16777215;
  206.         } else {
  207.             int TeamColor = (255/(g_Config.m_SvMaxClients / GameServer()->max_teamsize) * zTeam)%256;
  208.             pClientInfo->m_ColorBody = TeamColor * 0x010000 + 0xff00;
  209.         }
  210.         pClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet;
  211.     } else {
  212.         pClientInfo->m_UseCustomColor = m_TeeInfos.m_UseCustomColor;
  213.         pClientInfo->m_ColorBody = m_TeeInfos.m_ColorBody;
  214.         pClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet;
  215.     }
  216.  
  217.     char clientname[MAX_NAME_LENGTH], clanname[MAX_CLAN_LENGTH];;
  218.     if(g_Config.m_SvShowTeam && zTeam > 0)
  219.         str_format(clientname, sizeof(clientname), "[%d]%s", zTeam, Server()->ClientName(m_ClientID));
  220.     else
  221.         str_copy(clientname, Server()->ClientName(m_ClientID), sizeof(clientname));
  222.     StrToInts(&pClientInfo->m_Name0, 4, clientname);
  223.  
  224.     if(zTeam > 0 && GameServer()->m_zTeamNames[zTeam] && str_length(GameServer()->m_zTeamNames[zTeam]) > 0)
  225.         str_copy(clanname, GameServer()->m_zTeamNames[zTeam], sizeof(clanname));
  226.     else
  227.         str_copy(clanname, Server()->ClientClan(m_ClientID), sizeof(clanname));
  228.     StrToInts(&pClientInfo->m_Clan0, 3, clanname);
  229.  
  230.  
  231.     CNetObj_PlayerInfo *pPlayerInfo = static_cast<CNetObj_PlayerInfo *>(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, id, sizeof(CNetObj_PlayerInfo)));
  232.  
  233.     if(!pPlayerInfo)
  234.         return;
  235.  
  236.     pPlayerInfo->m_Latency = SnappingClient == -1 ? m_Latency.m_Min : GameServer()->m_apPlayers[SnappingClient]->m_aActLatency[m_ClientID];
  237.     pPlayerInfo->m_Local = 0;
  238.     pPlayerInfo->m_ClientID = id;
  239.     pPlayerInfo->m_Score = m_Score;
  240.     pPlayerInfo->m_Team = m_Team;
  241.  
  242.     if(m_ClientID == SnappingClient)
  243.         pPlayerInfo->m_Local = 1;
  244.  
  245.     if(m_ClientID == SnappingClient && m_Team == TEAM_SPECTATORS)
  246.     {
  247.         CNetObj_SpectatorInfo *pSpectatorInfo = static_cast<CNetObj_SpectatorInfo *>(Server()->SnapNewItem(NETOBJTYPE_SPECTATORINFO, m_ClientID, sizeof(CNetObj_SpectatorInfo)));
  248.         if(!pSpectatorInfo)
  249.             return;
  250.  
  251.         pSpectatorInfo->m_SpectatorID = m_SpectatorID;
  252.         pSpectatorInfo->m_X = m_ViewPos.x;
  253.         pSpectatorInfo->m_Y = m_ViewPos.y;
  254.     }
  255. }
  256.  
  257. void CPlayer::FakeSnap(int SnappingClient)
  258. {
  259.     IServer::CClientInfo info;
  260.     //dbg_msg("fakesnap", "SnappingClient: %d", SnappingClient);
  261.     Server()->GetClientInfo(SnappingClient, &info);
  262.     if (info.m_CustClt)
  263.         return;
  264.  
  265.     int id = VANILLA_MAX_CLIENTS - 1;
  266.  
  267.     CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, id, sizeof(CNetObj_ClientInfo)));
  268.  
  269.     if(!pClientInfo)
  270.         return;
  271.  
  272.     StrToInts(&pClientInfo->m_Name0, 4, " ");
  273.     StrToInts(&pClientInfo->m_Clan0, 3, Server()->ClientClan(m_ClientID));
  274.     StrToInts(&pClientInfo->m_Skin0, 6, m_TeeInfos.m_SkinName);
  275. }
  276.  
  277. void CPlayer::OnDisconnect(const char *pReason)
  278. {
  279.     KillCharacter();
  280.  
  281.     if(Server()->ClientIngame(m_ClientID))
  282.     {
  283.         char aBuf[512];
  284.         if(pReason && *pReason)
  285.             str_format(aBuf, sizeof(aBuf), "'%s' has left the game (%s)", Server()->ClientName(m_ClientID), pReason);
  286.         else
  287.             str_format(aBuf, sizeof(aBuf), "'%s' has left the game", Server()->ClientName(m_ClientID));
  288.         GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
  289.  
  290.         str_format(aBuf, sizeof(aBuf), "leave player='%d:%s'", m_ClientID, Server()->ClientName(m_ClientID));
  291.         GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf);
  292.     }
  293. }
  294.  
  295. void CPlayer::OnPredictedInput(CNetObj_PlayerInput *NewInput)
  296. {
  297.     // skip the input if chat is active
  298.     if((m_PlayerFlags&PLAYERFLAG_CHATTING) && (NewInput->m_PlayerFlags&PLAYERFLAG_CHATTING))
  299.         return;
  300.  
  301.     if(m_pCharacter && m_pCharacter->m_FreezeTicks)
  302.         return;
  303.  
  304.     if(m_pCharacter)
  305.         m_pCharacter->OnPredictedInput(NewInput);
  306. }
  307.  
  308. void CPlayer::OnDirectInput(CNetObj_PlayerInput *NewInput)
  309. {
  310.     if(NewInput->m_PlayerFlags&PLAYERFLAG_CHATTING)
  311.     {
  312.         // skip the input if chat is active
  313.         if(m_PlayerFlags&PLAYERFLAG_CHATTING)
  314.             return;
  315.  
  316.         // reset input
  317.         if(m_pCharacter)
  318.             m_pCharacter->ResetInput();
  319.  
  320.         m_PlayerFlags = NewInput->m_PlayerFlags;
  321.         return;
  322.     }
  323.  
  324.     m_PlayerFlags = NewInput->m_PlayerFlags;
  325.  
  326.     if(m_pCharacter)
  327.         m_pCharacter->OnDirectInput(NewInput);
  328.  
  329.     if(m_pCharacter && m_pCharacter->m_FreezeTicks)
  330.         return;
  331.  
  332.     if(!m_pCharacter && m_Team != TEAM_SPECTATORS && (NewInput->m_Fire&1))
  333.         m_Spawning = true;
  334.  
  335.     // check for activity
  336.     if(NewInput->m_Direction || m_LatestActivity.m_TargetX != NewInput->m_TargetX ||
  337.         m_LatestActivity.m_TargetY != NewInput->m_TargetY || NewInput->m_Jump ||
  338.         NewInput->m_Fire&1 || NewInput->m_Hook)
  339.     {
  340.         m_LatestActivity.m_TargetX = NewInput->m_TargetX;
  341.         m_LatestActivity.m_TargetY = NewInput->m_TargetY;
  342.         m_LastActionTick = Server()->Tick();
  343.     }
  344. }
  345.  
  346. CCharacter *CPlayer::GetCharacter()
  347. {
  348.     if(m_pCharacter && m_pCharacter->IsAlive())
  349.         return m_pCharacter;
  350.     return 0;
  351. }
  352.  
  353. void CPlayer::KillCharacter(int Weapon)
  354. {
  355.     if(m_pCharacter)
  356.     {
  357.         m_pCharacter->Die(m_ClientID, Weapon);
  358.         delete m_pCharacter;
  359.         m_pCharacter = 0;
  360.     }
  361. }
  362.  
  363. void CPlayer::Respawn()
  364. {
  365.     if(m_Team != TEAM_SPECTATORS)
  366.         m_Spawning = true;
  367. }
  368.  
  369. void CPlayer::SetTeam(int Team, bool DoChatMsg)
  370. {
  371.     // clamp the team
  372.     Team = GameServer()->m_pController->ClampTeam(Team);
  373.     if(m_Team == Team)
  374.         return;
  375.  
  376.     char aBuf[512];
  377.     if(DoChatMsg)
  378.     {
  379.         str_format(aBuf, sizeof(aBuf), "'%s' joined the %s", Server()->ClientName(m_ClientID), GameServer()->m_pController->GetTeamName(Team));
  380.         GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
  381.     }
  382.  
  383.     KillCharacter();
  384.  
  385.     m_Team = Team;
  386.     m_LastActionTick = Server()->Tick();
  387.     m_SpectatorID = SPEC_FREEVIEW;
  388.     // we got to wait 0.5 secs before respawning
  389.     m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
  390.     str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' m_Team=%d", m_ClientID, Server()->ClientName(m_ClientID), m_Team);
  391.     GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  392.  
  393.     if(Team == TEAM_SPECTATORS)
  394.     {
  395.         // update spectator modes
  396.         for(int i = 0; i < MAX_CLIENTS; ++i)
  397.         {
  398.             if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_SpectatorID == m_ClientID)
  399.                 GameServer()->m_apPlayers[i]->m_SpectatorID = SPEC_FREEVIEW;
  400.         }
  401.         m_SpecExplicit = true;
  402.     }
  403.     else
  404.         m_SpecExplicit = false;
  405. }
  406.  
  407. void CPlayer::SetTeamDirect(int Team)
  408. {
  409.     m_Team = Team;
  410. }
  411.  
  412. void CPlayer::TryRespawn()
  413. {
  414.     vec2 SpawnPos;
  415.  
  416.     if(!GameServer()->m_pController->CanSpawn(m_Team, &SpawnPos))
  417.         return;
  418.  
  419.     m_Spawning = false;
  420.     m_pCharacter = new(m_ClientID) CCharacter(&GameServer()->m_World);
  421.     m_pCharacter->Spawn(this, SpawnPos);
  422.     GameServer()->CreatePlayerSpawn(SpawnPos);
  423. }
  424.  
  425. int CPlayer::Anticamper()
  426. {
  427.     if(GameServer()->m_World.m_Paused || !m_pCharacter || m_Team == TEAM_SPECTATORS || m_pCharacter->m_FreezeTicks)
  428.     {
  429.         m_CampTick = -1;
  430.         m_SentCampMsg = false;
  431.         return 0;
  432.     }
  433.  
  434.     int AnticamperTime = g_Config.m_SvAnticamperTime;
  435.     int AnticamperRange = g_Config.m_SvAnticamperRange;
  436.  
  437.     if(m_CampTick == -1)
  438.     {
  439.         m_CampPos = m_pCharacter->m_Pos;
  440.         m_CampTick = Server()->Tick() + Server()->TickSpeed()*AnticamperTime;
  441.     }
  442.  
  443.     // Check if the player is moving
  444.     if((m_CampPos.x - m_pCharacter->m_Pos.x >= (float)AnticamperRange || m_CampPos.x - m_pCharacter->m_Pos.x <= -(float)AnticamperRange)
  445.     || (m_CampPos.y - m_pCharacter->m_Pos.y >= (float)AnticamperRange || m_CampPos.y - m_pCharacter->m_Pos.y <= -(float)AnticamperRange))
  446.         {
  447.             m_CampTick = -1;
  448.         }
  449.  
  450.     // Send warning to the player
  451.     if(m_CampTick <= Server()->Tick() + Server()->TickSpeed() * AnticamperTime/2 && m_CampTick != -1 && !m_SentCampMsg)
  452.     {
  453.         GameServer()->SendBroadcast("ANTICAMPER: Move or die", m_ClientID);
  454.         m_SentCampMsg = true;
  455.     }
  456.  
  457.     // Kill him
  458.     if((m_CampTick <= Server()->Tick()) && (m_CampTick > 0))
  459.     {
  460.         if(g_Config.m_SvAnticamperFreeze)
  461.         {
  462.             m_pCharacter->Freeze(Server()->TickSpeed()*g_Config.m_SvAnticamperFreeze);
  463.             GameServer()->SendBroadcast("You have been freezed due camping", m_ClientID);
  464.         }
  465.         else
  466.             m_pCharacter->Die(m_ClientID, WEAPON_GAME);
  467.         m_CampTick = -1;
  468.         m_SentCampMsg = false;
  469.         return 1;
  470.     }
  471.     return 0;
  472. }
  473.  
  474. // catch another player
  475. void CPlayer::AddZCatchVictim(int ClientID, int reason)
  476. {
  477.     CPlayer *victim = GameServer()->m_apPlayers[ClientID];
  478.     if(victim)
  479.     {
  480.         // add to list of victims
  481.         CZCatchVictim *v = new CZCatchVictim;
  482.         v->ClientID = ClientID;
  483.         v->Reason = reason;
  484.         v->prev = m_ZCatchVictims;
  485.         m_ZCatchVictims = v;
  486.         ++m_zCatchNumVictims;
  487.         // set victim's status
  488.         victim->m_CaughtBy = m_ClientID;
  489.         victim->m_SpecExplicit = false;
  490.         victim->m_zCatchJoinSpecWhenReleased = false;
  491.         victim->SetTeamDirect(TEAM_SPECTATORS);
  492.         victim->m_SpectatorID = m_ClientID;
  493.     }
  494. }
  495.  
  496. // release one or more of the victims
  497. void CPlayer::ReleaseZCatchVictim(int ClientID, int limit)
  498. {
  499.     CZCatchVictim **v = &m_ZCatchVictims;
  500.     CZCatchVictim *tmp;
  501.     CPlayer *victim;
  502.     int count = 0;
  503.     while(*v != NULL)
  504.     {
  505.         if(ClientID == ZCATCH_RELEASE_ALL || (*v)->ClientID == ClientID)
  506.         {
  507.             victim = GameServer()->m_apPlayers[(*v)->ClientID];
  508.             if(victim)
  509.             {
  510.                 victim->m_CaughtBy = ZCATCH_NOT_CAUGHT;
  511.                 victim->SetTeamDirect(GameServer()->m_pController->ClampTeam(1));
  512.                 victim->m_SpectatorID = SPEC_FREEVIEW;
  513.                 // SetTeam after SetTeamDirect, otherwise it would skip the message for joining the spectators
  514.                 if(victim->m_zCatchJoinSpecWhenReleased)
  515.                     victim->SetTeam(GameServer()->m_pController->ClampTeam(TEAM_SPECTATORS));
  516.             }
  517.             // delete from list
  518.             tmp = (*v)->prev;
  519.             delete *v;
  520.             *v = tmp;
  521.             --m_zCatchNumVictims;
  522.             if (limit && ++count >= limit)
  523.                 return;
  524.         }
  525.         else
  526.             v = &(*v)->prev;
  527.     }
  528. }
  529.  
  530. bool CPlayer::CanAttack(int ID) {
  531.     if(zTeam == 0)
  532.         return true;
  533.     else
  534.         if(GameServer()->m_apPlayers[ID] && GameServer()->m_apPlayers[ID]->zTeam == zTeam)
  535.             return false;
  536.     return true;
  537. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement