Purpose

Replacement voting system for Q3A,
filtering system to limit the types of votes that may be called.

Overview

First, the actual vote system is replaced, using a vote-registration and ballot system.
Players qualified to vote upon callvote initiation are registered to vote, and given a ballot.
The ballots can be weighted, allowing referees or deputy admins greater sway.

Second, a callvote-filter allows the server admin to constrain the kinds of votes that may be called.
For example, only allowing a callvote on fraglimit if the requested value is between 20 and 100 (disallowing a callvote on a fraglimit of 100000000).
The filter works on a first-match basis; the filter searches its list of rules until a match is made.
Should no rules match, the callvote is denied (Deny-By-Default policy).
An admin may also specify explicit deny rules in the list of rules.

Usage

A series of console commands configures the vote filter:

votefilter_clear

Clears the vote filter ruleset.

votefilter_add passcommandrange

Add a vote filter rule.

pass

Percentage of votes needed to pass.
An exclamation mark (!) indicates a deny rule, that is, a match on this rule denies a callvote.
Values with a percent sign (%) indicate a percent value,
otherwise the value is interpreted as a fraction (full stop (.) as decimal separator).
The percentage of yes votes must exceed this value; for example, if pass is 50%, and two players are voting, just 1 vote is not enough, as 50% does not exceed 50% (just merely equals).

command

The first word in a callvote (i.e. the console command to vote upon).

range

Constraints on the parameter (stuff following the command):

integer:integer - inclusive range of integers.

real:real - inclusive range of floating point numbers.

string - an exact string match

. - (full stop) no parameter

- (no constraint given) any parameter allowed (including none).

For convenience, these commands can be stored in a Q3 .cfg file and executed as needed.

Limitations

Requires a malloc implementation.

Called votes, if passed, are executed verbatim.
There is no rewrite rule.
Rewriting would be useful for creating alias or macro commands,
for example,
a gamemode vote to change g_gametype and immediately put it into effect,
or a kickban vote to kick and ban a player.

The current revision does not have any mechanism for assigning weights, other than 1, to players.

Programming Notes

Unaltered, spectators may call votes, but cannot actually vote.
Spectating+recording is a frequent tool for tracking down or determining cheaters.
Though, under the baseq3 vote system, a spectator may join the game and call a vote, then return to spec, this breaks the flow of the recorded demo.
If the vote passes, the break in spectating is a moot point;
but should the vote fail, there is a period in the recording when the suspect is not watched.

The voting system uses a registration system.
All players qualified to vote at the time of a callvote are recorded, by clientid numbers.
This means a player may still vote if he/she/it goes spectator or switches team.
This also means should a spectator at the time of the callvote join the game shortly afterwards, the ex-spectator cannote participate in the current vote (was spectator at callvote (registration) time).
In the extreme case, should a vote-registered player disconnect and a different player connect on the same clientid, the new player is qualified to vote.
This last behavior should probably change.