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


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.


A series of console commands configures the vote filter:

Clears the vote filter ruleset.
votefilter_add pass command range
Add a vote filter rule.
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).
The first word in a callvote (i.e. the console command to vote upon).
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.


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.

Drop-in files. Patching instructions included in files: g_vote.c

Sample/default filter configuration file: voterule.cfg

Initial posting.

-- PhaethonH (PhaethonH@gmail.com)