From 73a04b9caeb1c9453a0d29fc0c3e51bdf6aee53a Mon Sep 17 00:00:00 2001 From: esteel Date: Sat, 17 Dec 2005 11:47:22 +0000 Subject: [PATCH] advanced voting :) git-svn-id: svn://svn.icculus.org/nexuiz/trunk@666 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/default.cfg | 12 +- data/qcsrc/gamec/cl_client.c | 8 +- data/qcsrc/gamec/clientcommands.c | 314 ++++++++++++++++++++---------- data/qcsrc/gamec/defs.h | 15 +- 4 files changed, 229 insertions(+), 120 deletions(-) diff --git a/data/default.cfg b/data/default.cfg index 9b6af78cc..e2ef95c35 100755 --- a/data/default.cfg +++ b/data/default.cfg @@ -414,7 +414,11 @@ bind F11 disconnect bind F12 screenshot // these commands can be voted -set sv_vote_allowed "restart timelimit fraglimit chmap g_grappling_hook" +set sv_vote_commands "restart timelimit fraglimit chmap g_grappling_hook" +// users can call a vote for the above commands +set sv_vote_call "1" +// users can call a vote to become master +set sv_vote_master "1" // set to 1 to allow to change you vote/mind set sv_vote_change "0" // set to 1 to count votes once after timeout or to 0 to count with every vote @@ -427,8 +431,10 @@ alias vhelp "cmd vote help" alias vstatus "cmd vote status" alias vcall "cmd vote call $*" alias vstop "cmd vote stop" -alias vyes "echo voted YES;cmd vote yes" -alias vno "echo voted NO;cmd vote no" +alias vmaster "cmd vote master" +alias vdo "cmd vote do $*" +alias vyes "cmd vote yes" +alias vno "cmd vote no" bind F1 vyes bind F2 vno diff --git a/data/qcsrc/gamec/cl_client.c b/data/qcsrc/gamec/cl_client.c index 19dd7e385..ca0b52368 100644 --- a/data/qcsrc/gamec/cl_client.c +++ b/data/qcsrc/gamec/cl_client.c @@ -1088,12 +1088,6 @@ void PlayerPreThink (void) else self.flags = self.flags | FL_JUMPRELEASED; - if (self.vote_finished > 0 // this player has called a vote - && time > self.vote_finished) // time is up - { - VoteCount(); - } - player_powerups(); player_regen(); player_anim(); @@ -1171,7 +1165,7 @@ void PlayerPreThink (void) centerprint(self, strcat("spectating ", self.enemy.netname, "\n\n\n^7press attack for next player\npress attack2 for free fly mode")); } - + VoteThink(); } /* diff --git a/data/qcsrc/gamec/clientcommands.c b/data/qcsrc/gamec/clientcommands.c index 1e261f0fb..504b03313 100644 --- a/data/qcsrc/gamec/clientcommands.c +++ b/data/qcsrc/gamec/clientcommands.c @@ -38,92 +38,102 @@ void SV_ParseClientCommand(string s) { } } else if(argv(0) == "vote") { if(argv(1) == "help") { - sprint(self, "^1You can use voting with \"^2cmd vote help^1\" \"^2cmd vote status^1\" \"^2cmd vote call ^3COMMAND ARGUMENTS^1\" \"^2cmd vote stop^1\" \"^2cmd vote yes^1\" \"^2cmd vote no^1\".\n"); - sprint(self, "^1Or if your version is up to date you can use these aliases \"^2vhelp^1\" \"^2vstatus^1\" \"^2vcall ^3COMMAND ARGUMENTS^1\" \"^2vstop^1\" \"^2vyes^1\" \"^2vno^1\".\n"); - sprint(self, "^1\"^2help^1\" shows this info.\n"); - sprint(self, "^1\"^2status^1\" shows if there is a vote called and who called it.\n"); - sprint(self, "^1\"^2call^1\" is used to call a vote. See the list of allowed commands.\n"); - sprint(self, "^1If more then 50% of the players vote yes the vote is executed.\n"); - sprint(self, "^1If more then 50% of the players vote no the vote fails.\n"); - sprint(self, "^1\"^2stop^1\" can be used by the vote caller to stop a vote and maybe correct it.\n"); - sprint(self, "^1\"^2yes^1\" and \"^2no^1\" to make your vote.\n"); - sprint(self, "^1You can call a vote with these commands:\n"); - sprint(self, strcat("^1\"^2vcall^1\" ^3", cvar_string("sv_vote_allowed"), "^1 and further ^3arguments^1\n")); + sprint(self, "^7You can use voting with \"^2cmd vote help^7\" \"^2cmd vote status^7\" \"^2cmd vote call ^3COMMAND ARGUMENTS^7\" \"^2cmd vote stop^7\" \"^2cmd vote master^7\" \"^2cmd vote do ^3COMMAND ARGUMENTS^7\" \"^2cmd vote yes^7\" \"^2cmd vote no^7\".\n"); + sprint(self, "^7Or if your version is up to date you can use these aliases \"^2vhelp^7\" \"^2vstatus^7\" \"^2vcall ^3COMMAND ARGUMENTS^7\" \"^2vstop^7\" \"^2vmaster^7\" \"^2vdo ^3COMMAND ARGUMENTS^7\" \"^2vyes^7\" \"^2vno^7\".\n"); + sprint(self, "^7\"^2help^7\" shows this info.\n"); + sprint(self, "^7\"^2status^7\" shows if there is a vote called and who called it.\n"); + sprint(self, "^7\"^2call^7\" is used to call a vote. See the list of allowed commands.\n"); + sprint(self, "^7\"^2stop^7\" can be used by the vote caller or an admin to stop a vote and maybe correct it.\n"); + sprint(self, "^7\"^2master^7\" is used to call a vote to become a master.\n"); + sprint(self, "^7\"^2do^7\" If you are a master you can execute a command without a vote. See the list of allowed commands.\n"); + sprint(self, "^7\"^2yes^7\" and \"^2no^7\" to make your vote.\n"); + sprint(self, "^7If more then 50% of the players vote yes the vote is accepted.\n"); + sprint(self, "^7If more then 50% of the players vote no the vote is rejected.\n"); + sprint(self, strcat("^7The vote will end after ", cvar_string("sv_vote_timeout"), "^7 seconds.\n")); + sprint(self, "^7You can call a vote for or execute these commands:\n"); + sprint(self, strcat("^3", cvar_string("sv_vote_commands"), "^7 and maybe further ^3arguments^7\n")); } else if(argv(1) == "status") { - if(votecalled == "") { - sprint(self, "^1No vote called.\n"); + if(votecalled) { + sprint(self, strcat("^7Vote for \"^1", votecalledvote, "^7\" called by \"^7", votecaller.netname, "^7\".\n")); } else { - sprint(self, strcat("^7Vote for \"^1", votecalled, "^7\" called by \"", votecaller.netname, "^7\".\n")); + sprint(self, "^1No vote called.\n"); } } else if(argv(1) == "call") { - if(votecalled == "") { - local string vote; - vote = argv(2); - index = 3; - while(argv(index) != "") { - vote = strcat(vote, " ", argv(index)); - index++; - } - - // necessary for some of the string operations - vote = strzone(vote); - - // now we remove some things that could be misused - index = 0; - local float found; - found = FALSE; - local float votelength; - votelength = strlen(vote); - while(!found && index < votelength) - { - local string badchar; - badchar = substring(vote, index, 1); - if(badchar == ";" - || badchar == "\n") - { - found = TRUE; + if(cvar("sv_vote_call")) { + if(votecalled) { + sprint(self, "^1There is already a vote called.\n"); + } else { + local string vote; + vote = VoteParse(); + if(vote == "") { + sprint(self, "^1Your vote is empty. See help for more info.\n"); + } else if(time < self.vote_next) { + sprint(self, strcat("^1You have to wait ^2", ftos(self.vote_next - time), "^1 seconds before you can again call a vote.\n")); + } else if(VoteAllowed(strcat(argv(2)))) { // strcat seems to be necessary + votecalled = TRUE; + votecalledmaster = FALSE; + votecalledvote = strzone(vote); + votecaller = self; // remember who called the vote + votecaller.vote_vote = 1; // of course you vote yes + votecaller.vote_finished = time + cvar("sv_vote_timeout"); + votecaller.vote_next = time + cvar("sv_vote_wait"); + bprint(strcat("^3Vote for \"^1", votecalledvote, "^3\" called by \"^7", votecaller.netname, "^3\".\n")); + VoteCount(); // needed if you are the only one } else { - index++; + sprint(self, "^1This vote is not ok. See help for more info.\n"); } } - vote = substring(vote, 0, index); - - if(vote == "") { - sprint(self, "^1You have to vote for something.\n"); - } else if(time < self.vote_next) { - sprint(self, strcat("^1You have to wait ^2", ftos(self.vote_next - time), "^1 seconds before you can again call a vote.\n")); - } else if(VoteAllowed(strcat(argv(2)))) { // strcat seems to be necessary - votecalled = strzone(vote); - votecaller = self; // remember who called the vote - self.vote_vote = 1; // of course you vote yes - self.vote_finished = time + cvar("sv_vote_timeout"); - self.vote_next = time + cvar("sv_vote_wait"); - bprint(strcat("^3Vote for \"^1", votecalled, "^3\" called by \"", self.netname, "^3\".\n")); - VoteCount(); // needed if you are the only one - } else { - sprint(self, "^1This vote is not ok. See help for more info.\n"); - } } else { - sprint(self, "^1There is already a vote called.\n"); + sprint(self, "^1Vote calling is NOT allowed.\n"); } } else if(argv(1) == "stop") { - if(votecalled == "") { + if(!votecalled) { sprint(self, "^1No vote called.\n"); - } else if(votecaller == self + } else if(self == votecaller || self.adminstatus > 0) { // the votecaller and admins can stop a vote - if(votecaller == self) { - // disable next votetimer so you can correct your vote - self.vote_next = 0; - } - VoteTimeout(votecaller); + VoteStop(self); } else { sprint(self, "^1You are not allowed to stop that Vote.\n"); } + } else if(argv(1) == "master") { + if(cvar("sv_vote_master")) { + if(votecalled) { + sprint(self, "^1There is already a vote called.\n"); + } else { + votecalled = TRUE; + votecalledmaster = TRUE; + votecalledvote = strzone("^3master"); + votecaller = self; // remember who called the vote + votecaller.vote_vote = 1; // of course you vote yes + votecaller.vote_finished = time + cvar("sv_vote_timeout"); + votecaller.vote_next = time + cvar("sv_vote_wait"); + bprint(strcat("\"^7", votecaller.netname, "^3\" called a vote to become ^3master^3.\n")); + VoteCount(); // needed if you are the only one + } + } else { + sprint(self, "^1Vote to become master is NOT allowed.\n"); + } + } else if(argv(1) == "do") { + if(self.vote_master) { + local string dovote; + dovote = VoteParse(); + if(dovote == "") { + sprint(self, "^1Your command was empty. See help for more info.\n"); + } else if(VoteAllowed(strcat(argv(2)))) { // strcat seems to be necessary + bprint("\"^7", strcat(self.netname, "^2 used his ^3master^2 status to do \"^2", dovote, "^2\".\n")); + localcmd(dovote); + } else { + sprint(self, "^1This command is not ok. See help for more info.\n"); + } + } else { + sprint(self, "^1You are NOT a master.\n"); + } } else if(argv(1) == "yes") { - if(votecalled == "") { + if(!votecalled) { sprint(self, "^1No vote called.\n"); } else if(self.vote_vote == 0 || cvar("sv_vote_change")) { + sprint(self, "^1You accepted the vote.\n"); self.vote_vote = 1; if(!cvar("sv_vote_singlecount")) { VoteCount(); @@ -132,10 +142,11 @@ void SV_ParseClientCommand(string s) { sprint(self, "^1You have already voted.\n"); } } else if(argv(1) == "no") { - if(votecalled == "") { + if(!votecalled) { sprint(self, "^1No vote called.\n"); } else if(self.vote_vote == 0 || cvar("sv_vote_change")) { + sprint(self, "^1You rejected the vote.\n"); self.vote_vote = -1; if(!cvar("sv_vote_singlecount")) { VoteCount(); @@ -210,8 +221,50 @@ void SV_ParseClientCommand(string s) { } } +void VoteThink() { + if(self.vote_finished > 0 // this player has called a vote + && time > self.vote_finished) // time is up + { + VoteCount(); + } +} + +string VoteParse() { + local float index; + index = 3; + local string vote; + vote = argv(2); + while(argv(index) != "") { + vote = strcat(vote, " ", argv(index)); + index++; + } + + // necessary for some of the string operations + vote = strzone(vote); + + // now we remove some things that could be misused + index = 0; + local float found; + found = FALSE; + local float votelength; + votelength = strlen(vote); + while(!found && index < votelength) + { + local string badchar; + badchar = substring(vote, index, 1); + if(badchar == ";" + || badchar == "\n") + { + found = TRUE; + } else { + index++; + } + } + return substring(vote, 0, index); +} + float VoteAllowed(string votecommand) { - tokenize(cvar_string("sv_vote_allowed")); + tokenize(cvar_string("sv_vote_commands")); local float index; index = 0; while(argv(index) != "") { @@ -225,58 +278,107 @@ float VoteAllowed(string votecommand) { return FALSE; } -void VoteCount() { - local float playercount; - playercount = 0; - local float yescount; - yescount = 0; - local float nocount; - nocount = 0; - local entity player; - local entity voter; - player = find(player, classname, "player"); - while(player) +void VoteReset() { + local string searchclass; + searchclass = "player"; + + while (TRUE) { - if(player.vote_vote < 0) { - nocount++; - } else if(player.vote_vote > 0) { - yescount++; + local entity player; + player = find(player, classname, searchclass); + while(player) + { + player.vote_vote = 0; + player.vote_finished = 0; + player = find(player, classname, searchclass); } - if(self.vote_finished > 0) { - voter = player; + if("player" == searchclass) { + searchclass = "observer"; + } else if("observer" == searchclass) { + searchclass = "spectator"; + } else { + break; } + } + + votecalled = FALSE; + votecalledmaster = FALSE; +} - playercount++; - player = find(player, classname, "player"); +void VoteAccept() { + bprint(strcat("^2The vote for \"^1", votecalledvote, "^2\" from \"^7", votecaller.netname, "^2\" was accepted.\n")); + if(votecalledmaster) + { + votecaller.vote_master = 1; + } else { + localcmd(votecalledvote); } + votecaller.vote_next = 0; // people like your votes, no wait for next vote + VoteReset(); +} - if((playercount / 2) < yescount) { // vote passed - VoteDo(voter); - } else if((playercount / 2) < nocount) { // vote rejected - VoteTimeout(voter); - } // else still running +void VoteReject() { + bprint(strcat("^2The vote for \"^1", votecalledvote, "^2\" from \"^7", votecaller.netname, "^2\" was rejected.\n")); + VoteReset(); } -void VoteDo(entity voter) { - bprint(strcat("^2The vote for \"^1", votecalled, "^2\" from \"", voter.netname, "^2\" DID PASS.\n")); - localcmd(votecalled); +void VoteTimeout() { + bprint(strcat("^5The vote for \"^1", votecalledvote, "^5\" from \"^7", votecaller.netname, "^5\" did timeout.\n")); VoteReset(); } -void VoteTimeout(entity voter) { - bprint(strcat("^5The vote for \"^1", votecalled, "^5\" from \"", voter.netname, "^5\" did NOT pass.\n")); +void VoteStop(entity stopper) { + bprint(strcat("^5The vote for \"^1", votecalledvote, "^5\" from \"^7", votecaller.netname, "^5\" was stopped by \"^5", stopper.netname, "^5\".\n")); + if(stopper == votecaller) { + // no wait for next vote so you can correct your vote + votecaller.vote_next = 0; + } VoteReset(); } -void VoteReset() { - local entity player; - player = find(player, classname, "player"); - while(player) +void VoteCount() { + local float playercount; + playercount = 0; + local float yescount; + yescount = 0; + local float nocount; + nocount = 0; + local string searchclass; + searchclass = "player"; + + while (TRUE) { - player.vote_vote = 0; - player.vote_finished = 0; - player = find(player, classname, "player"); + local entity player; + player = find(player, classname, searchclass); + + while(player) + { + if(clienttype(player) != CLIENTTYPE_BOT) { + if(player.vote_vote < 0) { + nocount++; + } else if(player.vote_vote > 0) { + yescount++; + } + playercount++; + } + player = find(player, classname, searchclass); + } + + if("player" == searchclass) { + searchclass = "observer"; + } else if("observer" == searchclass) { + searchclass = "specator"; + } else { + break; + } } - votecalled = ""; + + if((playercount / 2) < yescount) { // vote accepted + VoteAccept(); + } else if((playercount / 2) < nocount) { // vote rejected + VoteReject(); + } else if(time > votecaller.vote_finished) { // vote timedout + VoteTimeout(); + } // else still running } diff --git a/data/qcsrc/gamec/defs.h b/data/qcsrc/gamec/defs.h index 4148642fa..9b0f97a71 100644 --- a/data/qcsrc/gamec/defs.h +++ b/data/qcsrc/gamec/defs.h @@ -186,16 +186,23 @@ float alreadychangedlevel; .string versionmessage; // stahl's voting -string votecalled; +float votecalled; +string votecalledvote; +float votecalledmaster; entity votecaller; +.float vote_master; .float vote_finished; .float vote_next; .float vote_vote; +void VoteThink(); +string VoteParse(); float VoteAllowed(string vote); -void VoteCount(); -void VoteDo(entity voter); -void VoteTimeout(entity voter); void VoteReset(); +void VoteAccept(); +void VoteReject(); +void VoteTimeout(); +void VoteStop(entity stopper); +void VoteCount(); // Wazat's grappling hook .entity hook; -- 2.39.2