diff --git a/datasrc/network.py b/datasrc/network.py index 6bfaeea38..911672a62 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -267,7 +267,8 @@ Messages = [ NetMessage("Sv_VoteSet", [ NetIntRange("m_Timeout", 0, 60), - NetStringStrict("m_pDescription") + NetStringStrict("m_pDescription"), + NetStringStrict("m_pReason"), ]), NetMessage("Sv_VoteStatus", [ @@ -324,5 +325,6 @@ Messages = [ NetMessage("Cl_CallVote", [ NetStringStrict("m_Type"), NetStringStrict("m_Value"), + NetStringStrict("m_Reason"), ]), ] diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index a9869bb37..c0273cfe9 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -293,34 +293,40 @@ void CHud::RenderVoting() Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.40f); - RenderTools()->DrawRoundRect(-10, 60-2, 100+10+4+5, 28, 5.0f); + RenderTools()->DrawRoundRect(-10, 60-2, 100+10+4+5, 46, 5.0f); Graphics()->QuadsEnd(); TextRender()->TextColor(1,1,1,1); - char Buf[512]; - str_format(Buf, sizeof(Buf), Localize("%ds left"), m_pClient->m_pVoting->SecondsLeft()); - float tw = TextRender()->TextWidth(0x0, 6, Buf, -1); - CTextCursor Cursor; - TextRender()->SetCursor(&Cursor, 5.0f, 60.0f, 6.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); - Cursor.m_LineWidth = 100-tw; + char aBuf[512]; + str_format(aBuf, sizeof(aBuf), Localize("%ds left"), m_pClient->m_pVoting->SecondsLeft()); + float tw = TextRender()->TextWidth(0x0, 6, aBuf, -1); + TextRender()->SetCursor(&Cursor, 5.0f+100.0f-tw, 60.0f, 6.0f, TEXTFLAG_RENDER); + TextRender()->TextEx(&Cursor, aBuf, -1); + + TextRender()->SetCursor(&Cursor, 5.0f, 60.0f, 6.0f, TEXTFLAG_RENDER); + Cursor.m_LineWidth = 100.0f-tw; + Cursor.m_MaxLines = 3; TextRender()->TextEx(&Cursor, m_pClient->m_pVoting->VoteDescription(), -1); - - TextRender()->Text(0x0, 5+100-tw, 60, 6, Buf, -1); + // reason + str_format(aBuf, sizeof(aBuf), "%s %s", Localize("Reason:"), m_pClient->m_pVoting->VoteReason()); + TextRender()->SetCursor(&Cursor, 5.0f, 79.0f, 6.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); + Cursor.m_LineWidth = 100.0f; + TextRender()->TextEx(&Cursor, aBuf, -1); - CUIRect Base = {5, 70, 100, 4}; + CUIRect Base = {5, 88, 100, 4}; m_pClient->m_pVoting->RenderBars(Base, false); const char *pYesKey = m_pClient->m_pBinds->GetKey("vote yes"); const char *pNoKey = m_pClient->m_pBinds->GetKey("vote no"); - str_format(Buf, sizeof(Buf), "%s - %s", pYesKey, Localize("Vote yes")); + str_format(aBuf, sizeof(aBuf), "%s - %s", pYesKey, Localize("Vote yes")); Base.y += Base.h+1; - UI()->DoLabel(&Base, Buf, 6.0f, -1); + UI()->DoLabel(&Base, aBuf, 6.0f, -1); - str_format(Buf, sizeof(Buf), "%s - %s", Localize("Vote no"), pNoKey); - UI()->DoLabel(&Base, Buf, 6.0f, 1); + str_format(aBuf, sizeof(aBuf), "%s - %s", Localize("Vote no"), pNoKey); + UI()->DoLabel(&Base, aBuf, 6.0f, 1); } void CHud::RenderCursor() diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index c9d39be19..ad43fc20d 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -323,11 +323,6 @@ void CMenus::RenderServerInfo(CUIRect MainView) TextRender()->Text(0, Motd.x+x, Motd.y+y, 16, m_pClient->m_pMotd->m_aServerMotd, (int)Motd.w); } -static const char *FormatCommand(const char *pCmd) -{ - return pCmd; -} - void CMenus::RenderServerControlServer(CUIRect MainView) { int NumOptions = 0; @@ -344,7 +339,7 @@ void CMenus::RenderServerControlServer(CUIRect MainView) CListboxItem Item = UiDoListboxNextItem(pOption); if(Item.m_Visible) - UI()->DoLabelScaled(&Item.m_Rect, FormatCommand(pOption->m_aDescription), 16.0f, -1); + UI()->DoLabelScaled(&Item.m_Rect, pOption->m_aDescription, 16.0f, -1); } m_CallvoteSelectedOption = UiDoListboxEnd(&s_ScrollValue, 0); @@ -440,13 +435,7 @@ void CMenus::RenderServerControl(CUIRect MainView) if(DoButton_Menu(&s_CallVoteButton, Localize("Call vote"), 0, &Button)) { if(s_ControlPage == 0) - { - // - m_pClient->m_pVoting->CallvoteOption(m_CallvoteSelectedOption); - /* - if(callvote_selectedmap >= 0 && callvote_selectedmap < gameclient.maplist->num()) - gameclient.voting->callvote_map(gameclient.maplist->name(callvote_selectedmap));*/ - } + m_pClient->m_pVoting->CallvoteOption(m_CallvoteSelectedOption, m_aCallvoteReason); else if(s_ControlPage == 1) { if(m_CallvoteSelectedPlayer >= 0 && m_CallvoteSelectedPlayer < MAX_CLIENTS && @@ -460,19 +449,16 @@ void CMenus::RenderServerControl(CUIRect MainView) } // render kick reason - if(s_ControlPage == 1) - { - CUIRect Reason; - Bottom.VSplitRight(40.0f, &Bottom, 0); - Bottom.VSplitRight(160.0f, &Bottom, &Reason); - Reason.HSplitTop(5.0f, 0, &Reason); - const char *pLabel = Localize("Reason:"); - UI()->DoLabelScaled(&Reason, pLabel, 14.0f, -1); - float w = TextRender()->TextWidth(0, 14.0f, pLabel, -1); - Reason.VSplitLeft(w+10.0f, 0, &Reason); - static float s_Offset = 0.0f; - DoEditBox(&m_aCallvoteReason, &Reason, m_aCallvoteReason, sizeof(m_aCallvoteReason), 14.0f, &s_Offset, false, CUI::CORNER_ALL); - } + CUIRect Reason; + Bottom.VSplitRight(40.0f, &Bottom, 0); + Bottom.VSplitRight(160.0f, &Bottom, &Reason); + Reason.HSplitTop(5.0f, 0, &Reason); + const char *pLabel = Localize("Reason:"); + UI()->DoLabelScaled(&Reason, pLabel, 14.0f, -1); + float w = TextRender()->TextWidth(0, 14.0f, pLabel, -1); + Reason.VSplitLeft(w+10.0f, 0, &Reason); + static float s_Offset = 0.0f; + DoEditBox(&m_aCallvoteReason, &Reason, m_aCallvoteReason, sizeof(m_aCallvoteReason), 14.0f, &s_Offset, false, CUI::CORNER_ALL); // force vote button (only available when authed in rcon) if(Client()->RconAuthed()) @@ -483,9 +469,7 @@ void CMenus::RenderServerControl(CUIRect MainView) if(DoButton_Menu(&s_ForceVoteButton, Localize("Force vote"), 0, &Button)) { if(s_ControlPage == 0) - { - m_pClient->m_pVoting->ForcevoteOption(m_CallvoteSelectedOption); - } + m_pClient->m_pVoting->ForcevoteOption(m_CallvoteSelectedOption, m_aCallvoteReason); else if(s_ControlPage == 1) { if(m_CallvoteSelectedPlayer >= 0 && m_CallvoteSelectedPlayer < MAX_CLIENTS && diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index 3718a20a7..1f99f4b30 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -5,13 +5,12 @@ #include #include #include -//#include #include "voting.h" void CVoting::ConCallvote(IConsole::IResult *pResult, void *pUserData) { CVoting *pSelf = (CVoting*)pUserData; - pSelf->Callvote(pResult->GetString(0), pResult->GetString(1)); + pSelf->Callvote(pResult->GetString(0), pResult->GetString(1), pResult->NumArguments() > 2 ? pResult->GetString(2) : ""); } void CVoting::ConVote(IConsole::IResult *pResult, void *pUserData) @@ -23,32 +22,30 @@ void CVoting::ConVote(IConsole::IResult *pResult, void *pUserData) pSelf->Vote(-1); } -void CVoting::Callvote(const char *pType, const char *pValue) +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::CallvoteKick(int ClientID, const char *pReason) { char aBuf[32]; - if(pReason[0]) - str_format(aBuf, sizeof(aBuf), "%d %s", ClientID, pReason); - else - str_format(aBuf, sizeof(aBuf), "%d", ClientID); - Callvote("kick", aBuf); + str_format(aBuf, sizeof(aBuf), "%d", ClientID); + Callvote("kick", aBuf, pReason); } -void CVoting::CallvoteOption(int OptionId) +void CVoting::CallvoteOption(int OptionId, const char *pReason) { CVoteOption *pOption = m_pFirst; while(pOption && OptionId >= 0) { if(OptionId == 0) { - Callvote("option", pOption->m_aDescription); + Callvote("option", pOption->m_aDescription, pReason); break; } @@ -57,6 +54,7 @@ void CVoting::CallvoteOption(int OptionId) } } +// TODO: fix these two void CVoting::ForcevoteKick(int ClientID, const char *pReason) { char aBuf[32]; @@ -67,7 +65,7 @@ void CVoting::ForcevoteKick(int ClientID, const char *pReason) Client()->Rcon(aBuf); } -void CVoting::ForcevoteOption(int OptionId) +void CVoting::ForcevoteOption(int OptionId, const char *pReason) { CVoteOption *pOption = m_pFirst; while(pOption && OptionId >= 0) @@ -108,13 +106,14 @@ 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", "sr", CFGFLAG_CLIENT, ConCallvote, this, "Call vote"); + Console()->Register("callvote", "ss?r", CFGFLAG_CLIENT, ConCallvote, this, "Call vote"); Console()->Register("vote", "r", CFGFLAG_CLIENT, ConVote, this, "Vote yes/no"); } @@ -127,6 +126,7 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg) { OnReset(); str_copy(m_aDescription, pMsg->m_pDescription, sizeof(m_aDescription)); + str_copy(m_aReason, pMsg->m_pReason, sizeof(m_aReason)); m_Closetime = time_get() + time_freq() * pMsg->m_Timeout; } else diff --git a/src/game/client/components/voting.h b/src/game/client/components/voting.h index 151ecbfc7..10e0512cb 100644 --- a/src/game/client/components/voting.h +++ b/src/game/client/components/voting.h @@ -15,10 +15,12 @@ class CVoting : public CComponent int64 m_Closetime; char m_aDescription[64]; + char m_aReason[16]; int m_Voted; + int m_Yes, m_No, m_Pass, m_Total; void ClearOptions(); - void Callvote(const char *pType, const char *pValue); + void Callvote(const char *pType, const char *pValue, const char *pReason); public: @@ -41,9 +43,9 @@ public: void RenderBars(CUIRect Bars, bool Text); void CallvoteKick(int ClientID, const char *pReason); - void CallvoteOption(int Option); + void CallvoteOption(int Option, const char *pReason); void ForcevoteKick(int ClientID, const char *pReason); - void ForcevoteOption(int Option); + void ForcevoteOption(int Option, const char *pReason); void Vote(int v); // -1 = no, 1 = yes @@ -51,8 +53,7 @@ public: bool IsVoting() { return m_Closetime != 0; } int TakenChoice() const { return m_Voted; } const char *VoteDescription() const { return m_aDescription; } - - int m_Yes, m_No, m_Pass, m_Total; + const char *VoteReason() const { return m_aReason; } }; #endif diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index a65142c67..f00d2b3c7 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -275,7 +275,7 @@ void CGameContext::SendBroadcast(const char *pText, int ClientID) } // -void CGameContext::StartVote(const char *pDesc, const char *pCommand) +void CGameContext::StartVote(const char *pDesc, const char *pCommand, const char *pReason) { // check if a vote is already running if(m_VoteCloseTime) @@ -296,6 +296,7 @@ void CGameContext::StartVote(const char *pDesc, const char *pCommand) m_VoteCloseTime = time_get() + time_freq()*25; str_copy(m_aVoteDescription, pDesc, sizeof(m_aVoteDescription)); str_copy(m_aVoteCommand, pCommand, sizeof(m_aVoteCommand)); + str_copy(m_aVoteReason, pReason, sizeof(m_aVoteReason)); SendVoteSet(-1); m_VoteUpdate = true; } @@ -314,11 +315,13 @@ void CGameContext::SendVoteSet(int ClientID) { Msg.m_Timeout = (m_VoteCloseTime-time_get())/time_freq(); Msg.m_pDescription = m_aVoteDescription; + Msg.m_pReason = m_aVoteReason; } else { Msg.m_Timeout = 0; Msg.m_pDescription = ""; + Msg.m_pReason = ""; } Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID); } @@ -625,9 +628,11 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) } char aChatmsg[512] = {0}; - char aDesc[512] = {0}; + char aDesc[64] = {0}; char aCmd[512] = {0}; CNetMsg_Cl_CallVote *pMsg = (CNetMsg_Cl_CallVote *)pRawMsg; + const char *pReason = pMsg->m_Reason[0] ? pMsg->m_Reason : "No reason given"; + if(str_comp_nocase(pMsg->m_Type, "option") == 0) { CVoteOption *pOption = m_pVoteOptionFirst; @@ -635,8 +640,9 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) { if(str_comp_nocase(pMsg->m_Value, pOption->m_aDescription) == 0) { - str_format(aChatmsg, sizeof(aChatmsg), "'%s' called vote to change server option '%s'", Server()->ClientName(ClientID), pOption->m_aDescription); - str_format(aDesc, sizeof(aDesc), "%s", pOption->m_aCommand); + str_format(aChatmsg, sizeof(aChatmsg), "'%s' called vote to change server option '%s' (%s)", Server()->ClientName(ClientID), + pOption->m_aDescription, pReason); + str_format(aDesc, sizeof(aDesc), "%s", pOption->m_aDescription); str_format(aCmd, sizeof(aCmd), "%s", pOption->m_aCommand); break; } @@ -694,16 +700,6 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) return; } - const char *pReason = "No reason given"; - for(const char *pStr = pMsg->m_Value; *pStr; ++pStr) - { - if(*pStr == ' ') - { - pReason = pStr+1; - break; - } - } - str_format(aChatmsg, sizeof(aChatmsg), "'%s' called for vote to kick '%s' (%s)", Server()->ClientName(ClientID), Server()->ClientName(KickID), pReason); str_format(aDesc, sizeof(aDesc), "Kick '%s'", Server()->ClientName(KickID)); if (!g_Config.m_SvVoteKickBantime) @@ -719,7 +715,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) if(aCmd[0]) { SendChat(-1, CGameContext::CHAT_ALL, aChatmsg); - StartVote(aDesc, aCmd); + StartVote(aDesc, aCmd, pReason); pPlayer->m_Vote = 1; pPlayer->m_VotePos = m_VotePos = 1; m_VoteCreator = ClientID; diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 19926290c..472f29f8d 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -83,7 +83,7 @@ public: class CCharacter *GetPlayerChar(int ClientID); // voting - void StartVote(const char *pDesc, const char *pCommand); + void StartVote(const char *pDesc, const char *pCommand, const char *pReason); void EndVote(); void SendVoteSet(int ClientID); void SendVoteStatus(int ClientID, int Total, int Yes, int No); @@ -95,6 +95,7 @@ public: int m_VotePos; char m_aVoteDescription[64]; char m_aVoteCommand[512]; + char m_aVoteReason[16]; int m_VoteEnforce; enum {