Skip to content

Commit

Permalink
Merge pull request #5 from Stannnnn/master
Browse files Browse the repository at this point in the history
24 player support (from Stannnn)
  • Loading branch information
uakfdotb authored Apr 29, 2018
2 parents 970551e + 44e3e44 commit 3f0eb73
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 64 deletions.
2 changes: 1 addition & 1 deletion ghost/bnetprotocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ Observers: (mask 0x00700000) cant be combined
UTIL_AppendByteArray( packet, CustomGame, 4 ); // Custom Game
UTIL_AppendByteArrayFast( packet, gameName ); // Game Name
packet.push_back( 0 ); // Game Password is NULL
packet.push_back( 98 ); // Slots Free (ascii 98 = char 'b' = 11 slots free) - note: do not reduce this as this is the # of PID's Warcraft III will allocate
packet.push_back( 110 ); // Slots Free (ascii 98 = char 'b' = 11 slots free) - note: do not reduce this as this is the # of PID's Warcraft III will allocate
UTIL_AppendByteArrayFast( packet, HostCounterString, false ); // Host Counter
UTIL_AppendByteArrayFast( packet, StatString ); // Stat String
packet.push_back( 0 ); // Stat String null terminator (the stat string is encoded to remove all even numbers i.e. zeros)
Expand Down
20 changes: 10 additions & 10 deletions ghost/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string
{
unsigned char SID = (unsigned char)( Slot - 1 );

if( !( m_Map->GetMapOptions( ) & MAPOPT_FIXEDPLAYERSETTINGS ) && Colour < 12 && SID < m_Slots.size( ) )
if( !( m_Map->GetMapOptions( ) & MAPOPT_FIXEDPLAYERSETTINGS ) && Colour < MAX_SLOTS && SID < m_Slots.size( ) )
{
if( m_Slots[SID].GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && m_Slots[SID].GetComputer( ) == 1 )
ColourSlot( SID, Colour );
Expand Down Expand Up @@ -879,7 +879,7 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string
{
unsigned char SID = (unsigned char)( Slot - 1 );

if( !( m_Map->GetMapOptions( ) & MAPOPT_FIXEDPLAYERSETTINGS ) && Team < 12 && SID < m_Slots.size( ) )
if( !( m_Map->GetMapOptions( ) & MAPOPT_FIXEDPLAYERSETTINGS ) && Team < MAX_SLOTS && SID < m_Slots.size( ) )
{
if( m_Slots[SID].GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && m_Slots[SID].GetComputer( ) == 1 )
{
Expand Down Expand Up @@ -1446,14 +1446,14 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string

uint32_t FixedHostCounter = m_HostCounter & 0x0FFFFFFF;

// we send 12 for SlotsTotal because this determines how many PID's Warcraft 3 allocates
// we need to make sure Warcraft 3 allocates at least SlotsTotal + 1 but at most 12 PID's
// this is because we need an extra PID for the virtual host player (but we always delete the virtual host player when the 12th person joins)
// we send MAX_SLOTS for SlotsTotal because this determines how many PID's Warcraft 3 allocates
// we need to make sure Warcraft 3 allocates at least SlotsTotal + 1 but at most MAX_SLOTS PID's
// this is because we need an extra PID for the virtual host player (but we always delete the virtual host player when the MAX_SLOTSth person joins)
// however, we can't send 13 for SlotsTotal because this causes Warcraft 3 to crash when sharing control of units
// nor can we send SlotsTotal because then Warcraft 3 crashes when playing maps with less than 12 PID's (because of the virtual host player taking an extra PID)
// we also send 12 for SlotsOpen because Warcraft 3 assumes there's always at least one player in the game (the host)
// nor can we send SlotsTotal because then Warcraft 3 crashes when playing maps with less than MAX_SLOTS PID's (because of the virtual host player taking an extra PID)
// we also send MAX_SLOTS for SlotsOpen because Warcraft 3 assumes there's always at least one player in the game (the host)
// so if we try to send accurate numbers it'll always be off by one and results in Warcraft 3 assuming the game is full when it still needs one more player
// the easiest solution is to simply send 12 for both so the game will always show up as (1/12) players
// the easiest solution is to simply send MAX_SLOTS for both so the game will always show up as (1/MAX_SLOTS) players

if( m_SaveGame )
{
Expand All @@ -1466,15 +1466,15 @@ bool CGame :: EventPlayerBotCommand( CGamePlayer *player, string command, string
BYTEARRAY MapHeight;
MapHeight.push_back( 0 );
MapHeight.push_back( 0 );
m_GHost->m_UDPSocket->SendTo( IP, Port, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, FixedHostCounter, m_EntryKey ) );
m_GHost->m_UDPSocket->SendTo( IP, Port, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), MAX_SLOTS, MAX_SLOTS, m_HostPort, FixedHostCounter, m_EntryKey ) );
}
else
{
// note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect)
// note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect)

uint32_t MapGameType = MAPGAMETYPE_UNKNOWN0;
m_GHost->m_UDPSocket->SendTo( IP, Port, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, FixedHostCounter, m_EntryKey ) );
m_GHost->m_UDPSocket->SendTo( IP, Port, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), MAX_SLOTS, MAX_SLOTS, m_HostPort, FixedHostCounter, m_EntryKey ) );
}
}
}
Expand Down
82 changes: 41 additions & 41 deletions ghost/game_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ bool CBaseGame :: Update( void *fd, void *send_fd )

// create the virtual host player

if( !m_GameLoading && !m_GameLoaded && GetNumPlayers( ) < 12 )
if( !m_GameLoading && !m_GameLoaded && GetNumPlayers( ) < MAX_SLOTS )
CreateVirtualHost( );

// unlock the game
Expand Down Expand Up @@ -473,14 +473,14 @@ bool CBaseGame :: Update( void *fd, void *send_fd )

uint32_t FixedHostCounter = m_HostCounter & 0x0FFFFFFF;

// we send 12 for SlotsTotal because this determines how many PID's Warcraft 3 allocates
// we need to make sure Warcraft 3 allocates at least SlotsTotal + 1 but at most 12 PID's
// this is because we need an extra PID for the virtual host player (but we always delete the virtual host player when the 12th person joins)
// we send MAX_SLOTS for SlotsTotal because this determines how many PID's Warcraft 3 allocates
// we need to make sure Warcraft 3 allocates at least SlotsTotal + 1 but at most MAX_SLOTS PID's
// this is because we need an extra PID for the virtual host player (but we always delete the virtual host player when the MAX_SLOTSth person joins)
// however, we can't send 13 for SlotsTotal because this causes Warcraft 3 to crash when sharing control of units
// nor can we send SlotsTotal because then Warcraft 3 crashes when playing maps with less than 12 PID's (because of the virtual host player taking an extra PID)
// we also send 12 for SlotsOpen because Warcraft 3 assumes there's always at least one player in the game (the host)
// nor can we send SlotsTotal because then Warcraft 3 crashes when playing maps with less than MAX_SLOTS PID's (because of the virtual host player taking an extra PID)
// we also send MAX_SLOTS for SlotsOpen because Warcraft 3 assumes there's always at least one player in the game (the host)
// so if we try to send accurate numbers it'll always be off by one and results in Warcraft 3 assuming the game is full when it still needs one more player
// the easiest solution is to simply send 12 for both so the game will always show up as (1/12) players
// the easiest solution is to simply send MAX_SLOTS for both so the game will always show up as (1/MAX_SLOTS) players

if( m_SaveGame )
{
Expand All @@ -493,15 +493,15 @@ bool CBaseGame :: Update( void *fd, void *send_fd )
BYTEARRAY MapHeight;
MapHeight.push_back( 0 );
MapHeight.push_back( 0 );
m_GHost->m_UDPSocket->Broadcast( 6112, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), 12, 12, m_HostPort, FixedHostCounter, m_EntryKey ) );
m_GHost->m_UDPSocket->Broadcast( 6112, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), MapWidth, MapHeight, m_GameName, "Varlock", GetTime( ) - m_CreationTime, "Save\\Multiplayer\\" + m_SaveGame->GetFileNameNoPath( ), m_SaveGame->GetMagicNumber( ), MAX_SLOTS, MAX_SLOTS, m_HostPort, FixedHostCounter, m_EntryKey ) );
}
else
{
// note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect)
// note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect)

uint32_t MapGameType = MAPGAMETYPE_UNKNOWN0;
m_GHost->m_UDPSocket->Broadcast( 6112, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), 12, 12, m_HostPort, FixedHostCounter, m_EntryKey ) );
m_GHost->m_UDPSocket->Broadcast( 6112, m_Protocol->SEND_W3GS_GAMEINFO( m_GHost->m_TFT, m_GHost->m_LANWar3Version, UTIL_CreateByteArray( MapGameType, false ), m_Map->GetMapGameFlags( ), m_Map->GetMapWidth( ), m_Map->GetMapHeight( ), m_GameName, "Varlock", GetTime( ) - m_CreationTime, m_Map->GetMapPath( ), m_Map->GetMapCRC( ), MAX_SLOTS, MAX_SLOTS, m_HostPort, FixedHostCounter, m_EntryKey ) );
}
}

Expand Down Expand Up @@ -2049,7 +2049,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP
// we have a slot for the new player
// make room for them by deleting the virtual host player if we have to

if( GetNumPlayers( ) >= 11 || EnforcePID == m_VirtualHostPID )
if( GetNumPlayers( ) >= MAX_SLOTS-1 || EnforcePID == m_VirtualHostPID )
DeleteVirtualHost( );

// turning the CPotentialPlayer into a CGamePlayer is a bit of a pain because we have to be careful not to close the socket
Expand Down Expand Up @@ -2079,9 +2079,9 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP
else
{
if( m_Map->GetMapFlags( ) & MAPFLAG_RANDOMRACES )
m_Slots[SID] = CGameSlot( Player->GetPID( ), 255, SLOTSTATUS_OCCUPIED, 0, 12, 12, SLOTRACE_RANDOM );
m_Slots[SID] = CGameSlot( Player->GetPID( ), 255, SLOTSTATUS_OCCUPIED, 0, MAX_SLOTS, MAX_SLOTS, SLOTRACE_RANDOM );
else
m_Slots[SID] = CGameSlot( Player->GetPID( ), 255, SLOTSTATUS_OCCUPIED, 0, 12, 12, SLOTRACE_RANDOM | SLOTRACE_SELECTABLE );
m_Slots[SID] = CGameSlot( Player->GetPID( ), 255, SLOTSTATUS_OCCUPIED, 0, MAX_SLOTS, MAX_SLOTS, SLOTRACE_RANDOM | SLOTRACE_SELECTABLE );

// try to pick a team and colour
// make sure there aren't too many other players already
Expand All @@ -2090,7 +2090,7 @@ void CBaseGame :: EventPlayerJoined( CPotentialPlayer *potential, CIncomingJoinP

for( unsigned char i = 0; i < m_Slots.size( ); ++i )
{
if( m_Slots[i].GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && m_Slots[i].GetTeam( ) != 12 )
if( m_Slots[i].GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && m_Slots[i].GetTeam( ) != MAX_SLOTS )
NumOtherPlayers++;
}

Expand Down Expand Up @@ -2439,7 +2439,7 @@ void CBaseGame :: EventPlayerJoinedWithScore( CPotentialPlayer *potential, CInco
// we have a slot for the new player
// make room for them by deleting the virtual host player if we have to

if( GetNumPlayers( ) >= 11 )
if( GetNumPlayers( ) >= MAX_SLOTS-1 )
DeleteVirtualHost( );

// identify their joined realm
Expand Down Expand Up @@ -3033,10 +3033,10 @@ void CBaseGame :: EventPlayerChangeTeam( CGamePlayer *player, unsigned char team
}
else
{
if( team > 12 )
if( team > MAX_SLOTS )
return;

if( team == 12 )
if( team == MAX_SLOTS )
{
if( m_Map->GetMapObservers( ) != MAPOBS_ALLOWED && m_Map->GetMapObservers( ) != MAPOBS_REFEREES )
return;
Expand All @@ -3052,7 +3052,7 @@ void CBaseGame :: EventPlayerChangeTeam( CGamePlayer *player, unsigned char team

for( unsigned char i = 0; i < m_Slots.size( ); ++i )
{
if( m_Slots[i].GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && m_Slots[i].GetTeam( ) != 12 && m_Slots[i].GetPID( ) != player->GetPID( ) )
if( m_Slots[i].GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && m_Slots[i].GetTeam( ) != MAX_SLOTS && m_Slots[i].GetPID( ) != player->GetPID( ) )
++NumOtherPlayers;
}

Expand All @@ -3066,13 +3066,13 @@ void CBaseGame :: EventPlayerChangeTeam( CGamePlayer *player, unsigned char team
{
m_Slots[SID].SetTeam( team );

if( team == 12 )
if( team == MAX_SLOTS )
{
// if they're joining the observer team give them the observer colour

m_Slots[SID].SetColour( 12 );
m_Slots[SID].SetColour( MAX_SLOTS );
}
else if( m_Slots[SID].GetColour( ) == 12 )
else if( m_Slots[SID].GetColour( ) == MAX_SLOTS )
{
// if they're joining a regular team give them an unused colour

Expand All @@ -3094,7 +3094,7 @@ void CBaseGame :: EventPlayerChangeColour( CGamePlayer *player, unsigned char co
if( m_Map->GetMapOptions( ) & MAPOPT_FIXEDPLAYERSETTINGS )
return;

if( colour > 11 )
if( colour > MAX_SLOTS-1 )
return;

unsigned char SID = GetSIDFromPID( player->GetPID( ) );
Expand All @@ -3103,7 +3103,7 @@ void CBaseGame :: EventPlayerChangeColour( CGamePlayer *player, unsigned char co
{
// make sure the player isn't an observer

if( m_Slots[SID].GetTeam( ) == 12 )
if( m_Slots[SID].GetTeam( ) == MAX_SLOTS )
return;

ColourSlot( SID, colour );
Expand Down Expand Up @@ -3698,7 +3698,7 @@ unsigned char CBaseGame :: GetNewColour( )
{
// find an unused colour for a player to use

for( unsigned char TestColour = 0; TestColour < 12; ++TestColour )
for( unsigned char TestColour = 0; TestColour < MAX_SLOTS; ++TestColour )
{
bool InUse = false;

Expand All @@ -3717,7 +3717,7 @@ unsigned char CBaseGame :: GetNewColour( )

// this should never happen

return 12;
return MAX_SLOTS;
}

BYTEARRAY CBaseGame :: GetPIDs( )
Expand Down Expand Up @@ -4013,7 +4013,7 @@ void CBaseGame :: ComputerSlot( unsigned char SID, unsigned char skill, bool kic

void CBaseGame :: ColourSlot( unsigned char SID, unsigned char colour )
{
if( SID < m_Slots.size( ) && colour < 12 )
if( SID < m_Slots.size( ) && colour < MAX_SLOTS )
{
// make sure the requested colour isn't already taken

Expand Down Expand Up @@ -4094,7 +4094,7 @@ void CBaseGame :: ShuffleSlots( )

for( vector<CGameSlot> :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); ++i )
{
if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetTeam( ) != 12 )
if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetTeam( ) != MAX_SLOTS )
PlayerSlots.push_back( *i );
}

Expand Down Expand Up @@ -4140,7 +4140,7 @@ void CBaseGame :: ShuffleSlots( )

for( vector<CGameSlot> :: iterator i = m_Slots.begin( ); i != m_Slots.end( ); ++i )
{
if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetTeam( ) != 12 )
if( (*i).GetSlotStatus( ) == SLOTSTATUS_OCCUPIED && (*i).GetComputer( ) == 0 && (*i).GetTeam( ) != MAX_SLOTS )
{
Slots.push_back( *CurrentPlayer );
++CurrentPlayer;
Expand Down Expand Up @@ -4168,7 +4168,7 @@ vector<unsigned char> CBaseGame :: BalanceSlotsRecursive( vector<unsigned char>
vector<unsigned char> BestOrdering = PlayerIDs;
double BestDifference = -1.0;

for( unsigned char i = StartTeam; i < 12; ++i )
for( unsigned char i = StartTeam; i < MAX_SLOTS; ++i )
{
if( TeamSizes[i] > 0 )
{
Expand All @@ -4195,9 +4195,9 @@ vector<unsigned char> CBaseGame :: BalanceSlotsRecursive( vector<unsigned char>
// now calculate the team scores for all the teams that we know about (e.g. on subsequent recursion steps this will NOT be every possible team)

vector<unsigned char> :: iterator CurrentPID = TestOrdering.begin( );
double TeamScores[12];
double TeamScores[MAX_SLOTS];

for( unsigned char j = StartTeam; j < 12; ++j )
for( unsigned char j = StartTeam; j < MAX_SLOTS; ++j )
{
TeamScores[j] = 0.0;

Expand All @@ -4212,11 +4212,11 @@ vector<unsigned char> CBaseGame :: BalanceSlotsRecursive( vector<unsigned char>

double LargestDifference = 0.0;

for( unsigned char j = StartTeam; j < 12; ++j )
for( unsigned char j = StartTeam; j < MAX_SLOTS; ++j )
{
if( TeamSizes[j] > 0 )
{
for( unsigned char k = j + 1; k < 12; ++k )
for( unsigned char k = j + 1; k < MAX_SLOTS; ++k )
{
if( TeamSizes[k] > 0 )
{
Expand Down Expand Up @@ -4252,12 +4252,12 @@ void CBaseGame :: BalanceSlots( )
}

// setup the necessary variables for the balancing algorithm
// use an array of 13 elements for 12 players because GHost++ allocates PID's from 1-12 (i.e. excluding 0) and we use the PID to index the array
// use an array of 13 elements for MAX_SLOTS players because GHost++ allocates PID's from 1-MAX_SLOTS (i.e. excluding 0) and we use the PID to index the array

vector<unsigned char> PlayerIDs;
unsigned char TeamSizes[12];
unsigned char TeamSizes[MAX_SLOTS];
double PlayerScores[13];
memset( TeamSizes, 0, sizeof( unsigned char ) * 12 );
memset( TeamSizes, 0, sizeof( unsigned char ) * MAX_SLOTS );

for( vector<CGamePlayer *> :: iterator i = m_Players.begin( ); i != m_Players.end( ); ++i )
{
Expand All @@ -4271,7 +4271,7 @@ void CBaseGame :: BalanceSlots( )
{
unsigned char Team = m_Slots[SID].GetTeam( );

if( Team < 12 )
if( Team < MAX_SLOTS )
{
// we are forced to use a default score because there's no way to balance the teams otherwise

Expand All @@ -4291,7 +4291,7 @@ void CBaseGame :: BalanceSlots( )
sort( PlayerIDs.begin( ), PlayerIDs.end( ) );

// balancing the teams is a variation of the bin packing problem which is NP
// we can have up to 12 players and/or teams so the scope of the problem is sometimes small enough to process quickly
// we can have up to MAX_SLOTS players and/or teams so the scope of the problem is sometimes small enough to process quickly
// let's try to figure out roughly how much work this is going to take
// examples:
// 2 teams of 4 = 70 ~ 5ms *** ok
Expand All @@ -4306,7 +4306,7 @@ void CBaseGame :: BalanceSlots( )
uint32_t AlgorithmCost = 0;
uint32_t PlayersLeft = PlayerIDs.size( );

for( unsigned char i = 0; i < 12; ++i )
for( unsigned char i = 0; i < MAX_SLOTS; ++i )
{
if( TeamSizes[i] > 0 )
{
Expand Down Expand Up @@ -4339,7 +4339,7 @@ void CBaseGame :: BalanceSlots( )

vector<unsigned char> :: iterator CurrentPID = BestOrdering.begin( );

for( unsigned char i = 0; i < 12; ++i )
for( unsigned char i = 0; i < MAX_SLOTS; ++i )
{
unsigned char CurrentSlot = 0;

Expand Down Expand Up @@ -4377,7 +4377,7 @@ void CBaseGame :: BalanceSlots( )
SendAllChat( m_GHost->m_Language->BalancingSlotsCompleted( ) );
SendAllSlotInfo( );

for( unsigned char i = 0; i < 12; ++i )
for( unsigned char i = 0; i < MAX_SLOTS; ++i )
{
bool TeamHasPlayers = false;
double TeamScore = 0.0;
Expand Down Expand Up @@ -4731,7 +4731,7 @@ void CBaseGame :: CreateFakePlayer( )

if( SID < m_Slots.size( ) )
{
if( GetNumPlayers( ) >= 11 )
if( GetNumPlayers( ) >= MAX_SLOTS-1 )
DeleteVirtualHost( );

m_FakePlayerPID = GetNewPID( );
Expand Down
Loading

0 comments on commit 3f0eb73

Please sign in to comment.