Your server here Bid in the weekly auction Promote server
62 lines 5.9 KiB Markdown Source Rendered Raw Permalink History
---
title: "mapcycle.txt: How to Set Your Map Rotation"
excerpt: "How the CS 1.6 engine reads mapcycle.txt, how it picks the next map, and the per-map config hook and common traps that quietly break a rotation."
category: "administration"
tags: "mapcycle, maps"
image: ""
read_time: "7 min read"
---
<p>Map rotation on a CS 1.6 server is driven by one plain-text file, <code>mapcycle.txt</code>, and one cvar, <code>mapcyclefile</code>. It is deliberately simple, which is exactly why it fails in ways that look mysterious: a map that is not on disk, a stray comment, or the wrong filename silently changes the rotation and you spend twenty minutes wondering why the server keeps looping <code>de_dust2</code>. This covers how the file is read, how the engine chooses the next map, and the per-map config hook most admins never wire up.</p>

<h2>1. Where the file lives and what points at it</h2>
<p>The rotation file is <code>cstrike/mapcycle.txt</code>. The engine locates it through the <code>mapcyclefile</code> cvar, which defaults to <code>mapcycle.txt</code> (a path relative to the game directory). Keeping several rotations and switching between them is a one-line change in <code>server.cfg</code>:</p>
<pre>// server.cfg
mapcyclefile "mapcycle.txt"
// or a themed rotation you keep alongside it
// mapcyclefile "cycle_gg.txt"</pre>

<h2>2. Write the file: one map per line</h2>
<p>Each line is a map name with <strong>no</strong> <code>.bsp</code> extension and no path. Blank lines and <code>//</code> comments are ignored:</p>
<pre>de_dust2
de_inferno
de_nuke
cs_office
de_train
// de_aztec   &lt;- disabled for now</pre>
<p>Every listed map must exist as <code>cstrike/maps/&lt;name&gt;.bsp</code>. The engine does not fail loudly on a missing entry — it skips it and moves to the next valid line, so a typo just quietly drops a map from the rotation. If you host these maps for download, they must also be on your FastDL mirror; see <a href="/tutorials/fastdl-setup-guide">the FastDL setup guide</a> and <a href="/tutorials/install-custom-maps-cs16-server">installing custom maps</a>.</p>

<h2>3. Understand how the next map is chosen</h2>
<p>When a map ends (see below for what ends it), the engine finds the <em>current</em> map in <code>mapcycle.txt</code> and advances to the line after it, wrapping to the top at the end. Two consequences trip people up:</p>
<ul>
<li>If the map you are on is <strong>not</strong> in the list at all, the engine cannot find its position and falls back to the first entry. A server that always jumps to the top of the cycle after a manual <code>changelevel</code> is doing exactly this.</li>
<li>The engine tracks position by map name, not by an index it saves to disk. On a clean restart it begins from wherever the current map sits in the file.</li>
</ul>
<p>The AMX Mod X <code>nextmap</code> plugin reads this same file to compute what <code>say nextmap</code> reports and to run end-of-map handling. If you also run a vote at map end, <code>mapchooser</code> or <a href="/tutorials/rtv-nextmap-setup">Rock The Vote</a> overrides the plain cycle — see that guide, and the <a href="/plugins/csb-mapchooser">CSB Mapchooser</a> plugin.</p>

<h2>4. What actually ends a map</h2>
<p>The rotation only advances when the map ends, and that is governed by cvars, not by <code>mapcycle.txt</code>:</p>
<pre>mp_timelimit 30      // minutes; 0 disables the time-based change
mp_maxrounds 0       // ReGameDLL: end after N rounds (0 = off)
mp_winlimit 0        // ReGameDLL: end when a team reaches N wins</pre>
<p>With <code>mp_timelimit 0</code> and no round/win limit the map never ends on its own and the cycle appears frozen. These and the rest of the round cvars are covered in the <a href="/tutorials/mp-cvars-reference">mp_ cvars reference</a>.</p>

<h2>5. Per-map configs with mapchangecfgfile</h2>
<p>Vanilla HLDS does not auto-execute a <code>&lt;mapname&gt;.cfg</code> for you, but it does expose <code>mapchangecfgfile</code>, a config it runs on <em>every</em> map change. Point it at a small script that re-applies per-rotation settings, or use it to <code>exec</code> a map-specific file yourself:</p>
<pre>// server.cfg
mapchangecfgfile "onchange.cfg"</pre>
<p>Keep gameplay cvars in <code>server.cfg</code> (executed at start) and only put things that must re-apply after a map load in the change config. Per-map tuning by name is better handled by an AMXX plugin that reads the current map, but <code>mapchangecfgfile</code> is the stock hook and it is reliable.</p>

<h2>Common errors</h2>
<ul>
<li><strong>Rotation ignores your edits</strong> — you edited the wrong file. Check what <code>mapcyclefile</code> actually resolves to in the console; if you set it to a custom name in <code>server.cfg</code>, <code>mapcycle.txt</code> is dead weight.</li>
<li><strong>A map never appears</strong> — the <code>.bsp</code> is missing from <code>cstrike/maps/</code>, or the line has a trailing extension (<code>de_nuke.bsp</code>) or a Windows carriage return from editing on the wrong OS. Save the file as plain LF text.</li>
<li><strong>Server always returns to the first map</strong> — you are running maps that are not in the cycle (a vote map, a manual <code>changelevel</code> to something unlisted). Add them, or accept that off-list maps reset the position.</li>
<li><strong>Map never changes at all</strong> — <code>mp_timelimit</code> is 0 with no round or win limit set. Nothing is telling the map to end.</li>
</ul>

<h2>Verification</h2>
<p>From RCON or the server console, load the first map and query the plugin view:</p>
<pre>changelevel de_dust2
// then in-game
say nextmap</pre>
<p><code>say nextmap</code> should report the line that follows your current map in the file. Let <code>mp_timelimit</code> expire once (or lower it to 1 for a quick test) and confirm the server advances to that map rather than reloading the same one. Once the cycle behaves, layer voting on top with <a href="/tutorials/rtv-nextmap-setup">the RTV and nextmap guide</a>.</p>