about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/engine/e_keynames.c805
-rw-r--r--src/engine/e_keys.h1
-rw-r--r--src/game/client/components/binds.cpp22
-rw-r--r--src/game/client/components/binds.hpp1
-rw-r--r--src/game/client/components/hud.cpp28
-rw-r--r--src/game/client/components/hud.hpp1
-rw-r--r--src/game/client/components/menus.cpp48
-rw-r--r--src/game/client/components/menus_settings.cpp2
-rw-r--r--src/game/client/components/voting.cpp61
-rw-r--r--src/game/client/components/voting.hpp3
-rw-r--r--src/game/server/entities/character.cpp3
-rw-r--r--src/game/server/gamecontext.cpp5
-rw-r--r--src/game/server/gamecontext.hpp1
-rw-r--r--src/game/server/hooks.cpp30
-rw-r--r--src/game/server/player.hpp1
15 files changed, 555 insertions, 457 deletions
diff --git a/src/engine/e_keynames.c b/src/engine/e_keynames.c
index fa87467d..64ac7642 100644
--- a/src/engine/e_keynames.c
+++ b/src/engine/e_keynames.c
@@ -1,58 +1,57 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
 /* AUTO GENERATED! DO NOT EDIT MANUALLY! */
 
 #include <string.h>
 
 static const char key_strings[512][16] =
 {
-	"#0",
-	"#1",
-	"#2",
-	"#3",
-	"#4",
-	"#5",
-	"#6",
-	"#7",
-	"#8",
-	"#9",
-	"#10",
-	"#11",
-	"#12",
-	"#13",
-	"#14",
-	"#15",
-	"#16",
-	"#17",
-	"#18",
-	"#19",
-	"#20",
-	"#21",
-	"#22",
-	"#23",
-	"#24",
-	"#25",
-	"#26",
-	"#27",
-	"#28",
-	"#29",
-	"#30",
-	"#31",
+	"&0",
+	"&1",
+	"&2",
+	"&3",
+	"&4",
+	"&5",
+	"&6",
+	"&7",
+	"&8",
+	"&9",
+	"&10",
+	"&11",
+	"&12",
+	"&13",
+	"&14",
+	"&15",
+	"&16",
+	"&17",
+	"&18",
+	"&19",
+	"&20",
+	"&21",
+	"&22",
+	"&23",
+	"&24",
+	"&25",
+	"&26",
+	"&27",
+	"&28",
+	"&29",
+	"&30",
+	"&31",
 	"space",
-	"#33",
-	"#34",
-	"#35",
-	"#36",
-	"#37",
-	"#38",
-	"#39",
-	"#40",
-	"#41",
-	"#42",
-	"#43",
-	"#44",
-	"#45",
-	"#46",
-	"#47",
+	"&33",
+	"&34",
+	"&35",
+	"&36",
+	"&37",
+	"&38",
+	"&39",
+	"&40",
+	"&41",
+	"&42",
+	"&43",
+	"&44",
+	"&45",
+	"&46",
+	"&47",
 	"0",
 	"1",
 	"2",
@@ -63,13 +62,13 @@ static const char key_strings[512][16] =
 	"7",
 	"8",
 	"9",
-	"#58",
-	"#59",
-	"#60",
-	"#61",
-	"#62",
-	"#63",
-	"#64",
+	"&58",
+	"&59",
+	"&60",
+	"&61",
+	"&62",
+	"&63",
+	"&64",
 	"a",
 	"b",
 	"c",
@@ -96,171 +95,171 @@ static const char key_strings[512][16] =
 	"x",
 	"y",
 	"z",
-	"#91",
-	"#92",
-	"#93",
-	"#94",
-	"#95",
-	"#96",
-	"#97",
-	"#98",
-	"#99",
-	"#100",
-	"#101",
-	"#102",
-	"#103",
-	"#104",
-	"#105",
-	"#106",
-	"#107",
-	"#108",
-	"#109",
-	"#110",
-	"#111",
-	"#112",
-	"#113",
-	"#114",
-	"#115",
-	"#116",
-	"#117",
-	"#118",
-	"#119",
-	"#120",
-	"#121",
-	"#122",
-	"#123",
-	"#124",
-	"#125",
-	"#126",
-	"#127",
-	"#128",
-	"#129",
-	"#130",
-	"#131",
-	"#132",
-	"#133",
-	"#134",
-	"#135",
-	"#136",
-	"#137",
-	"#138",
-	"#139",
-	"#140",
-	"#141",
-	"#142",
-	"#143",
-	"#144",
-	"#145",
-	"#146",
-	"#147",
-	"#148",
-	"#149",
-	"#150",
-	"#151",
-	"#152",
-	"#153",
-	"#154",
-	"#155",
-	"#156",
-	"#157",
-	"#158",
-	"#159",
-	"#160",
-	"#161",
-	"#162",
-	"#163",
-	"#164",
-	"#165",
-	"#166",
-	"#167",
-	"#168",
-	"#169",
-	"#170",
-	"#171",
-	"#172",
-	"#173",
-	"#174",
-	"#175",
-	"#176",
-	"#177",
-	"#178",
-	"#179",
-	"#180",
-	"#181",
-	"#182",
-	"#183",
-	"#184",
-	"#185",
-	"#186",
-	"#187",
-	"#188",
-	"#189",
-	"#190",
-	"#191",
-	"#192",
-	"#193",
-	"#194",
-	"#195",
-	"#196",
-	"#197",
-	"#198",
-	"#199",
-	"#200",
-	"#201",
-	"#202",
-	"#203",
-	"#204",
-	"#205",
-	"#206",
-	"#207",
-	"#208",
-	"#209",
-	"#210",
-	"#211",
-	"#212",
-	"#213",
-	"#214",
-	"#215",
-	"#216",
-	"#217",
-	"#218",
-	"#219",
-	"#220",
-	"#221",
-	"#222",
-	"#223",
-	"#224",
-	"#225",
-	"#226",
-	"#227",
-	"#228",
-	"#229",
-	"#230",
-	"#231",
-	"#232",
-	"#233",
-	"#234",
-	"#235",
-	"#236",
-	"#237",
-	"#238",
-	"#239",
-	"#240",
-	"#241",
-	"#242",
-	"#243",
-	"#244",
-	"#245",
-	"#246",
-	"#247",
-	"#248",
-	"#249",
-	"#250",
-	"#251",
-	"#252",
-	"#253",
-	"#254",
-	"#255",
+	"&91",
+	"&92",
+	"&93",
+	"&94",
+	"&95",
+	"&96",
+	"&97",
+	"&98",
+	"&99",
+	"&100",
+	"&101",
+	"&102",
+	"&103",
+	"&104",
+	"&105",
+	"&106",
+	"&107",
+	"&108",
+	"&109",
+	"&110",
+	"&111",
+	"&112",
+	"&113",
+	"&114",
+	"&115",
+	"&116",
+	"&117",
+	"&118",
+	"&119",
+	"&120",
+	"&121",
+	"&122",
+	"&123",
+	"&124",
+	"&125",
+	"&126",
+	"&127",
+	"&128",
+	"&129",
+	"&130",
+	"&131",
+	"&132",
+	"&133",
+	"&134",
+	"&135",
+	"&136",
+	"&137",
+	"&138",
+	"&139",
+	"&140",
+	"&141",
+	"&142",
+	"&143",
+	"&144",
+	"&145",
+	"&146",
+	"&147",
+	"&148",
+	"&149",
+	"&150",
+	"&151",
+	"&152",
+	"&153",
+	"&154",
+	"&155",
+	"&156",
+	"&157",
+	"&158",
+	"&159",
+	"&160",
+	"&161",
+	"&162",
+	"&163",
+	"&164",
+	"&165",
+	"&166",
+	"&167",
+	"&168",
+	"&169",
+	"&170",
+	"&171",
+	"&172",
+	"&173",
+	"&174",
+	"&175",
+	"&176",
+	"&177",
+	"&178",
+	"&179",
+	"&180",
+	"&181",
+	"&182",
+	"&183",
+	"&184",
+	"&185",
+	"&186",
+	"&187",
+	"&188",
+	"&189",
+	"&190",
+	"&191",
+	"&192",
+	"&193",
+	"&194",
+	"&195",
+	"&196",
+	"&197",
+	"&198",
+	"&199",
+	"&200",
+	"&201",
+	"&202",
+	"&203",
+	"&204",
+	"&205",
+	"&206",
+	"&207",
+	"&208",
+	"&209",
+	"&210",
+	"&211",
+	"&212",
+	"&213",
+	"&214",
+	"&215",
+	"&216",
+	"&217",
+	"&218",
+	"&219",
+	"&220",
+	"&221",
+	"&222",
+	"&223",
+	"&224",
+	"&225",
+	"&226",
+	"&227",
+	"&228",
+	"&229",
+	"&230",
+	"&231",
+	"&232",
+	"&233",
+	"&234",
+	"&235",
+	"&236",
+	"&237",
+	"&238",
+	"&239",
+	"&240",
+	"&241",
+	"&242",
+	"&243",
+	"&244",
+	"&245",
+	"&246",
+	"&247",
+	"&248",
+	"&249",
+	"&250",
+	"&251",
+	"&252",
+	"&253",
+	"&254",
+	"&255",
 	"special",
 	"esc",
 	"f1",
@@ -324,69 +323,69 @@ static const char key_strings[512][16] =
 	"kpdecimal",
 	"kpequal",
 	"kpenter",
-	"#319",
-	"#320",
-	"#321",
-	"#322",
-	"#323",
-	"#324",
-	"#325",
-	"#326",
-	"#327",
-	"#328",
-	"#329",
-	"#330",
-	"#331",
-	"#332",
-	"#333",
-	"#334",
-	"#335",
-	"#336",
-	"#337",
-	"#338",
-	"#339",
-	"#340",
-	"#341",
-	"#342",
-	"#343",
-	"#344",
-	"#345",
-	"#346",
-	"#347",
-	"#348",
-	"#349",
-	"#350",
-	"#351",
-	"#352",
-	"#353",
-	"#354",
-	"#355",
-	"#356",
-	"#357",
-	"#358",
-	"#359",
-	"#360",
-	"#361",
-	"#362",
-	"#363",
-	"#364",
-	"#365",
-	"#366",
-	"#367",
-	"#368",
-	"#369",
-	"#370",
-	"#371",
-	"#372",
-	"#373",
-	"#374",
-	"#375",
-	"#376",
-	"#377",
-	"#378",
-	"#379",
-	"#380",
-	"#381",
+	"&319",
+	"&320",
+	"&321",
+	"&322",
+	"&323",
+	"&324",
+	"&325",
+	"&326",
+	"&327",
+	"&328",
+	"&329",
+	"&330",
+	"&331",
+	"&332",
+	"&333",
+	"&334",
+	"&335",
+	"&336",
+	"&337",
+	"&338",
+	"&339",
+	"&340",
+	"&341",
+	"&342",
+	"&343",
+	"&344",
+	"&345",
+	"&346",
+	"&347",
+	"&348",
+	"&349",
+	"&350",
+	"&351",
+	"&352",
+	"&353",
+	"&354",
+	"&355",
+	"&356",
+	"&357",
+	"&358",
+	"&359",
+	"&360",
+	"&361",
+	"&362",
+	"&363",
+	"&364",
+	"&365",
+	"&366",
+	"&367",
+	"&368",
+	"&369",
+	"&370",
+	"&371",
+	"&372",
+	"&373",
+	"&374",
+	"&375",
+	"&376",
+	"&377",
+	"&378",
+	"&379",
+	"&380",
+	"&381",
 	"mousewheeldown",
 	"mousewheelup",
 	"mouse1",
@@ -397,126 +396,126 @@ static const char key_strings[512][16] =
 	"mouse6",
 	"mouse7",
 	"mouse8",
-	"#392",
-	"#393",
-	"#394",
-	"#395",
-	"#396",
-	"#397",
-	"#398",
-	"#399",
-	"#400",
-	"#401",
-	"#402",
-	"#403",
-	"#404",
-	"#405",
-	"#406",
-	"#407",
-	"#408",
-	"#409",
-	"#410",
-	"#411",
-	"#412",
-	"#413",
-	"#414",
-	"#415",
-	"#416",
-	"#417",
-	"#418",
-	"#419",
-	"#420",
-	"#421",
-	"#422",
-	"#423",
-	"#424",
-	"#425",
-	"#426",
-	"#427",
-	"#428",
-	"#429",
-	"#430",
-	"#431",
-	"#432",
-	"#433",
-	"#434",
-	"#435",
-	"#436",
-	"#437",
-	"#438",
-	"#439",
-	"#440",
-	"#441",
-	"#442",
-	"#443",
-	"#444",
-	"#445",
-	"#446",
-	"#447",
-	"#448",
-	"#449",
-	"#450",
-	"#451",
-	"#452",
-	"#453",
-	"#454",
-	"#455",
-	"#456",
-	"#457",
-	"#458",
-	"#459",
-	"#460",
-	"#461",
-	"#462",
-	"#463",
-	"#464",
-	"#465",
-	"#466",
-	"#467",
-	"#468",
-	"#469",
-	"#470",
-	"#471",
-	"#472",
-	"#473",
-	"#474",
-	"#475",
-	"#476",
-	"#477",
-	"#478",
-	"#479",
-	"#480",
-	"#481",
-	"#482",
-	"#483",
-	"#484",
-	"#485",
-	"#486",
-	"#487",
-	"#488",
-	"#489",
-	"#490",
-	"#491",
-	"#492",
-	"#493",
-	"#494",
-	"#495",
-	"#496",
-	"#497",
-	"#498",
-	"#499",
-	"#500",
-	"#501",
-	"#502",
-	"#503",
-	"#504",
-	"#505",
-	"#506",
-	"#507",
-	"#508",
-	"#509",
-	"#510",
-	"#511",
+	"&392",
+	"&393",
+	"&394",
+	"&395",
+	"&396",
+	"&397",
+	"&398",
+	"&399",
+	"&400",
+	"&401",
+	"&402",
+	"&403",
+	"&404",
+	"&405",
+	"&406",
+	"&407",
+	"&408",
+	"&409",
+	"&410",
+	"&411",
+	"&412",
+	"&413",
+	"&414",
+	"&415",
+	"&416",
+	"&417",
+	"&418",
+	"&419",
+	"&420",
+	"&421",
+	"&422",
+	"&423",
+	"&424",
+	"&425",
+	"&426",
+	"&427",
+	"&428",
+	"&429",
+	"&430",
+	"&431",
+	"&432",
+	"&433",
+	"&434",
+	"&435",
+	"&436",
+	"&437",
+	"&438",
+	"&439",
+	"&440",
+	"&441",
+	"&442",
+	"&443",
+	"&444",
+	"&445",
+	"&446",
+	"&447",
+	"&448",
+	"&449",
+	"&450",
+	"&451",
+	"&452",
+	"&453",
+	"&454",
+	"&455",
+	"&456",
+	"&457",
+	"&458",
+	"&459",
+	"&460",
+	"&461",
+	"&462",
+	"&463",
+	"&464",
+	"&465",
+	"&466",
+	"&467",
+	"&468",
+	"&469",
+	"&470",
+	"&471",
+	"&472",
+	"&473",
+	"&474",
+	"&475",
+	"&476",
+	"&477",
+	"&478",
+	"&479",
+	"&480",
+	"&481",
+	"&482",
+	"&483",
+	"&484",
+	"&485",
+	"&486",
+	"&487",
+	"&488",
+	"&489",
+	"&490",
+	"&491",
+	"&492",
+	"&493",
+	"&494",
+	"&495",
+	"&496",
+	"&497",
+	"&498",
+	"&499",
+	"&500",
+	"&501",
+	"&502",
+	"&503",
+	"&504",
+	"&505",
+	"&506",
+	"&507",
+	"&508",
+	"&509",
+	"&510",
+	"&511",
 };
 
 const char *inp_key_name(int k) { if (k >= 0 && k < 512) return key_strings[k]; else return key_strings[0]; }
diff --git a/src/engine/e_keys.h b/src/engine/e_keys.h
index 77a52f58..9670f1a0 100644
--- a/src/engine/e_keys.h
+++ b/src/engine/e_keys.h
@@ -1,4 +1,3 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
 #ifndef ENGINE_KEYS_H
 #define ENGINE_KEYS_H
 /* AUTO GENERATED! DO NOT EDIT MANUALLY! */
diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp
index 7fa5da5e..b55e7333 100644
--- a/src/game/client/components/binds.cpp
+++ b/src/game/client/components/binds.cpp
@@ -63,6 +63,21 @@ const char *BINDS::get(int keyid)
 	return "";
 }
 
+const char *BINDS::get_key(const char *bindstr)
+{
+	for(int keyid = 0; keyid < KEY_LAST; keyid++)
+	{
+		const char *bind = get(keyid);
+		if(!bind[0])
+			continue;
+			
+		if(strcmp(bind, bindstr) == 0)
+			return inp_key_name(keyid);
+	}
+	
+	return "";
+}
+
 void BINDS::set_defaults()
 {
 	// set default key bindings
@@ -90,6 +105,9 @@ void BINDS::set_defaults()
 	
 	bind('T', "chat all");
 	bind('Y', "chat team");	
+
+	bind(KEY_F3, "vote yes");
+	bind(KEY_F4, "vote no");	
 }
 
 void BINDS::on_console_init()
@@ -104,8 +122,6 @@ void BINDS::on_console_init()
 	set_defaults();
 }
 
-
-
 void BINDS::con_bind(void *result, void *user_data)
 {
 	BINDS *binds = (BINDS *)user_data;
@@ -159,7 +175,7 @@ void BINDS::con_dump_binds(void *result, void *user_data)
 int BINDS::get_key_id(const char *key_name)
 {
 	// check for numeric
-	if(key_name[0] == '#')
+	if(key_name[0] == '&')
 	{
 		int i = atoi(key_name+1);
 		if(i > 0 && i < KEY_LAST)
diff --git a/src/game/client/components/binds.hpp b/src/game/client/components/binds.hpp
index 1c9bf388..bdf242f9 100644
--- a/src/game/client/components/binds.hpp
+++ b/src/game/client/components/binds.hpp
@@ -27,6 +27,7 @@ public:
 	void set_defaults();
 	void unbindall();
 	const char *get(int keyid);
+	const char *get_key(const char *bindstr);
 	
 	virtual void on_save();
 	virtual void on_console_init();
diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp
index f2c37b83..86ce6257 100644
--- a/src/game/client/components/hud.cpp
+++ b/src/game/client/components/hud.cpp
@@ -13,6 +13,8 @@
 #include "controls.hpp"
 #include "camera.hpp"
 #include "hud.hpp"
+#include "voting.hpp"
+#include "binds.hpp"
 
 HUD::HUD()
 {
@@ -196,12 +198,35 @@ void HUD::render_teambalancewarning()
 				gfx_text_color(1,1,0.5f,1);
 			else
 				gfx_text_color(0.7f,0.7f,0.2f,1.0f);
-			gfx_text(0x0, 5, 50, 6, text, -1);
+			gfx_text(0x0, 5, 40, 6, text, -1);
 			gfx_text_color(1,1,1,1);
 		}
 	}
 }
 
+
+void HUD::render_voting()
+{
+	if(!gameclient.voting->is_voting())
+		return;
+	
+	gfx_text_color(1,1,1,1);
+	gfx_text(0x0, 5, 50, 6, gameclient.voting->vote_description(), -1);
+
+	RECT base = {5, 60, 119, 3};
+	gameclient.voting->render_bars(base, false);
+	
+	char buf[512];
+	const char *yes_key = gameclient.binds->get_key("vote yes");
+	const char *no_key = gameclient.binds->get_key("vote no");
+	str_format(buf, sizeof(buf), "%s - Vote Yes", yes_key);
+	base.y += base.h+1;
+	ui_do_label(&base, buf, 6.0f, -1);
+
+	str_format(buf, sizeof(buf), "Vote No - %s", no_key);
+	ui_do_label(&base, buf, 6.0f, 1);
+}
+
 void HUD::render_cursor()
 {
 	if(!gameclient.snap.local_character)
@@ -283,5 +308,6 @@ void HUD::on_render()
 	render_connectionwarning();
 	render_tunewarning();
 	render_teambalancewarning();
+	render_voting();
 	render_cursor();
 }
diff --git a/src/game/client/components/hud.hpp b/src/game/client/components/hud.hpp
index 15b9e52c..3ec102f1 100644
--- a/src/game/client/components/hud.hpp
+++ b/src/game/client/components/hud.hpp
@@ -10,6 +10,7 @@ class HUD : public COMPONENT
 	void render_connectionwarning();
 	void render_tunewarning();
 	void render_teambalancewarning();
+	void render_voting();
 	void render_healthandammo();
 	void render_goals();
 	
diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp
index 8cfd211b..d2759642 100644
--- a/src/game/client/components/menus.cpp
+++ b/src/game/client/components/menus.cpp
@@ -621,8 +621,9 @@ void MENUS::render_news(RECT main_view)
 
 void MENUS::render_game(RECT main_view)
 {
-	RECT button, votearea;
-	ui_hsplit_t(&main_view, 45.0f, &main_view, &votearea);
+	RECT button;
+	//RECT votearea;
+	ui_hsplit_t(&main_view, 45.0f, &main_view, 0);
 	ui_draw_rect(&main_view, color_tabbar_active, CORNER_ALL, 10.0f);
 
 	ui_hsplit_t(&main_view, 10.0f, 0, &main_view);
@@ -690,6 +691,7 @@ 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*3 + 25.0f, &votearea, &bars);
@@ -731,52 +733,14 @@ void MENUS::render_game(RECT main_view)
 		// 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;
-			}
-			
-			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;
-			}
+		gameclient.voting->render_bars(bars, true);
 
-			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);
-	}
-	
+	}*/
 }
 
 void MENUS::render_serverinfo(RECT main_view)
diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp
index e43793a4..9311477e 100644
--- a/src/game/client/components/menus_settings.cpp
+++ b/src/game/client/components/menus_settings.cpp
@@ -250,6 +250,8 @@ void MENUS::render_settings_controls(RECT main_view)
 		{ "Console:", "toggle_local_console", 0 },
 		{ "Remote Console:", "toggle_remote_console", 0 },
 		{ "Screenshot:", "screenshot", 0 },
+		{ "Vote Yes:", "vote yes", 0 },
+		{ "Vote No:", "vote no", 0 },
 	};
 
 	const int key_count = sizeof(keys) / sizeof(KEYINFO);
diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp
index d90e617f..e835aa8f 100644
--- a/src/game/client/components/voting.cpp
+++ b/src/game/client/components/voting.cpp
@@ -1,5 +1,8 @@
 #include <engine/e_client_interface.h>
 #include <game/generated/g_protocol.hpp>
+#include <base/vmath.hpp>
+#include <game/client/gc_render.hpp>
+//#include <game/client/gameclient.hpp>
 #include "voting.hpp"
 
 void VOTING::con_callvote(void *result, void *user_data)
@@ -76,3 +79,61 @@ void VOTING::on_render()
 {
 }
 
+
+void VOTING::render_bars(RECT bars, bool text)
+{
+	ui_draw_rect(&bars, vec4(0.8f,0.8f,0.8f,0.5f), CORNER_ALL, bars.h/3);
+	
+	RECT splitter = bars;
+	splitter.x = splitter.x+splitter.w/2;
+	splitter.w = splitter.h/2.0f;
+	splitter.x -= splitter.w/2;
+	ui_draw_rect(&splitter, vec4(0.4f,0.4f,0.4f,0.5f), CORNER_ALL, splitter.h/4);
+			
+	if(total)
+	{
+		RECT pass_area = bars;
+		if(yes)
+		{
+			RECT yes_area = bars;
+			yes_area.w *= yes/(float)total;
+			ui_draw_rect(&yes_area, vec4(0.2f,0.9f,0.2f,0.85f), CORNER_ALL, bars.h/3);
+			
+			if(text)
+			{
+				char buf[256];
+				str_format(buf, sizeof(buf), "%d", yes);
+				ui_do_label(&yes_area, buf, bars.h*0.75f, 0);
+			}
+			
+			pass_area.x += yes_area.w;
+			pass_area.w -= yes_area.w;
+		}
+		
+		if(no)
+		{
+			RECT no_area = bars;
+			no_area.w *= no/(float)total;
+			no_area.x = (bars.x + bars.w)-no_area.w;
+			ui_draw_rect(&no_area, vec4(0.9f,0.2f,0.2f,0.85f), CORNER_ALL, bars.h/3);
+			
+			if(text)
+			{
+				char buf[256];
+				str_format(buf, sizeof(buf), "%d", no);
+				ui_do_label(&no_area, buf, bars.h*0.75f, 0);
+			}
+
+			pass_area.w -= no_area.w;
+		}
+
+		if(text && pass)
+		{
+			char buf[256];
+			str_format(buf, sizeof(buf), "%d", pass);
+			ui_do_label(&pass_area, buf, bars.h*0.75f, 0);
+		}
+	}	
+}
+
+
diff --git a/src/game/client/components/voting.hpp b/src/game/client/components/voting.hpp
index e5338d10..03de629d 100644
--- a/src/game/client/components/voting.hpp
+++ b/src/game/client/components/voting.hpp
@@ -1,4 +1,5 @@
 #include <game/client/component.hpp>
+#include <game/client/ui.hpp>
 
 class VOTING : public COMPONENT
 {
@@ -27,6 +28,8 @@ public:
 	virtual void on_message(int msgtype, void *rawmsg);
 	virtual void on_render();
 	
+	void render_bars(RECT bars, bool text);
+	
 	void vote(int v); // -1 = no, 1 = yes
 	
 	int seconds_left() { return (closetime - time_get())/time_freq(); }
diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp
index c04be833..df3e7666 100644
--- a/src/game/server/entities/character.cpp
+++ b/src/game/server/entities/character.cpp
@@ -682,7 +682,8 @@ void CHARACTER::tick_defered()
 		reckoningcore.write(&predicted);
 		core.write(&current);
 		
-		if(mem_comp(&predicted, &current, sizeof(NETOBJ_CHARACTER)) != 0)
+		// only allow dead reackoning for a top of 3 seconds
+		if(reckoning_tick+server_tickspeed()*3 < server_tick() || mem_comp(&predicted, &current, sizeof(NETOBJ_CHARACTER)) != 0)
 		{
 			reckoning_tick = server_tick();
 			sendcore = core;
diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp
index d5e5c19d..258b2994 100644
--- a/src/game/server/gamecontext.cpp
+++ b/src/game/server/gamecontext.cpp
@@ -321,8 +321,11 @@ void GAMECONTEXT::tick()
 			console_execute_line(vote_command);
 			end_vote();
 			send_chat(-1, GAMECONTEXT::CHAT_ALL, "Vote passed");
+			
+			if(players[vote_creator])
+				players[vote_creator]->last_votecall = 0;
 		}
-		else if(time_get() > vote_closetime || no >= total/2+1)
+		else if(time_get() > vote_closetime || no >= total/2+1 || yes+no == total)
 		{
 			end_vote();
 			send_chat(-1, GAMECONTEXT::CHAT_ALL, "Vote failed");
diff --git a/src/game/server/gamecontext.hpp b/src/game/server/gamecontext.hpp
index 6ce9f068..124df645 100644
--- a/src/game/server/gamecontext.hpp
+++ b/src/game/server/gamecontext.hpp
@@ -49,6 +49,7 @@ public:
 	void end_vote();
 	void send_vote_set(int cid);
 	void send_vote_status(int cid);
+	int vote_creator;
 	int64 vote_closetime;
 	char vote_description[512];
 	char vote_command[512];
diff --git a/src/game/server/hooks.cpp b/src/game/server/hooks.cpp
index 0f3008ce..f7fad64a 100644
--- a/src/game/server/hooks.cpp
+++ b/src/game/server/hooks.cpp
@@ -128,6 +128,22 @@ void mods_message(int msgtype, int client_id)
 	}
 	else if(msgtype == NETMSGTYPE_CL_CALLVOTE)
 	{
+		int64 now = time_get();
+		if(game.vote_closetime)
+		{
+			game.send_chat(-1, client_id, "Wait for current vote to end before calling a new one.");
+			return;
+		}
+		
+		int64 timeleft = p->last_votecall + time_freq()*60 - now;
+		if(timeleft > 0)
+		{
+			char chatmsg[512] = {0};
+			str_format(chatmsg, sizeof(chatmsg), "You must wait %d seconds before making another vote", (timeleft/time_freq())+1);
+			game.send_chat(-1, client_id, chatmsg);
+			return;
+		}
+		
 		char chatmsg[512] = {0};
 		char desc[512] = {0};
 		char cmd[512] = {0};
@@ -144,6 +160,8 @@ void mods_message(int msgtype, int client_id)
 			game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chatmsg);
 			game.start_vote(desc, cmd);
 			p->vote = 1;
+			game.vote_creator = client_id;
+			p->last_votecall = now;
 			game.send_vote_status(-1);
 		}
 	}
@@ -151,11 +169,13 @@ void mods_message(int msgtype, int client_id)
 	{
 		if(!game.vote_closetime)
 			return;
-			
-		NETMSG_CL_VOTE *msg = (NETMSG_CL_VOTE *)rawmsg;
-		p->vote = msg->vote;
-		dbg_msg("", "%d voted %d", client_id, msg->vote);
-		game.send_vote_status(-1);
+
+		if(p->vote == 0)
+		{
+			NETMSG_CL_VOTE *msg = (NETMSG_CL_VOTE *)rawmsg;
+			p->vote = msg->vote;
+			game.send_vote_status(-1);
+		}
 	}
 	else if (msgtype == NETMSGTYPE_CL_SETTEAM)
 	{
diff --git a/src/game/server/player.hpp b/src/game/server/player.hpp
index f483ecf9..24713c93 100644
--- a/src/game/server/player.hpp
+++ b/src/game/server/player.hpp
@@ -29,6 +29,7 @@ public:
 	
 	//
 	int vote;
+	int64 last_votecall;
 
 	//
 	int64 last_chat;