Monday, 11 May 2020

How to set a random mapcycle with nQuakesv

This article assumes you are running the nquakesv server package on a linux flavour.

I don't know about you but I seem to still be playing Quake multiplayer 25 years after this game was released - Not the entire time,  but I'm kind of revisiting it right now after a decade or so of not playing.

So my biggest issue with nquake is having random levels every time i start a multiplayer match.   They say most modern servers work on a map voting system where the players vote for a map but I just can't deal with that and would rather have my server just randomly pumping out a new level after every match.

nquake does ship with a built in random function you can add to your server.cfg and that parameter is called k_random_maplist 1  however the biggest problem with this function is that it repeats levels pretty easily since random is well random...   I thought there could be a better way.

KTX currently loads maps in a way that is numbered like set k_ml_0 "dm2" and set k_ml_1 "dm6" etc..   so I thought i would create an array of the level names and then have a script shuffle them.


  1. run the following command in the /nquakesv/qw/maps/ folder:
  2. ls > level_names.txt
  3. open this file and find and replace all .bsp and .ent and .txt endings after each filename - you should now have a long list of just the map names alone.
  4. copy the contents of the file and paste it into this script I got from one of the nquake discord members
#!/bin/bash
#generate ffa map rotation using specified list in the following format:
# mapname minplayers maxplayers

#shuffle map cycle?
shuffle=1

#this is our fallback map
firstmap="dm5"

#paste your map names into the array below
maps="
13edge
a2
ab2
ac4
aerowalk
ag
agenda
agent
aggressr
aghast
alk08dm
"

shuffle_com="cat"
if [ "$shuffle" -eq 1 ];then
shuffle_com="shuf"
fi
shuffled=$(echo "$maps"|sort -u|grep --color=never -v '^#'|$shuffle_com)

#newmaps=$(echo -e "${firstmap}\n${shuffled}")
newmaps=$(echo -e "${shuffled}")

count=0

while read -r line; do
if [ -z "$line" ];then
continue
fi
map=""
min=""
max=""
for part in $line;do
if [ -z $map ];then
map=$part
continue
fi
if [ -z $min ];then
min=$part
continue
fi
if [ -z $max ];then
max=$part
continue
fi
done
echo 'set k_ml_'$count' "'$map'"'
if [ -z $min ];then
min=0
fi
echo 'set k_ml_minp_'$count' "'$min'"'
if [ -z $max ];then
max=0
fi
echo 'set k_ml_maxp_'$count' "'$max'"'
let count=count+1
done <<< "$newmaps"

  1. Save the script above as something like generate_maps.sh and give it a chmod +x
  2. The Script on its own simply outputs everything in a way that KTX can use and also sets the min and max player counts per level.  If you want to use the min and max settings of this script then where you paste your map names in the array you can put two numbers after each entry like aerowalk 2 4 this would set the aerowalk map to have a minimum of 2 players and a max of 4
  3. What i did next was create a second shell script called start_mapcycle.sh which also has a chmod +x and save it in the root of nquakesv.  The contents of the script are:

#!/bin/bash
./generate_mapcycle.sh > ./ktx/configs/usermodes/ffa/mapcycle.cfg

  1. This will now write the maps into a text file that KTX understands and in a shuffled way.
  2. All you need to do now is have whatever usermode cfg you are running exec your new file in my case i'm using configs/usermodes/ffa/default.cfg
  3. inside default.cfg at the map rotation section simply have it read
exec configs/usermodes/ffa/mapcycle.cfg

You'll need to run start_mapcycle.sh before every start of your server if you want a freshly rotated list of maps - but its still an awesome way to do it.   All credit to @ciscon at nquake #helpdesk

No comments:

Post a Comment