strcat("^2:^1", ftos(vote_reject_count)),
((mincount >= 0) ? strcat("^2 (^1", ftos(mincount), "^2 needed)") : "^2"),
strcat(", ^1", ftos(vote_abstain_count), "^2 didn't care"),
- strcat(", ^1", ftos(notvoters), strcat("^2 didn't ", ((mincount >= 0) ? string_null : "have to "), "vote\n"))));
+ strcat(", ^1", ftos(notvoters), strcat("^2 didn't ", ((mincount >= 0) ? "" : "have to "), "vote\n"))));
if(autocvar_sv_eventlog)
{
|| ((autocvar_sv_vote_nospectators == 1) && (inWarmupStage || gameover))
|| (autocvar_sv_vote_nospectators == 0));
- float vote_player_count, is_player, notvoters;
- float vote_real_player_count, vote_real_accept_count;
- float vote_real_reject_count, vote_real_abstain_count;
+ float vote_player_count = 0, is_player, notvoters = 0;
+ float vote_real_player_count = 0, vote_real_accept_count = 0;
+ float vote_real_reject_count = 0, vote_real_abstain_count = 0;
float vote_needed_of_voted, final_needed_votes;
float vote_factor_overall, vote_factor_of_voted;
{
entity tmp_player;
float ready_needed_factor, ready_needed_count;
- float t_ready, t_players;
+ float t_ready = 0, t_players = 0;
FOR_EACH_REALPLAYER(tmp_player)
{
if(strstrofs(l, strcat(" ", vote_command, " "), 0) >= 0)
return TRUE;
- // if gotomap is allowed, chmap is too, and vice versa
- if(vote_command == "gotomap")
- if(strstrofs(l, " chmap ", 0) >= 0)
- return TRUE;
-
- if(vote_command == "chmap")
- if(strstrofs(l, " gotomap ", 0) >= 0)
- return TRUE;
-
return FALSE;
}
{
validated_map = MapInfo_FixName(validated_map);
- if(!validated_map)
+ if not(validated_map)
{
print_to(caller, "This map is not available on this server.");
return string_null;
return validated_map;
}
-float VoteCommand_parse(entity caller, string vote_command, string vote_list, float startpos, float argc)
+float VoteCommand_checkargs(float startpos, float argc)
{
- string first_command;
-
- first_command = argv(startpos);
+ float p, q, check, minargs;
+ string cvarname = strcat("sv_vote_command_restriction_", argv(startpos));
+ string cmdrestriction = cvar_string(cvarname); // note: this warns on undefined cvar. We want that.
+ string charlist, arg;
+ float checkmate;
- if not(VoteCommand_checkinlist(first_command, vote_list))
+ if(cmdrestriction == "")
+ return TRUE;
+
+ ++startpos; // skip command name
+
+ // check minimum arg count
+
+ // 0 args: argc == startpos
+ // 1 args: argc == startpos + 1
+ // ...
+
+ minargs = stof(cmdrestriction);
+ if(argc - startpos < minargs)
return FALSE;
- if(argc < startpos) // These commands won't work without arguments
+ p = strstrofs(cmdrestriction, ";", 0); // find first semicolon
+
+ for(;;)
{
- switch(first_command)
+ // we know that at any time, startpos <= argc - minargs
+ // so this means: argc-minargs >= startpos >= argc, thus
+ // argc-minargs >= argc, thus minargs <= 0, thus all minargs
+ // have been seen already
+
+ if(startpos >= argc) // all args checked? GOOD
+ break;
+
+ if(p < 0) // no more args? FAIL
{
- case "map":
- case "chmap":
- case "gotomap":
- case "kick":
- case "kickban":
- return FALSE;
-
- default: { break; }
+ // exception: exactly minargs left, this one included
+ if(argc - startpos == minargs)
+ break;
+
+ // otherwise fail
+ return FALSE;
+ }
+
+ // cut to next semicolon
+ q = strstrofs(cmdrestriction, ";", p+1); // find next semicolon
+ if(q < 0)
+ charlist = substring(cmdrestriction, p+1, -1);
+ else
+ charlist = substring(cmdrestriction, p+1, q - (p+1));
+
+ // in case we ever want to allow semicolons in VoteCommand_checknasty
+ // charlist = strreplace("^^", ";", charlist);
+
+ if(charlist != "")
+ {
+ // verify the arg only contains allowed chars
+ arg = argv(startpos);
+ checkmate = strlen(arg);
+ for(check = 0; check < checkmate; ++check)
+ if(strstrofs(charlist, substring(arg, check, 1), 0) < 0)
+ return FALSE; // not allowed character
+ // all characters are allowed. FINE.
}
+
+ ++startpos;
+ --minargs;
+ p = q;
}
+
+ return TRUE;
+}
+
+float VoteCommand_parse(entity caller, string vote_command, string vote_list, float startpos, float argc)
+{
+ string first_command;
+ first_command = argv(startpos);
+
+ if not(VoteCommand_checkinlist(first_command, vote_list))
+ return FALSE;
+
+ if not(VoteCommand_checkargs(startpos, argc))
+ return FALSE;
+
switch(first_command) // now go through and parse the proper commands to adjust as needed.
{
case "kick":
|| ((autocvar_sv_vote_nospectators == 1) && inWarmupStage)
|| (autocvar_sv_vote_nospectators == 0));
- float tmp_playercount;
+ float tmp_playercount = 0;
entity tmp_player;
vote_command = VoteCommand_extractcommand(vote_command, 2, argc);
if not(autocvar_sv_vote_call || !caller) { print_to(caller, "^1Vote calling is not allowed."); }
+ else if(!autocvar_sv_vote_gamestart && time < game_starttime) { print_to(caller, "^1Vote calling is not allowed before the match has started."); }
else if(vote_called) { print_to(caller, "^1There is already a vote called."); }
else if(!spectators_allowed && (caller && (caller.classname != "player"))) { print_to(caller, "^1Only players can call a vote."); }
else if(timeout_status) { print_to(caller, "^1You can not call a vote while a timeout is active."); }