---
title: "Per-Map Configs (maps/mapname.cfg)"
excerpt: "Stock HLDS does not auto-execute a per-map config. Here is the mapchangecfgfile workaround and a small AMX Mod X plugin that reliably execs maps/mapname.cfg on every map."
category: "administration"
tags: "config, maps"
image: ""
read_time: "8 min read"
---
<p>It is a widespread belief that CS 1.6 automatically runs <code>maps/de_dust2.cfg</code> when it loads <code>de_dust2</code>. It does not. Stock HLDS has no built-in per-map config auto-exec, which is why so many admins swear their <code>maps/*.cfg</code> files are being ignored — they are. This explains what the engine really does, the one stock hook that comes close, and a tiny plugin that gives you true per-map configs.</p>
<h2>1. What the engine actually executes on a map change</h2>
<p>At the start of every map the engine runs <a href="/tutorials/setup-server-cfg-cs16">server.cfg</a>, and if you have set it, the file named by <code>mapchangecfgfile</code>. That is the whole list. There is no name-based lookup for <code>maps/<currentmap>.cfg</code> anywhere in stock HLDS. Any tutorial that tells you to just drop <code>maps/de_dust2.cfg</code> and expect it to run is repeating a myth.</p>
<h2>2. The stock hook: mapchangecfgfile</h2>
<p>The engine does expose one config that runs on <em>every</em> map change:</p>
<pre>// server.cfg
mapchangecfgfile "onchange.cfg"</pre>
<p>This is useful for settings that must re-apply after each load, but it is the same file for every map — it is not per-map. You can bootstrap per-map behavior from it (read the current map and exec a matching file), but doing that in a config is clumsy. A plugin is cleaner.</p>
<h2>3. The reliable way: a small AMXX plugin</h2>
<p>The classic solution is a few lines of Pawn that read the current map name and <code>exec</code> a file named after it. This runs once, early, on every map:</p>
<pre>#include <amxmodx>
public plugin_init()
{
register_plugin("Per-Map Config", "1.0", "CSB")
new mapname[32]
get_mapname(mapname, charsmax(mapname))
new path[64]
formatex(path, charsmax(path), "maps/%s.cfg", mapname)
// only exec if the file exists, to avoid a console error
new full[96]
formatex(full, charsmax(full), "%s", path)
if (file_exists(full))
server_cmd("exec %s", path)
}</pre>
<p>Compile it, drop the <code>.amxx</code> in <code>addons/amxmodx/plugins/</code>, and add it to <a href="/tutorials/plugins-ini-load-order">plugins.ini</a>. The <code>exec</code> path is relative to the <code>cstrike/</code> game directory, so the files live in <code>cstrike/maps/de_dust2.cfg</code> and so on. If you would rather not compile your own, a maintained equivalent ships as a <a href="/plugins/csb-map-config">CSB Map Config</a> plugin.</p>
<h2>4. What belongs in a per-map config</h2>
<p>Keep these files small and specific — only the things that genuinely differ per map:</p>
<pre>// cstrike/maps/awp_map.cfg
mp_startmoney 16000
mp_buytime 0.1
mp_roundtime 3</pre>
<pre>// cstrike/maps/cs_assault.cfg
mp_startmoney 800
mp_freezetime 4</pre>
<p>Because the engine does not <em>reset</em> cvars between maps, anything you change in one map's cfg persists into the next unless the next map's cfg (or server.cfg) sets it back. That is the number-one per-map gotcha — see the errors below. The cvars themselves are documented in the <a href="/tutorials/mp-cvars-reference">mp_ cvars reference</a>.</p>
<h2>5. Reset what you change</h2>
<p>Because settings leak forward, treat per-map configs as overrides that every map must fully declare, or set your baseline in <code>server.cfg</code> and only override the deltas per map. The cleanest pattern: put normal values in <code>server.cfg</code>, and in each map cfg change <em>only</em> what that map needs — then add the reset to any map that would otherwise inherit an unwanted value. A map that bumps <code>mp_startmoney</code> to 16000 must be followed by maps that set it back to 800, or every map after the money map is rich.</p>
<h2>Troubleshooting</h2>
<ul>
<li><strong>maps/mapname.cfg is ignored</strong> — you expected stock auto-exec, which does not exist. Install the plugin above or use <code>mapchangecfgfile</code>.</li>
<li><strong>Settings bleed into the next map</strong> — cvars are not reset between maps. Each map cfg must declare, or your baseline in server.cfg must reassert, the values.</li>
<li><strong><code>exec</code> prints "couldn't exec"</strong> — the file name does not match the map exactly (case, or a stray <code>.cfg.cfg</code> from a Windows editor), or it is not under <code>cstrike/maps/</code>. The plugin's <code>file_exists</code> guard avoids the error for maps with no config.</li>
<li><strong>Config runs but values do not stick</strong> — a later config (<code>amxx.cfg</code>, a plugin) re-sets them. Trace the execution order.</li>
<li><strong>Plugin does nothing</strong> — not listed in <code>plugins.ini</code>, or <code>amxx plugins</code> shows it as <code>bad load</code>. Fix the load first.</li>
</ul>
<h2>Verification</h2>
<p>Create <code>cstrike/maps/de_dust2.cfg</code> with an obvious value like <code>mp_startmoney 16000</code>, change to that map, and read it back in the console:</p>
<pre>changelevel de_dust2
mp_startmoney // should echo 16000</pre>
<p>Then change to a different map that does not set it and confirm your baseline reasserts — if it stays at 16000, you have found the leak and need a reset line. Once the pattern holds, keep the per-map files short and version them alongside <code>server.cfg</code>.</p>