diff --git a/datasrc/network.py b/datasrc/network.py index 8d0bf2469..318007f99 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -273,4 +273,9 @@ Messages = [ NetMessage("cl_vote", [ NetIntRange("vote", -1, 1), ]), + + NetMessage("cl_callvote", [ + NetString("type"), + NetString("value"), + ]), ] diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 2c04c4670..7cac8bcdb 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -690,17 +690,87 @@ void MENUS::render_game(RECT main_view) } } + RECT bars; ui_hsplit_t(&votearea, 10.0f, 0, &votearea); - ui_hsplit_t(&votearea, 25.0f+10.0f*2, &votearea, 0); + ui_hsplit_t(&votearea, 25.0f + 10.0f*3 + 25.0f, &votearea, &bars); ui_draw_rect(&votearea, color_tabbar_active, CORNER_ALL, 10.0f); - ui_vmargin(&votearea, 10.0f, &votearea); + ui_vmargin(&votearea, 20.0f, &votearea); ui_hmargin(&votearea, 10.0f, &votearea); + + ui_hsplit_b(&votearea, 35.0f, &votearea, &bars); + if(gameclient.voting->is_voting()) { + // do yes button + ui_vsplit_l(&votearea, 50.0f, &button, &votearea); + static int yes_button = 0; + if(ui_do_button(&yes_button, "Yes", 0, &button, ui_draw_menu_button, 0)) + gameclient.voting->vote(1); + + // do no button + ui_vsplit_l(&votearea, 5.0f, 0, &votearea); + ui_vsplit_l(&votearea, 50.0f, &button, &votearea); + static int no_button = 0; + if(ui_do_button(&no_button, "No", 0, &button, ui_draw_menu_button, 0)) + gameclient.voting->vote(-1); - } + // do time left + ui_vsplit_r(&votearea, 50.0f, &votearea, &button); + char buf[256]; + str_format(buf, sizeof(buf), "%d", gameclient.voting->seconds_left()); + ui_do_label(&button, buf, 24.0f, 0); + + // do description and command + ui_vsplit_l(&votearea, 5.0f, 0, &votearea); + ui_do_label(&votearea, gameclient.voting->vote_description(), 14.0f, -1); + ui_hsplit_t(&votearea, 16.0f, 0, &votearea); + ui_do_label(&votearea, gameclient.voting->vote_command(), 10.0f, -1); + + // do bars + ui_hsplit_t(&bars, 10.0f, 0, &bars); + ui_hmargin(&bars, 5.0f, &bars); + ui_draw_rect(&bars, vec4(0.8f,0.8f,0.8f,1), CORNER_ALL, 5.0f); + + if(gameclient.voting->total) + { + RECT pass_area = bars; + if(gameclient.voting->yes) + { + RECT yes_area = bars; + yes_area.w *= gameclient.voting->yes/(float)gameclient.voting->total; + ui_draw_rect(&yes_area, vec4(0.4f,0.8f,0.4f,1), CORNER_ALL, 5.0f); + + char buf[256]; + str_format(buf, sizeof(buf), "%d", gameclient.voting->yes); + ui_do_label(&yes_area, buf, 12.0f, 0); + + pass_area.x += yes_area.w; + pass_area.w -= yes_area.w; + } + else if(gameclient.voting->no) + { + RECT no_area = bars; + no_area.w *= gameclient.voting->no/(float)gameclient.voting->total; + no_area.x = (bars.x + bars.w)-no_area.w; + ui_draw_rect(&no_area, vec4(0.8f,0.4f,0.4f,1), CORNER_ALL, 5.0f); + + char buf[256]; + str_format(buf, sizeof(buf), "%d", gameclient.voting->no); + ui_do_label(&no_area, buf, 12.0f, 0); + + pass_area.w -= no_area.w; + } + + if(gameclient.voting->pass) + { + char buf[256]; + str_format(buf, sizeof(buf), "%d", gameclient.voting->pass); + ui_do_label(&pass_area, buf, 12.0f, 0); + } + } + } else { ui_do_label(&votearea, "No vote in progress", 18.0f, -1); diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index b81cfb97d..d90e617fc 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -4,12 +4,29 @@ void VOTING::con_callvote(void *result, void *user_data) { + NETMSG_CL_CALLVOTE msg = {0}; + msg.type = console_arg_string(result, 0); + msg.value = console_arg_string(result, 1); + msg.pack(MSGFLAG_VITAL); + client_send_msg(); } void VOTING::con_vote(void *result, void *user_data) { + VOTING *self = (VOTING *)user_data; + if(str_comp_nocase(console_arg_string(result, 0), "yes") == 0) + self->vote(1); + else if(str_comp_nocase(console_arg_string(result, 0), "no") == 0) + self->vote(-1); } - + +void VOTING::vote(int v) +{ + NETMSG_CL_VOTE msg = {v}; + msg.pack(MSGFLAG_VITAL); + client_send_msg(); +} + VOTING::VOTING() { on_reset(); @@ -26,7 +43,7 @@ void VOTING::on_reset() void VOTING::on_console_init() { - MACRO_REGISTER_COMMAND("callvote", "r", con_callvote, this); + MACRO_REGISTER_COMMAND("callvote", "sr", con_callvote, this); MACRO_REGISTER_COMMAND("vote", "r", con_vote, this); } diff --git a/src/game/client/components/voting.hpp b/src/game/client/components/voting.hpp index 6f518d106..e5338d107 100644 --- a/src/game/client/components/voting.hpp +++ b/src/game/client/components/voting.hpp @@ -29,6 +29,7 @@ public: void vote(int v); // -1 = no, 1 = yes + int seconds_left() { return (closetime - time_get())/time_freq(); } bool is_voting() { return closetime != 0; } int taken_choice() const { return voted; } const char *vote_description() const { return description; } diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index f896a1401..ca335896f 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -264,7 +264,7 @@ void GAMECONTEXT::send_vote_status(int cid) msg.total++; if(players[i]->vote > 0) msg.yes++; - else if(players[i]->vote > 0) + else if(players[i]->vote < 0) msg.no++; else msg.pass++; @@ -302,18 +302,22 @@ void GAMECONTEXT::tick() total++; if(players[i]->vote > 0) yes++; - else if(players[i]->vote > 0) + else if(players[i]->vote < 0) no++; } } - if(yes > (total+1)/2) + if(yes >= (total+1)/2) { console_execute_line(vote_command); vote_closetime = 0; + send_chat(-1, GAMECONTEXT::CHAT_ALL, "Vote passed"); } - else if(time_get() > vote_closetime || no > (total+1)/2) + else if(time_get() > vote_closetime || no >= (total+1)/2) + { + send_chat(-1, GAMECONTEXT::CHAT_ALL, "Vote failed"); vote_closetime = 0; + } } } diff --git a/src/game/server/hooks.cpp b/src/game/server/hooks.cpp index 494f4f627..3a034a970 100644 --- a/src/game/server/hooks.cpp +++ b/src/game/server/hooks.cpp @@ -126,6 +126,33 @@ void mods_message(int msgtype, int client_id) game.send_chat(client_id, team, msg->message); } + else if(msgtype == NETMSGTYPE_CL_CALLVOTE) + { + char chatmsg[512] = {0}; + char desc[512] = {0}; + char cmd[512] = {0}; + NETMSG_CL_CALLVOTE *msg = (NETMSG_CL_CALLVOTE *)rawmsg; + if(str_comp_nocase(msg->type, "map") == 0) + { + str_format(chatmsg, sizeof(chatmsg), "Vote called to change map to '%s'", msg->value); + str_format(desc, sizeof(desc), "Change map to '%s'", msg->value); + str_format(cmd, sizeof(cmd), "sv_map %s", msg->value); + } + + if(cmd[0]) + { + game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chatmsg); + game.start_vote(desc, cmd); + p->vote = 1; + game.send_vote_status(-1); + } + } + else if(msgtype == NETMSGTYPE_CL_VOTE) + { + NETMSG_CL_VOTE *msg = (NETMSG_CL_VOTE *)rawmsg; + p->vote = msg->vote; + game.send_vote_status(-1); + } else if (msgtype == NETMSGTYPE_CL_SETTEAM) { NETMSG_CL_SETTEAM *msg = (NETMSG_CL_SETTEAM *)rawmsg;