diff options
| -rw-r--r-- | datasrc/network.py | 21 | ||||
| -rw-r--r-- | src/game/client/components/menus.cpp | 22 | ||||
| -rw-r--r-- | src/game/client/components/voting.cpp | 61 | ||||
| -rw-r--r-- | src/game/client/components/voting.hpp | 39 | ||||
| -rw-r--r-- | src/game/client/gameclient.cpp | 4 | ||||
| -rw-r--r-- | src/game/client/gameclient.hpp | 1 | ||||
| -rw-r--r-- | src/game/server/gamecontext.cpp | 91 | ||||
| -rw-r--r-- | src/game/server/gamecontext.hpp | 9 | ||||
| -rw-r--r-- | src/game/server/player.hpp | 3 |
9 files changed, 246 insertions, 5 deletions
diff --git a/datasrc/network.py b/datasrc/network.py index 0f1d3496..8d0bf246 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -224,7 +224,19 @@ Messages = [ NetIntRange("cid", 0, 'MAX_CLIENTS-1'), NetIntRange("emoticon", 0, 'NUM_EMOTICONS-1'), ]), - + + NetMessage("sv_vote_set", [ + NetIntRange("timeout", 0, 60), + NetString("description"), + NetString("command"), + ]), + + NetMessage("sv_vote_status", [ + NetIntRange("yes", 0, 'MAX_CLIENTS'), + NetIntRange("no", 0, 'MAX_CLIENTS'), + NetIntRange("pass", 0, 'MAX_CLIENTS'), + NetIntRange("total", 0, 'MAX_CLIENTS'), + ]), ### Client messages NetMessage("cl_say", [ @@ -251,11 +263,14 @@ Messages = [ NetIntAny("color_body"), NetIntAny("color_feet"), ]), - + NetMessage("cl_kill", []), NetMessage("cl_emoticon", [ NetIntRange("emoticon", 0, 'NUM_EMOTICONS-1'), ]), - + + NetMessage("cl_vote", [ + NetIntRange("vote", -1, 1), + ]), ] diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 36bf6378..6c28138d 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -23,6 +23,7 @@ extern "C" { #include <game/generated/gc_data.hpp> #include <game/client/components/binds.hpp> #include <game/client/components/motd.hpp> +#include <game/client/components/voting.hpp> #include <game/client/gameclient.hpp> #include <game/client/animstate.hpp> #include <game/client/gc_render.hpp> @@ -620,8 +621,8 @@ void MENUS::render_news(RECT main_view) void MENUS::render_game(RECT main_view) { - RECT button; - ui_hsplit_t(&main_view, 45.0f, &main_view, 0); + RECT button, votearea; + ui_hsplit_t(&main_view, 45.0f, &main_view, &votearea); ui_draw_rect(&main_view, color_tabbar_active, CORNER_ALL, 10.0f); ui_hsplit_t(&main_view, 10.0f, 0, &main_view); @@ -688,6 +689,23 @@ void MENUS::render_game(RECT main_view) } } } + + ui_hsplit_t(&votearea, 10.0f, 0, &votearea); + ui_hsplit_t(&votearea, 25.0f+10.0f*2, &votearea, 0); + + ui_draw_rect(&votearea, color_tabbar_active, CORNER_ALL, 10.0f); + + ui_vmargin(&votearea, 10.0f, &votearea); + ui_hmargin(&votearea, 10.0f, &votearea); + if(gameclient.voting->is_voting()) + { + + } + else + { + ui_do_label(&votearea, "No vote in progress", 18.0f, -1); + } + } void MENUS::render_serverinfo(RECT main_view) diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp new file mode 100644 index 00000000..b81cfb97 --- /dev/null +++ b/src/game/client/components/voting.cpp @@ -0,0 +1,61 @@ +#include <engine/e_client_interface.h> +#include <game/generated/g_protocol.hpp> +#include "voting.hpp" + +void VOTING::con_callvote(void *result, void *user_data) +{ +} + +void VOTING::con_vote(void *result, void *user_data) +{ +} + +VOTING::VOTING() +{ + on_reset(); +} + +void VOTING::on_reset() +{ + closetime = 0; + description[0] = 0; + command[0] = 0; + yes = no = pass = total = 0; + voted = 0; +} + +void VOTING::on_console_init() +{ + MACRO_REGISTER_COMMAND("callvote", "r", con_callvote, this); + MACRO_REGISTER_COMMAND("vote", "r", con_vote, this); +} + +void VOTING::on_message(int msgtype, void *rawmsg) +{ + if(msgtype == NETMSGTYPE_SV_VOTE_SET) + { + NETMSG_SV_VOTE_SET *msg = (NETMSG_SV_VOTE_SET *)rawmsg; + if(msg->timeout) + { + on_reset(); + str_copy(description, msg->description, sizeof(description)); + str_copy(command, msg->command, sizeof(description)); + closetime = time_get() + time_freq() * msg->timeout; + } + else + on_reset(); + } + else if(msgtype == NETMSGTYPE_SV_VOTE_STATUS) + { + NETMSG_SV_VOTE_STATUS *msg = (NETMSG_SV_VOTE_STATUS *)rawmsg; + yes = msg->yes; + no = msg->no; + pass = msg->pass; + total = msg->total; + } +} + +void VOTING::on_render() +{ +} + diff --git a/src/game/client/components/voting.hpp b/src/game/client/components/voting.hpp new file mode 100644 index 00000000..6f518d10 --- /dev/null +++ b/src/game/client/components/voting.hpp @@ -0,0 +1,39 @@ +#include <game/client/component.hpp> + +class VOTING : public COMPONENT +{ + /* + void render_goals(float x, float y, float w); + void render_spectators(float x, float y, float w); + void render_scoreboard(float x, float y, float w, int team, const char *title); + + static void con_key_scoreboard(void *result, void *user_data); + + bool active; + */ + + static void con_callvote(void *result, void *user_data); + static void con_vote(void *result, void *user_data); + + int64 closetime; + char description[512]; + char command[512]; + int voted; + +public: + VOTING(); + virtual void on_reset(); + virtual void on_console_init(); + virtual void on_message(int msgtype, void *rawmsg); + virtual void on_render(); + + void vote(int v); // -1 = no, 1 = yes + + bool is_voting() { return closetime != 0; } + int taken_choice() const { return voted; } + const char *vote_description() const { return description; } + const char *vote_command() const { return command; } + + int yes, no, pass, total; +}; + diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 5ae98ced..e1634706 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -32,6 +32,7 @@ #include "components/scoreboard.hpp" #include "components/skins.hpp" #include "components/sounds.hpp" +#include "components/voting.hpp" GAMECLIENT gameclient; @@ -55,6 +56,7 @@ static SCOREBOARD scoreboard; static SOUNDS sounds; static EMOTICON emoticon; static DAMAGEIND damageind; +static VOTING voting; static PLAYERS players; static NAMEPLATES nameplates; @@ -105,6 +107,7 @@ void GAMECLIENT::on_console_init() motd = &::motd; damageind = &::damageind; mapimages = &::mapimages; + voting = &::voting; // make a list of all the systems, make sure to add them in the corrent render order all.add(skins); @@ -115,6 +118,7 @@ void GAMECLIENT::on_console_init() all.add(controls); all.add(camera); all.add(sounds); + all.add(voting); all.add(particles); // doesn't render anything, just updates all the particles all.add(&maplayers_background); // first to render diff --git a/src/game/client/gameclient.hpp b/src/game/client/gameclient.hpp index 4b397e86..c1e60c2c 100644 --- a/src/game/client/gameclient.hpp +++ b/src/game/client/gameclient.hpp @@ -137,6 +137,7 @@ public: class SOUNDS *sounds; class MOTD *motd; class MAPIMAGES *mapimages; + class VOTING *voting; }; extern GAMECLIENT gameclient; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 987ce64e..f896a140 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -8,6 +8,8 @@ GAMECONTEXT::GAMECONTEXT() { for(int i = 0; i < MAX_CLIENTS; i++) players[i] = 0; + + vote_closetime = 0; } GAMECONTEXT::~GAMECONTEXT() @@ -211,6 +213,69 @@ void GAMECONTEXT::send_broadcast(const char *text, int cid) +// +void GAMECONTEXT::start_vote(const char *desc, const char *command) +{ + // check if a vote is already running + if(vote_closetime) + return; + + // reset votes + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(players[i]) + players[i]->vote = 0; + } + + // start vote + vote_closetime = time_get() + time_freq()*10; + str_copy(vote_description, desc, sizeof(vote_description)); + str_copy(vote_command, command, sizeof(vote_description)); + send_vote_set(-1); + send_vote_status(-1); +} + +void GAMECONTEXT::send_vote_set(int cid) +{ + NETMSG_SV_VOTE_SET msg; + if(vote_closetime) + { + msg.timeout = (vote_closetime-time_get())/time_freq(); + msg.description = vote_description; + msg.command = vote_command; + } + else + { + msg.timeout = 0; + msg.description = ""; + msg.command = ""; + } + msg.pack(MSGFLAG_VITAL); + server_send_msg(cid); +} + +void GAMECONTEXT::send_vote_status(int cid) +{ + NETMSG_SV_VOTE_STATUS msg = {0}; + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(players[i]) + { + msg.total++; + if(players[i]->vote > 0) + msg.yes++; + else if(players[i]->vote > 0) + msg.no++; + else + msg.pass++; + } + } + + msg.pack(MSGFLAG_VITAL); + server_send_msg(cid); + +} + void GAMECONTEXT::tick() { world.core.tuning = tuning; @@ -224,6 +289,32 @@ void GAMECONTEXT::tick() if(players[i]) players[i]->tick(); } + + // update voting + if(vote_closetime) + { + // count votes + int total = 0, yes = 0, no = 0; + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(players[i]) + { + total++; + if(players[i]->vote > 0) + yes++; + else if(players[i]->vote > 0) + no++; + } + } + + if(yes > (total+1)/2) + { + console_execute_line(vote_command); + vote_closetime = 0; + } + else if(time_get() > vote_closetime || no > (total+1)/2) + vote_closetime = 0; + } } void GAMECONTEXT::snap(int client_id) diff --git a/src/game/server/gamecontext.hpp b/src/game/server/gamecontext.hpp index dd10ec4d..83ada09f 100644 --- a/src/game/server/gamecontext.hpp +++ b/src/game/server/gamecontext.hpp @@ -43,6 +43,14 @@ public: void tick(); void snap(int client_id); + + // voting + void start_vote(const char *desc, const char *command); + void send_vote_set(int cid); + void send_vote_status(int cid); + int64 vote_closetime; + char vote_description[512]; + char vote_command[512]; // helper functions void create_damageind(vec2 p, float angle_mod, int amount); @@ -68,6 +76,7 @@ public: void send_weapon_pickup(int cid, int weapon); void send_broadcast(const char *text, int cid); void send_info(int who, int to_who); + }; extern GAMECONTEXT game; diff --git a/src/game/server/player.hpp b/src/game/server/player.hpp index c92265a8..f483ecf9 100644 --- a/src/game/server/player.hpp +++ b/src/game/server/player.hpp @@ -26,6 +26,9 @@ public: int team; int score; bool force_balanced; + + // + int vote; // int64 last_chat; |