ddnet/src/game/client/components/voting.cpp
H-M-H 7ae4b39574 made recording demos work
- videorecorder only works for recording demos now
- demoplayer was modified to allow controll over the time that passed
  in order to get perfect fps, IVideo controlls how much time passed,
  basically every rendercall sets the time to record the next frame
2019-09-30 20:48:47 +08:00

338 lines
8.2 KiB
C++

/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <engine/shared/config.h>
#include <game/generated/protocol.h>
#include <base/vmath.h>
#include <game/client/render.h>
#include "voting.h"
void CVoting::ConCallvote(IConsole::IResult *pResult, void *pUserData)
{
CVoting *pSelf = (CVoting*)pUserData;
pSelf->Callvote(pResult->GetString(0), pResult->GetString(1), pResult->NumArguments() > 2 ? pResult->GetString(2) : "");
}
void CVoting::ConVote(IConsole::IResult *pResult, void *pUserData)
{
CVoting *pSelf = (CVoting *)pUserData;
if(str_comp_nocase(pResult->GetString(0), "yes") == 0)
pSelf->Vote(1);
else if(str_comp_nocase(pResult->GetString(0), "no") == 0)
pSelf->Vote(-1);
}
void CVoting::Callvote(const char *pType, const char *pValue, const char *pReason)
{
CNetMsg_Cl_CallVote Msg = {0};
Msg.m_Type = pType;
Msg.m_Value = pValue;
Msg.m_Reason = pReason;
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
}
void CVoting::CallvoteSpectate(int ClientID, const char *pReason, bool ForceVote)
{
if(ForceVote)
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "set_team %d -1", ClientID);
Client()->Rcon(aBuf);
}
else
{
char aBuf[32];
str_format(aBuf, sizeof(aBuf), "%d", ClientID);
Callvote("spectate", aBuf, pReason);
}
}
void CVoting::CallvoteKick(int ClientID, const char *pReason, bool ForceVote)
{
if(ForceVote)
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "force_vote kick %d %s", ClientID, pReason);
Client()->Rcon(aBuf);
}
else
{
char aBuf[32];
str_format(aBuf, sizeof(aBuf), "%d", ClientID);
Callvote("kick", aBuf, pReason);
}
}
void CVoting::CallvoteOption(int OptionID, const char *pReason, bool ForceVote)
{
CVoteOptionClient *pOption = m_pFirst;
while(pOption && OptionID >= 0)
{
if(OptionID == 0)
{
if(ForceVote)
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "force_vote option \"%s\" %s", pOption->m_aDescription, pReason);
Client()->Rcon(aBuf);
}
else
Callvote("option", pOption->m_aDescription, pReason);
break;
}
OptionID--;
pOption = pOption->m_pNext;
}
}
void CVoting::RemovevoteOption(int OptionID)
{
CVoteOptionClient *pOption = m_pFirst;
while(pOption && OptionID >= 0)
{
if(OptionID == 0)
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "remove_vote \"%s\"", pOption->m_aDescription);
Client()->Rcon(aBuf);
break;
}
OptionID--;
pOption = pOption->m_pNext;
}
}
void CVoting::AddvoteOption(const char *pDescription, const char *pCommand)
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "add_vote \"%s\" %s", pDescription, pCommand);
Client()->Rcon(aBuf);
}
void CVoting::Vote(int v)
{
m_Voted = v;
CNetMsg_Cl_Vote Msg = {v};
Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
}
CVoting::CVoting()
{
ClearOptions();
m_Closetime = 0;
m_aDescription[0] = 0;
m_aReason[0] = 0;
m_Yes = m_No = m_Pass = m_Total = 0;
m_Voted = 0;
}
void CVoting::AddOption(const char *pDescription)
{
CVoteOptionClient *pOption;
if(m_pRecycleFirst)
{
pOption = m_pRecycleFirst;
m_pRecycleFirst = m_pRecycleFirst->m_pNext;
if(m_pRecycleFirst)
m_pRecycleFirst->m_pPrev = 0;
else
m_pRecycleLast = 0;
}
else
pOption = (CVoteOptionClient *)m_Heap.Allocate(sizeof(CVoteOptionClient));
pOption->m_pNext = 0;
pOption->m_pPrev = m_pLast;
if(pOption->m_pPrev)
pOption->m_pPrev->m_pNext = pOption;
m_pLast = pOption;
if(!m_pFirst)
m_pFirst = pOption;
str_copy(pOption->m_aDescription, pDescription, sizeof(pOption->m_aDescription));
++m_NumVoteOptions;
}
void CVoting::ClearOptions()
{
m_Heap.Reset();
m_NumVoteOptions = 0;
m_pFirst = 0;
m_pLast = 0;
m_pRecycleFirst = 0;
m_pRecycleLast = 0;
}
void CVoting::OnReset()
{
m_Closetime = 0;
m_aDescription[0] = 0;
m_aReason[0] = 0;
m_Yes = m_No = m_Pass = m_Total = 0;
m_Voted = 0;
}
void CVoting::OnConsoleInit()
{
Console()->Register("callvote", "s[name] s[command] ?r[reason]", CFGFLAG_CLIENT, ConCallvote, this, "Call vote");
Console()->Register("vote", "r['yes'|'no']", CFGFLAG_CLIENT, ConVote, this, "Vote yes/no");
}
void CVoting::OnMessage(int MsgType, void *pRawMsg)
{
if(MsgType == NETMSGTYPE_SV_VOTESET)
{
CNetMsg_Sv_VoteSet *pMsg = (CNetMsg_Sv_VoteSet *)pRawMsg;
if(pMsg->m_Timeout)
{
OnReset();
str_copy(m_aDescription, pMsg->m_pDescription, sizeof(m_aDescription));
str_copy(m_aReason, pMsg->m_pReason, sizeof(m_aReason));
m_Closetime = time() + time_freq() * pMsg->m_Timeout;
}
else
OnReset();
}
else if(MsgType == NETMSGTYPE_SV_VOTESTATUS)
{
CNetMsg_Sv_VoteStatus *pMsg = (CNetMsg_Sv_VoteStatus *)pRawMsg;
m_Yes = pMsg->m_Yes;
m_No = pMsg->m_No;
m_Pass = pMsg->m_Pass;
m_Total = pMsg->m_Total;
}
else if(MsgType == NETMSGTYPE_SV_VOTECLEAROPTIONS)
{
ClearOptions();
}
else if(MsgType == NETMSGTYPE_SV_VOTEOPTIONLISTADD)
{
CNetMsg_Sv_VoteOptionListAdd *pMsg = (CNetMsg_Sv_VoteOptionListAdd *)pRawMsg;
int NumOptions = pMsg->m_NumOptions;
for(int i = 0; i < NumOptions; ++i)
{
switch(i)
{
case 0: AddOption(pMsg->m_pDescription0); break;
case 1: AddOption(pMsg->m_pDescription1); break;
case 2: AddOption(pMsg->m_pDescription2); break;
case 3: AddOption(pMsg->m_pDescription3); break;
case 4: AddOption(pMsg->m_pDescription4); break;
case 5: AddOption(pMsg->m_pDescription5); break;
case 6: AddOption(pMsg->m_pDescription6); break;
case 7: AddOption(pMsg->m_pDescription7); break;
case 8: AddOption(pMsg->m_pDescription8); break;
case 9: AddOption(pMsg->m_pDescription9); break;
case 10: AddOption(pMsg->m_pDescription10); break;
case 11: AddOption(pMsg->m_pDescription11); break;
case 12: AddOption(pMsg->m_pDescription12); break;
case 13: AddOption(pMsg->m_pDescription13); break;
case 14: AddOption(pMsg->m_pDescription14);
}
}
}
else if(MsgType == NETMSGTYPE_SV_VOTEOPTIONADD)
{
CNetMsg_Sv_VoteOptionAdd *pMsg = (CNetMsg_Sv_VoteOptionAdd *)pRawMsg;
AddOption(pMsg->m_pDescription);
}
else if(MsgType == NETMSGTYPE_SV_VOTEOPTIONREMOVE)
{
CNetMsg_Sv_VoteOptionRemove *pMsg = (CNetMsg_Sv_VoteOptionRemove *)pRawMsg;
for(CVoteOptionClient *pOption = m_pFirst; pOption; pOption = pOption->m_pNext)
{
if(str_comp(pOption->m_aDescription, pMsg->m_pDescription) == 0)
{
// remove it from the list
if(m_pFirst == pOption)
m_pFirst = m_pFirst->m_pNext;
if(m_pLast == pOption)
m_pLast = m_pLast->m_pPrev;
if(pOption->m_pPrev)
pOption->m_pPrev->m_pNext = pOption->m_pNext;
if(pOption->m_pNext)
pOption->m_pNext->m_pPrev = pOption->m_pPrev;
--m_NumVoteOptions;
// add it to recycle list
pOption->m_pNext = 0;
pOption->m_pPrev = m_pRecycleLast;
if(pOption->m_pPrev)
pOption->m_pPrev->m_pNext = pOption;
m_pRecycleLast = pOption;
if(!m_pRecycleFirst)
m_pRecycleLast = pOption;
break;
}
}
}
}
void CVoting::OnRender()
{
}
void CVoting::RenderBars(CUIRect Bars, bool Text)
{
RenderTools()->DrawUIRect(&Bars, ColorRGBA(0.8f,0.8f,0.8f,0.5f), CUI::CORNER_ALL, Bars.h/3);
CUIRect Splitter = Bars;
Splitter.x = Splitter.x+Splitter.w/2;
Splitter.w = Splitter.h/2.0f;
Splitter.x -= Splitter.w/2;
RenderTools()->DrawUIRect(&Splitter, ColorRGBA(0.4f,0.4f,0.4f,0.5f), CUI::CORNER_ALL, Splitter.h/4);
if(m_Total)
{
CUIRect PassArea = Bars;
if(m_Yes)
{
CUIRect YesArea = Bars;
YesArea.w *= m_Yes/(float)m_Total;
RenderTools()->DrawUIRect(&YesArea, ColorRGBA(0.2f,0.9f,0.2f,0.85f), CUI::CORNER_ALL, Bars.h/3);
if(Text)
{
char Buf[256];
str_format(Buf, sizeof(Buf), "%d", m_Yes);
UI()->DoLabel(&YesArea, Buf, Bars.h*0.75f, 0);
}
PassArea.x += YesArea.w;
PassArea.w -= YesArea.w;
}
if(m_No)
{
CUIRect NoArea = Bars;
NoArea.w *= m_No/(float)m_Total;
NoArea.x = (Bars.x + Bars.w)-NoArea.w;
RenderTools()->DrawUIRect(&NoArea, ColorRGBA(0.9f,0.2f,0.2f,0.85f), CUI::CORNER_ALL, Bars.h/3);
if(Text)
{
char Buf[256];
str_format(Buf, sizeof(Buf), "%d", m_No);
UI()->DoLabel(&NoArea, Buf, Bars.h*0.75f, 0);
}
PassArea.w -= NoArea.w;
}
if(Text && m_Pass)
{
char Buf[256];
str_format(Buf, sizeof(Buf), "%d", m_Pass);
UI()->DoLabel(&PassArea, Buf, Bars.h*0.75f, 0);
}
}
}