Call of Duty mapvotes
A mapvote for Black Ops II trickshot servers on Plutonium. I later ported the same vote to the other Call of Duty games players asked for.

Contents
A mapvote allows, at the end of a match, the players' selection of the next map to play. When the mapvote time hits zero, the server will find the winning selection and is tasked to rotate to the winning map.
I built the first one in 2021 for Call of Duty: Black Ops II. The servers ran on the Plutonium client (Plutonium is a custom game client that lets people host their own servers for older Call of Duty games). At the time I was hosting some servers for both multiplayer (most trickshot servers, which is a custom gamemode) and zombies.
The YouTuber Shaawn was hosting some trickshot servers built by a modder named Matrix. They were the first servers on the client with a mapvote that really worked. I set myself the same goal, with the scripting knowledge I had at the time. I became the second person in that community to reach it.
The Black Ops II vote is public on GitHub. The later games have their own repositories, listed at the end of this page. Anyone can use them.
The first acceptable result#
The first public result acceptable for publishing came in January 2021, when I had a working menu with a decent design.

The hard part wasn't programming the voting logic itself, but rather allowing the server owner to configure it and making sure the design looked like a complete menu. My first script worked, but the code was a mess and the mapvote was hard to configure. I kept revising the menu. The look I was aiming for was that of the classic Modern Warfare 2 vote, based on the Mapvote 0.5.4 R2 mod.
With the help of the community, we managed to come up with a really well-designed final version.

- When the match starts
The mapvote initialization phase involves checking whether it is enabled; if so, it will configure all server-side variables and client-side dvars.
- When the match ends
Regardless of whether or not the final killcam plays, the system will check to see if it was the last round and display the voting menu to all players in the match.
- When the player chooses
The counter for each option will increase when the option is selected and decrease when it is deselected.
- When the time to vote reaches zero
The server code identifies the winner and sets the value of the "maprotation" dvar to the winning map and/or game type.
The Stable Codebase#
Black Ops II gave me the knowledge and development patterns I needed to create a stable, easy-to-maintain, and easy-to-port codebase. In October 2021, I managed to port the same mapvote feature from multiplayer to Zombies. The logic and UI remained the same, except for the HUD elements used (images) and a few minor differences.



Black Ops II past the limits#
After carefully reorganizing the code and resolving several major issues, I was able to optimize the code to support a greater number of maps at the user interface design level. Due to the limited number of HUD elements that can be active at any given time, I had to pay special attention to their usage.
Thanks to an effective reorganization and review of the code, I optimized the user interface management to allow for the use of a greater number of maps while maintaining the design style.


Black Ops II client-side UI#
The Black Ops II mapvote kept being updated while it was being ported to the other games.
The server logic is a handled by a GSC script that gets executed server-side. Each game needs its own version of the GSC script, because the functions pointer, location, and name could differ from game to game.
The menu files can be in two forms, as .menu for older games (Modern Warfare 3 and Black Ops) or lui for a newer client, and are optional because, in all the mapvotes, it has been provided a fully server-side UI.
The final design#
After a careful re-work and with the help from some members of the community such as @ZECxR3ap3r, @JezuzLizard, @John Kramer and birchy, and with a good teamwork, the final design reached its best.


The community asked what the community needs#
The recognition I received from the Black Ops II mapvotes helped me make a name for myself in the community of modders and server owners. It was a project that left an impression on many people and helped improve the quality of life for players during the COVID-19 pandemic. At the time, it was quite common for users to ask me for custom scripts and features, which I was happy to provide to test my knowledge in an attempt to self-improve. Thanks to some popular servers that started using the mapvotes, it wasn't long before I was asked to port it to other games.
The working and re-working of the codebase was beneficial to the porting of the project into other clients and games. The server logic behind each mapvote started from the same point with the only difference being the game and its function names and pointers.
On each game and client, to execute and display the mapvote after the game ends, I chose to work on the function that handles the final killcam before the end of the game that gets called even if there is no final killcam to show.
This function is called as a thread and uses the waittill with the string id "final_killcam_done" that gets sent from the end of the game function in any case. The trick is to wait for the string to get sent and, once received, the block after the waittill would be executed.
The function can change from engine to engine, Treyarch or Infinity Ward.
function() {
if ( !IsDefined( level.finalKillCam_winner ) ) {
return 0;
}
level waittill( "final_killcam_done" );
return 1;
}main() {
replaceFunc(
maps\mp\gametypes\_killcam::finalkillcamwaiter,
::finalkillcamwaiter);
}
finalkillcamwaiter() {
if (!isDefined(level.finalkillcam_winner))
{
return 0;
}
level waittill("final_killcam_done");
if(wasLastRound())
mapvote();
return 1;
}main() {
replacefunc(
maps\mp\gametypes\_gamelogic::waittillFinalKillcamDone,
::waittillFinalKillcamDone);
}
_waittillFinalKillcamDone() {
if ( !IsDefined( level.finalKillCam_winner ) )
{
return 0;
}
level waittill( "final_killcam_done" );
if(wasLastRound())
mapvote();
return 1;
}The first porting#
The mapvote porting to Modern Warfare III was a bit harsher because of the limited tools that allowed me to compile the .menu files to be then shipped to the users as downloadable content from the servers. The only software (named zoonetool) capable of handling the .menu was quite limited for the parsing of the UI files, but with some tricks and skill I managed to make it compile and work as intended by using very complicated syntax tricks from a user perspective.

BeforeAfterOther portings#




Timeline#
- Jan 2021Black Ops II multiplayerThe first working mapvote, 22 January 2021.
- Sep 2021Black Ops II design cleanupThe multiplayer design pass, 6 September 2021.
- Oct 2021Black Ops II zombiesThe multiplayer vote ported to zombies, 31 October 2021.
- Apr 2022Black Ops II multiplayer and zombiesThe release of a stable for multiplayer and zombies, 8 April 2022.
- Apr 2022Modern Warfare 3Experimental
.menumapvote, 9 April 2022. - Apr 2022Modern Warfare 3Experimental
.menuwith game-type support, 9 on 11 April 2022. - Jun 2022Black OpsThe first mapvote, 9 June 2022.
- Aug 2022Ghosts, experimentalExperimental mapvote, 12 August 2022.
- Oct 2022GhostsThe first stable version, 28 October 2022.
- Feb 2023Modern Warfare RemasteredThe first stable version, 2 February 2023.
- Apr 2023Black Ops II multiplayer and zombies past the limitAdded support for 5 and 6 maps to choose from, 2 April 2023.
- Jan 2024Black Ops II multiplayer LUIRelease of the first LUI mapvote, 24 January 2024.
- Aug 2026Black Ops II zombies LUIRelease of the first LUI mapvote, 9 August 2026.
Where to read the code#
- Black Ops II, engine T6: PlutoniumT6Mapvote
- Modern Warfare 3, engine IW5: PlutoniumIW5Mapvote
- Black Ops, engine T5: PlutoniumT5Mapvote
- Ghosts, engine IW6: IW6Mapvote
- Modern Warfare Remastered, engine H1: H1Mapvote