added support for ai-controlled players #1390

This commit is contained in:
oy 2018-11-25 17:50:57 +01:00
parent 454af88ee5
commit 75350af11d
8 changed files with 103 additions and 19 deletions

View file

@ -6,7 +6,7 @@ Emoticons = Enum("EMOTICON", ["OOP", "EXCLAMATION", "HEARTS", "DROP", "DOTDOT",
Votes = Enum("VOTE", ["UNKNOWN", "START_OP", "START_KICK", "START_SPEC", "END_ABORT", "END_PASS", "END_FAIL"])
ChatModes = Enum("CHAT", ["NONE", "ALL", "TEAM", "WHISPER"])
PlayerFlags = Flags("PLAYERFLAG", ["ADMIN", "CHATTING", "SCOREBOARD", "READY", "DEAD", "WATCHING"])
PlayerFlags = Flags("PLAYERFLAG", ["ADMIN", "CHATTING", "SCOREBOARD", "READY", "DEAD", "WATCHING", "BOT"])
GameFlags = Flags("GAMEFLAG", ["TEAMS", "FLAGS", "SURVIVAL"])
GameStateFlags = Flags("GAMESTATEFLAG", ["WARMUP", "SUDDENDEATH", "ROUNDOVER", "GAMEOVER", "PAUSED", "STARTCOUNTDOWN"])
CoreEventFlags = Flags("COREEVENTFLAG", ["GROUND_JUMP", "AIR_JUMP", "HOOK_ATTACH_PLAYER", "HOOK_ATTACH_GROUND", "HOOK_HIT_NOHOOK"])

View file

@ -828,9 +828,9 @@ int CClient::PlayerScoreComp(const void *a, const void *b)
{
CServerInfo::CClient *p0 = (CServerInfo::CClient *)a;
CServerInfo::CClient *p1 = (CServerInfo::CClient *)b;
if(p0->m_Player && !p1->m_Player)
if(!(p0->m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC) && (p1->m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC))
return -1;
if(!p0->m_Player && p1->m_Player)
if((p0->m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC) && !(p1->m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC))
return 1;
if(p0->m_Score == p1->m_Score)
return 0;
@ -857,6 +857,8 @@ int CClient::UnpackServerInfo(CUnpacker *pUnpacker, CServerInfo *pInfo, int *pTo
pInfo->m_MaxPlayers = pUnpacker->GetInt();
pInfo->m_NumClients = pUnpacker->GetInt();
pInfo->m_MaxClients = pUnpacker->GetInt();
pInfo->m_NumBotPlayers = 0;
pInfo->m_NumBotSpectators = 0;
// don't add invalid info to the server browser list
if(pInfo->m_NumClients < 0 || pInfo->m_NumClients > MAX_CLIENTS || pInfo->m_MaxClients < 0 || pInfo->m_MaxClients > MAX_CLIENTS ||
@ -867,14 +869,30 @@ int CClient::UnpackServerInfo(CUnpacker *pUnpacker, CServerInfo *pInfo, int *pTo
if(!pToken)
return 0;
int NumPlayers = 0;
int NumClients = 0;
for(int i = 0; i < pInfo->m_NumClients; i++)
{
str_copy(pInfo->m_aClients[i].m_aName, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aClients[i].m_aName));
str_copy(pInfo->m_aClients[i].m_aClan, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aClients[i].m_aClan));
pInfo->m_aClients[i].m_Country = pUnpacker->GetInt();
pInfo->m_aClients[i].m_Score = pUnpacker->GetInt();
pInfo->m_aClients[i].m_Player = pUnpacker->GetInt() != 0 ? true : false;
pInfo->m_aClients[i].m_PlayerType = pUnpacker->GetInt()&CServerInfo::CClient::PLAYERFLAG_MASK;
if(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_BOT)
{
if(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC)
pInfo->m_NumBotSpectators++;
else
pInfo->m_NumBotPlayers++;
}
NumClients++;
if(!(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC))
NumPlayers++;
}
pInfo->m_NumPlayers = NumPlayers;
pInfo->m_NumClients = NumClients;
return 0;
}

View file

@ -44,6 +44,7 @@ void CServerBrowser::CServerlist::Clear()
m_ServerlistHeap.Reset();
m_NumServers = 0;
m_NumPlayers = 0;
m_NumClients = 0;
mem_zero(m_aServerlistIp, sizeof(m_aServerlistIp));
}
@ -545,6 +546,7 @@ void CServerBrowser::SetInfo(int ServerlistType, CServerEntry *pEntry, const CSe
pEntry->m_Info.m_NetAddr = pEntry->m_Addr;
m_aServerlist[ServerlistType].m_NumPlayers += pEntry->m_Info.m_NumPlayers;
m_aServerlist[ServerlistType].m_NumClients += pEntry->m_Info.m_NumClients;
pEntry->m_InfoState = CServerEntry::STATE_READY;
}

View file

@ -32,6 +32,7 @@ public:
int NumServers() const { return m_aServerlist[m_ActServerlistType].m_NumServers; }
int NumPlayers() const { return m_aServerlist[m_ActServerlistType].m_NumPlayers; }
int NumClients() const { return m_aServerlist[m_ActServerlistType].m_NumClients; }
const CServerInfo *Get(int Index) const { return &m_aServerlist[m_ActServerlistType].m_ppServerlist[Index]->m_Info; };
int NumSortedServers(int FilterIndex) const { return m_ServerBrowserFilter.GetNumSortedServers(FilterIndex); }
@ -72,6 +73,7 @@ private:
public:
class CHeap m_ServerlistHeap;
int m_NumClients;
int m_NumPlayers;
int m_NumServers;
int m_NumServerCapacity;

View file

@ -201,7 +201,15 @@ void CServerBrowserFilter::CServerFilter::Filter()
if(!(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_FRIENDS) || m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_FriendState != IFriends::FRIEND_NO)
{
m_pSortedServerlist[m_NumSortedServers++] = i;
m_NumSortedPlayers += (m_FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS) ? m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumPlayers : m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumClients;
int Count = (m_FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS) ? m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumPlayers : m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumClients;
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_BOTS)
{
Count -= m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumBotPlayers;
if(!(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS))
Count -= m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumBotSpectators;
}
m_NumSortedPlayers += Count;
}
}
}
@ -209,8 +217,9 @@ void CServerBrowserFilter::CServerFilter::Filter()
int CServerBrowserFilter::CServerFilter::GetSortHash() const
{
int i = g_Config.m_BrSort&0xf;
i |= g_Config.m_BrSortOrder<<4;
int i = g_Config.m_BrSort&0x7;
i |= g_Config.m_BrSortOrder<<3;
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_BOTS) i |= 1 << 4;
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_EMPTY) i |= 1<<5;
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_FULL) i |= 1<<6;
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS) i |= 1<<7;

View file

@ -1100,7 +1100,7 @@ void CServer::GenerateServerInfo(CPacker *pPacker, int Token)
pPacker->AddString(ClientClan(i), MAX_CLAN_LENGTH); // client clan
pPacker->AddInt(m_aClients[i].m_Country); // client country
pPacker->AddInt(m_aClients[i].m_Score); // client score
pPacker->AddInt(GameServer()->IsClientPlayer(i)?1:0); // is player?
pPacker->AddInt(GameServer()->IsClientPlayer(i)?0:1); // flag spectator=1, bot=2 (player=0)
}
}
}

View file

@ -23,9 +23,16 @@ public:
char m_aClan[MAX_CLAN_LENGTH];
int m_Country;
int m_Score;
bool m_Player;
int m_PlayerType;
int m_FriendState;
enum
{
PLAYERFLAG_SPEC=1,
PLAYERFLAG_BOT=2,
PLAYERFLAG_MASK=3,
};
};
//int m_SortedIndex;
@ -40,6 +47,8 @@ public:
int m_NumClients;
int m_MaxPlayers;
int m_NumPlayers;
int m_NumBotPlayers;
int m_NumBotSpectators;
int m_Flags;
int m_ServerLevel;
int m_Favorite;
@ -102,6 +111,7 @@ public:
FLAG_PURE=2,
FLAG_PUREMAP=4,
FILTER_BOTS=16,
FILTER_EMPTY=32,
FILTER_FULL=64,
FILTER_SPECTATORS=128,
@ -123,6 +133,7 @@ public:
virtual int NumServers() const = 0;
virtual int NumPlayers() const = 0;
virtual int NumClients() const = 0;
virtual const CServerInfo *Get(int Index) const = 0;
virtual int NumSortedServers(int Index) const = 0;

View file

@ -507,10 +507,26 @@ int CMenus::DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEn
CServerFilterInfo FilterInfo;
pFilter->GetFilter(&FilterInfo);
int Num = (FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS) ? pEntry->m_NumPlayers : pEntry->m_NumClients;
int Max = (FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS) ? pEntry->m_MaxPlayers : pEntry->m_MaxClients;
if(FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS)
str_format(aTemp, sizeof(aTemp), "%d/%d", pEntry->m_NumPlayers, pEntry->m_MaxPlayers);
else
str_format(aTemp, sizeof(aTemp), "%d/%d", pEntry->m_NumClients, pEntry->m_MaxClients);
{
int SpecNum = pEntry->m_NumClients - pEntry->m_NumPlayers;
if(pEntry->m_MaxClients - pEntry->m_MaxPlayers < SpecNum)
Max -= SpecNum;
}
if(FilterInfo.m_SortHash&IServerBrowser::FILTER_BOTS)
{
Num -= pEntry->m_NumBotPlayers;
Max -= pEntry->m_NumBotPlayers;
if(!(FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS))
{
Num -= pEntry->m_NumBotSpectators;
Max -= pEntry->m_NumBotSpectators;
}
}
str_format(aTemp, sizeof(aTemp), "%d/%d", Num, Max);
if(g_Config.m_BrFilterString[0] && (pEntry->m_QuickSearchHit&IServerBrowser::QUICK_PLAYER))
TextRender()->TextColor(0.4f, 0.4f, 1.0f, TextAlpha);
Button.y += 2.0f;
@ -797,7 +813,7 @@ void CMenus::RenderServerbrowserOverlay()
Name.VSplitRight(40.0f, &Name, &Clan);
// score
if(pInfo->m_aClients[i].m_Player)
if(!(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC))
{
char aTemp[16];
str_format(aTemp, sizeof(aTemp), "%d", pInfo->m_aClients[i].m_Score);
@ -1141,7 +1157,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
CUIRect OriginalView = View;
View.y -= s_ScrollValue*ScrollNum*LineH;
int NumPlayers = ServerBrowser()->NumPlayers();
int NumPlayers = ServerBrowser()->NumClients();
for(int s = 0; s < m_lFilters.size(); s++)
{
@ -1362,7 +1378,7 @@ void CMenus::RenderServerbrowserFriendTab(CUIRect View)
FriendItem.m_pServerInfo = pEntry;
str_copy(FriendItem.m_aName, pEntry->m_aClients[j].m_aName, sizeof(FriendItem.m_aName));
str_copy(FriendItem.m_aClan, pEntry->m_aClients[j].m_aClan, sizeof(FriendItem.m_aClan));
FriendItem.m_IsPlayer = pEntry->m_aClients[j].m_Player;
FriendItem.m_IsPlayer = !(pEntry->m_aClients[j].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC);
if(pEntry->m_aClients[j].m_FriendState == IFriends::FRIEND_PLAYER)
m_lFriendList[0].add(FriendItem);
@ -1596,6 +1612,11 @@ void CMenus::RenderServerbrowserFilterTab(CUIRect View)
if(DoButton_CheckBox(&s_BrFilterFriends, Localize("Show friends only"), FilterInfo.m_SortHash&IServerBrowser::FILTER_FRIENDS, &Button))
NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_FRIENDS;
ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter);
static int s_BrFilterBots = 0;
if(DoButton_CheckBox(&s_BrFilterBots, Localize("Hide Bots"), FilterInfo.m_SortHash&IServerBrowser::FILTER_BOTS, &Button))
NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_BOTS;
ServerFilter.HSplitTop(LineSize, &Button, &ServerFilter);
static int s_BrFilterPw = 0;
if(DoButton_CheckBox(&s_BrFilterPw, Localize("No password"), FilterInfo.m_SortHash&IServerBrowser::FILTER_PW, &Button))
@ -1900,8 +1921,23 @@ void CMenus::RenderDetailInfo(CUIRect View, const CServerInfo *pInfo)
void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int Column)
{
// slected filter
CBrowserFilter *pFilter = 0;
for(int i = 0; i < m_lFilters.size(); ++i)
{
if(m_lFilters[i].Extended())
{
pFilter = &m_lFilters[i];
m_SelectedFilter = i;
break;
}
}
if(!pFilter)
return;
CServerFilterInfo FilterInfo;
pFilter->GetFilter(&FilterInfo);
// server scoreboard
// CUIRect ServerHeader;
CTextCursor Cursor;
const float FontSize = 10.0f;
int ActColumn = 0;
@ -1911,17 +1947,21 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int
if(pInfo)
{
CUIRect Row = View;
int Count = 0;
for(int i = 0; i < pInfo->m_NumClients; i++)
{
if((FilterInfo.m_SortHash&IServerBrowser::FILTER_BOTS) && (pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_BOT))
continue;
CUIRect Name, Clan, Score, Flag, Icon;
if(i % (16 / Column) == 0)
if(Count % (16 / Column) == 0)
{
View.VSplitLeft(View.w / (Column - ActColumn), &Row, &View);
ActColumn++;
}
Row.HSplitTop(20.0f, &Name, &Row);
RenderTools()->DrawUIRect(&Name, vec4(1.0f, 1.0f, 1.0f, (i % 2 + 1)*0.05f), CUI::CORNER_ALL, 4.0f);
RenderTools()->DrawUIRect(&Name, vec4(1.0f, 1.0f, 1.0f, (Count % 2 + 1)*0.05f), CUI::CORNER_ALL, 4.0f);
// friend
if(UI()->DoButtonLogic(&pInfo->m_aClients[i], "", 0, &Name))
@ -1945,7 +1985,7 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int
Name.HSplitTop(10.0f, &Name, &Clan);
// score
if(pInfo->m_aClients[i].m_Player)
if(!(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC))
{
char aTemp[16];
str_format(aTemp, sizeof(aTemp), "%d", pInfo->m_aClients[i].m_Score);
@ -2002,6 +2042,8 @@ void CMenus::RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int
Flag.w = Flag.h*2;
vec4 Color(1.0f, 1.0f, 1.0f, 0.5f);
m_pClient->m_pCountryFlags->Render(pInfo->m_aClients[i].m_Country, &Color, Flag.x, Flag.y, Flag.w, Flag.h);
++Count;
}
}
}