{"id":29,"date":"2026-07-17T11:08:51","date_gmt":"2026-07-17T08:08:51","guid":{"rendered":"https:\/\/danielmarcu.com\/blog\/?p=29"},"modified":"2026-07-17T11:13:03","modified_gmt":"2026-07-17T08:13:03","slug":"how-to-make-a-cs-1-6-map","status":"publish","type":"post","link":"https:\/\/danielmarcu.com\/blog\/?p=29","title":{"rendered":"How to Make a CS 1.6 Map?"},"content":{"rendered":"<p><span style=\"display: inline-block; width: 0px; overflow: hidden; line-height: 0;\" data-mce-type=\"bookmark\" class=\"mce_SELRES_start\">\ufeff<\/span><\/p>\n<h1>The Complete GoldSrc Mapping Guide: Building a Real Counter-Strike 1.6 Map<\/h1>\n<p>This is a full walkthrough for building maps in classic Counter-Strike 1.6, running on the GoldSrc engine. It covers everything from tool setup to compiling, optimizing, and packaging a finished map \u2014 written for GoldSrc specifically, not Source or Source 2. The workflow, compilers, and entity set below (Valve Hammer Editor, ZHLT, BSP\/VIS\/RAD) do not apply to CS:Source or CS:GO, which use a completely different toolchain (Hammer++, VBSP\/VVIS\/VRAD, VMF format).<\/p>\n<p><a href=\"#\" id=\"toggle-full-article\" onclick=\"document.getElementById('full-article').style.display='block'; this.parentElement.style.display='none'; return false;\">Click to read the full guide \u2192<\/a><\/p>\n<div id=\"full-article\" style=\"display:none;\">\n<h2>Step 1: Install the Core Tools<\/h2>\n<p>You need three things before you touch a single brush:<\/p>\n<ul>\n<li><strong>Valve Hammer Editor<\/strong> (v3.4 or later) \u2014 the actual level design application. It&#8217;s the GoldSrc-era predecessor to Hammer++.<\/li>\n<li><strong>ZHLT (Zoner&#8217;s Half-Life Tools)<\/strong> \u2014 the compiler suite. This is what converts your editable <code>.map<\/code>\/<code>.rmf<\/code> file into a playable <code>.bsp<\/code>.<\/li>\n<li><strong>halflife-cs.fgd<\/strong> and <strong>halflife.wad<\/strong> \u2014 the entity definitions and base texture set for Counter-Strike specifically.<\/li>\n<\/ul>\n<p>Install Hammer to a simple path like <code>C:\\Hammer\\<\/code> rather than Program Files \u2014 GoldSrc-era tools sometimes fight with Windows write permissions in protected folders. Extract ZHLT into its own dedicated folder too, for example <code>C:\\zhlt\\<\/code>. Keep your compile tools and your Counter-Strike install in accessible, non-nested locations; this will matter later when writing your compile script.<\/p>\n<h2>Step 2: Configure Hammer Properly<\/h2>\n<p>Open <strong>Tools \u2192 Options<\/strong> and work through each tab \u2014 most beginners skip half of this and pay for it later.<\/p>\n<ul>\n<li><strong>Game Configurations tab:<\/strong> create a new configuration named <code>cstrike<\/code>. Point the Game Executable Directory at your Counter-Strike install, and the Mod Directory specifically at the <code>cstrike<\/code> subfolder.<\/li>\n<li><strong>Game Data Files:<\/strong> add <code>halflife-cs.fgd<\/code>. This file tells Hammer what entities exist (spawn points, buttons, lights, CS-specific entities like buy zones) and what properties each one has.<\/li>\n<li><strong>Textures tab:<\/strong> add <code>halflife.wad<\/code> as your base WAD. You can add more WADs later (custom texture packs, <code>zhlt.wad<\/code> for tool textures) \u2014 Hammer will pull from all loaded WADs when you browse textures.<\/li>\n<li><strong>Build Programs tab:<\/strong> point Hammer at your ZHLT executables (<code>hlcsg.exe<\/code>, <code>hlbsp.exe<\/code>, <code>hlvis.exe<\/code>, <code>hlrad.exe<\/code>). This lets you compile directly from inside Hammer later instead of relying only on a batch file, which is faster for iteration.<\/li>\n<\/ul>\n<h2>Step 3: Learn the Interface<\/h2>\n<p>Hammer splits your screen into four viewports: <strong>Top<\/strong>, <strong>Front<\/strong>, <strong>Side<\/strong>, and a <strong>3D\/Camera<\/strong> view. The three orthographic views are 2D slices of your map from different angles \u2014 everything you build exists simultaneously in all of them. Get comfortable checking your work across all three 2D views before committing to a shape; a wall that looks fine from the top might be floating or misaligned from the side.<\/p>\n<p>Key tools you&#8217;ll use constantly:<\/p>\n<ul>\n<li><strong>Selection tool<\/strong> \u2014 select, move, and resize existing brushes and entities.<\/li>\n<li><strong>Brush (block) tool<\/strong> \u2014 draw new rectangular solids.<\/li>\n<li><strong>Entity tool<\/strong> \u2014 place point entities like lights and spawn points.<\/li>\n<li><strong>Camera tool<\/strong> \u2014 creates a preview camera so the 3D viewport shows something.<\/li>\n<li><strong>Clipping tool<\/strong> \u2014 slices a single brush into two along a plane, essential for anything that isn&#8217;t a plain box (stairs, ramps, angled walls).<\/li>\n<li><strong>Vertex tool<\/strong> \u2014 manually drag individual corners\/edges of a brush for custom shapes.<\/li>\n<\/ul>\n<h2>Step 4: Understand Brushes and the Void<\/h2>\n<p>Every solid object in a GoldSrc map \u2014 walls, floors, stairs, props built from geometry \u2014 is a <strong>brush<\/strong>: a convex 3D shape defined by flat planes. GoldSrc brushes must be convex; you can&#8217;t make a single brush shaped like an L or a U. Complex shapes are built from multiple brushes fit together, or by using the clipping\/vertex tools to reshape a box.<\/p>\n<p>Outside of anything you build is <strong>the void<\/strong> \u2014 empty, non-existent space. The void isn&#8217;t a wall or a boundary; it&#8217;s the absence of your map. This concept is central to the single biggest challenge new mappers face, covered next.<\/p>\n<h2>Step 5: The Golden Rule \u2014 No Leaks<\/h2>\n<p>A GoldSrc map must be a fully enclosed, sealed volume. If there is any gap \u2014 a missing wall, a tiny sliver where two brushes don&#8217;t quite touch, a doorway with no door brush sealing it \u2014 the void leaks into your playable space. This is called a <strong>leak<\/strong>, and it breaks your compile&#8217;s lighting and visibility calculations entirely (the compiler can&#8217;t process VIS or RAD correctly if it can&#8217;t tell what&#8217;s &#8220;inside&#8221; your map).<\/p>\n<p>Practical rules to avoid leaks:<\/p>\n<ul>\n<li>Every room needs a floor, ceiling, and all four walls \u2014 no exceptions, even for rooms you think are &#8220;outdoor.&#8221;<\/li>\n<li>Outdoor\/sky areas still need to be enclosed by a skybox \u2014 a large hollow box using the <code>SKY<\/code> texture. There&#8217;s no such thing as truly open space in GoldSrc.<\/li>\n<li>Windows and openings need to be sealed with glass brushes, grates, or something \u2014 an open hole to the void is a leak.<\/li>\n<li>If your compile does leak, ZHLT generates a <strong>pointfile<\/strong>. Load it in Hammer (<strong>Map \u2192 Load Pointfile<\/strong>) and it draws a red line straight from your map&#8217;s origin to the exact leak point \u2014 follow the line to find the gap.<\/li>\n<\/ul>\n<h2>Step 6: Build Your First Room<\/h2>\n<ol>\n<li>Pick a texture from a loaded WAD using the texture browser.<\/li>\n<li>Draw a brush in the Top viewport for your floor \u2014 flat and wide.<\/li>\n<li>Hold <strong>Shift<\/strong> while dragging the floor brush to duplicate it, then resize the copy into a wall. Repeat for all four walls and the ceiling.<\/li>\n<li>Check every seam in all three 2D viewports to confirm brushes are actually touching, not just visually close.<\/li>\n<li>Adjust your grid size with the <code>[<\/code> and <code>]<\/code> keys \u2014 use a large grid (32, 64, or bigger) for basic room shapes, and only drop to a fine grid when you need small precise details. Building on too fine a grid early on is one of the most common causes of tiny, invisible leaks.<\/li>\n<\/ol>\n<h2>Step 7: Texture Alignment<\/h2>\n<p>Textures on GoldSrc brushes can be reset, scaled, and shifted independently per face. Poor alignment (stretched, rotated, or seamed textures) is one of the fastest ways to make a map look unfinished. Use the <strong>Face Edit<\/strong> sheet (usually opened with the texture application tool or a dedicated hotkey) to:<\/p>\n<ul>\n<li>Fit a texture cleanly to a face size<\/li>\n<li>Adjust X\/Y shift and scale so textures align across adjoining brushes (like a floor and a wall meeting at a corner)<\/li>\n<li>Use &#8220;Treat as one&#8221; alignment across multi-brush surfaces so a texture doesn&#8217;t visibly repeat awkwardly at brush seams<\/li>\n<\/ul>\n<h2>Step 8: Place Core Entities<\/h2>\n<p>Entities give your geometry gameplay meaning. Every Counter-Strike map needs, at minimum:<\/p>\n<ul>\n<li><strong>info_player_start<\/strong> \u2014 Counter-Terrorist spawn points. Place several, floating slightly above the floor (never touching walls or floor) so players don&#8217;t spawn stuck.<\/li>\n<li><strong>info_player_deathmatch<\/strong> \u2014 Terrorist spawn points, same placement rules.<\/li>\n<li><strong>light<\/strong> \u2014 a point light entity. Set color and brightness via Alt+Enter on the entity. Standard format is R G B Brightness (e.g. <code>255 255 128 200<\/code>).<\/li>\n<\/ul>\n<p>Beyond the basics, Counter-Strike&#8217;s FGD gives you gamemode-defining entities:<\/p>\n<ul>\n<li><strong>func_buyzone<\/strong> \u2014 a brush entity (select brushes, Ctrl+T) defining where players can open the buy menu. Set the Team property so CT and T buy zones don&#8217;t overlap incorrectly.<\/li>\n<li><strong>func_bomb_target<\/strong> \u2014 defines a bombsite for de_ maps.<\/li>\n<li><strong>info_bomb_target<\/strong> \u2014 point entity alternative\/companion for radar bomb icon placement.<\/li>\n<li><strong>hostage_entity<\/strong> \u2014 places a rescuable hostage for cs_ maps.<\/li>\n<li><strong>func_hostage_rescue<\/strong> \u2014 brush entity marking the rescue zone.<\/li>\n<li><strong>armoury_entity<\/strong> \u2014 spawns weapons\/equipment pickups directly in the world.<\/li>\n<li><strong>weaponbox<\/strong> and related \u2014 used less often manually, but relevant for scripted weapon placement.<\/li>\n<\/ul>\n<p>Map type dictates which entities are mandatory: de_ maps need bomb targets, cs_ maps need hostages and rescue zones, and both need properly configured buy zones or the round will not function correctly even if the map compiles fine.<\/p>\n<h2>Step 9: Add Detail Entities<\/h2>\n<p>Once the gameplay skeleton is in place, layer in atmosphere:<\/p>\n<ul>\n<li><strong>ambient_generic<\/strong> \u2014 plays a looping or triggered sound (wind, machinery, music) from a WAV in the game&#8217;s sound folder.<\/li>\n<li><strong>func_water<\/strong> \u2014 a brush entity that turns a sealed volume into swimmable\/visible water, with adjustable current and opacity.<\/li>\n<li><strong>func_door<\/strong> and <strong>func_door_rotating<\/strong> \u2014 sliding and rotating doors respectively, built by turning a brush into an entity (Ctrl+T) and configuring open direction, speed, and lip.<\/li>\n<li><strong>func_ladder<\/strong> \u2014 an invisible climbable volume placed over a ladder-textured brush; without it, the ladder texture is purely visual and unclimbable.<\/li>\n<li><strong>func_breakable<\/strong> \u2014 glass, crates, or other destructible geometry.<\/li>\n<li><strong>trigger_multiple \/ trigger_once<\/strong> \u2014 invisible brush volumes that fire other entities when a player touches them, the backbone of scripted sequences.<\/li>\n<\/ul>\n<h2>Step 10: Understand the Compile Process<\/h2>\n<p>ZHLT compiles in four sequential stages, each producing input for the next. Understanding what each stage actually does makes error messages far less mysterious:<\/p>\n<ol>\n<li><strong>hlcsg (CSG)<\/strong> \u2014 Constructive Solid Geometry. Converts your brushes into the engine&#8217;s internal format and checks for leaks. This is where a leak error first appears.<\/li>\n<li><strong>hlbsp (BSP)<\/strong> \u2014 Binary Space Partitioning. Splits your map into a tree structure the engine uses for collision and rendering. This stage can throw errors about &#8220;MAX_MAP&#8221; limits if your map is too complex or contains malformed brushes.<\/li>\n<li><strong>hlvis (VIS)<\/strong> \u2014 Visibility. Calculates which parts of the map can see which other parts, so the engine doesn&#8217;t render geometry the player can&#8217;t possibly see. This is usually the slowest stage on large or open maps.<\/li>\n<li><strong>hlrad (RAD)<\/strong> \u2014 Radiosity. Calculates lighting by bouncing light off surfaces. This stage is what actually makes your light entities and texture lights visible in-game.<\/li>\n<\/ol>\n<p>A basic Steam-based compile batch file looks like this:<\/p>\n<pre><code>@echo off\r\nhlcsg -nowadtextures yourmapname\r\nhlbsp yourmapname\r\nhlvis yourmapname\r\nhlrad yourmapname\r\ncopy yourmapname.bsp \"C:\\Steam\\SteamApps\\&lt;youraccount&gt;\\counter-strike\\cstrike\\maps\"\r\npause\r\n\"C:\\Steam\\Steam.exe\" -applaunch 10 -dev +sv_cheats 1 +map yourmapname\r\n<\/code><\/pre>\n<p><code>-nowadtextures<\/code> embeds all textures directly into the BSP so players don&#8217;t need your custom WADs installed separately \u2014 strongly recommended for anything you plan to release publicly.<\/p>\n<h2>Step 11: Useful Compile Flags for Faster Iteration<\/h2>\n<p>Full-quality compiles can take a long time, especially VIS and RAD on larger maps. While actively building and testing, use fast\/preview flags to cut iteration time dramatically, then switch to full quality only for your final release build:<\/p>\n<ul>\n<li><code>hlvis -fast<\/code> \u2014 a much faster, lower-quality visibility pass for testing.<\/li>\n<li><code>hlrad -fast<\/code> \u2014 quick, rougher lighting pass, useful for checking layout without waiting on full radiosity.<\/li>\n<li><code>hlcsg -onlyents<\/code> \u2014 skips full geometry recompilation and only updates entity data, useful when you&#8217;ve only moved a spawn point or tweaked a light, not the brushwork.<\/li>\n<li>Full release compile should drop the fast flags entirely, and consider <code>hlrad -extra<\/code> for higher-quality bounce lighting on a finished map.<\/li>\n<\/ul>\n<h2>Step 12: Optimize for Performance<\/h2>\n<p>GoldSrc is an old engine, but poorly optimized maps still choke it, especially in multiplayer. A few essential habits:<\/p>\n<ul>\n<li><strong>Use the NULL texture<\/strong> on any brush face that will never be seen by a player \u2014 the underside of terrain, brush faces pressed flush against another brush, the outside of your skybox. NULL faces aren&#8217;t rendered or lit, saving compile time and runtime performance.<\/li>\n<li><strong>Hint brushes<\/strong> (using the <code>zhlt.wad<\/code> tool textures) let you manually guide the VIS compiler to split visibility more intelligently around corners and sightlines, which is otherwise one of the hardest things to optimize automatically.<\/li>\n<li><strong>Avoid excessive brush count and unnecessary complexity<\/strong> in detail geometry \u2014 use texture detail instead of geometric detail where possible.<\/li>\n<li><strong>func_wall<\/strong> or <strong>func_illusionary<\/strong> can convert static decorative brushes into entities, which removes them from VIS calculations in certain cases and can help performance on detail-heavy areas.<\/li>\n<li>Keep an eye on the <code>r_speeds<\/code> in-game counter (enable with <code>sv_cheats 1<\/code>, then <code>r_speeds 1<\/code>) while testing \u2014 it shows real-time polygon and surface counts so you can spot problem areas.<\/li>\n<\/ul>\n<h2>Step 13: Test Thoroughly<\/h2>\n<p>Compile with cheats enabled and walk your own map like a player would, not just a builder:<\/p>\n<ul>\n<li>Use <code>noclip<\/code> to check for leaks and gaps you might have missed visually.<\/li>\n<li>Use <code>impulse 101<\/code> to grab a full weapon set and test combat sightlines, not just navigation.<\/li>\n<li>Check that all spawn points are unobstructed and that buy zones, bomb sites, or hostage rescue zones actually trigger correctly.<\/li>\n<li>Test with bots or a second player if possible \u2014 solo walkthroughs miss a lot of balance issues that only show up with real player movement and gunfights.<\/li>\n<\/ul>\n<h2>Step 14: Package for Distribution<\/h2>\n<p>If you want other people to play your map without manually installing your WAD files, remember to compile with <code>-nowadtextures<\/code> so all textures are baked directly into the <code>.bsp<\/code>. Beyond that:<\/p>\n<ul>\n<li>Include any custom sounds referenced by <code>ambient_generic<\/code> entities in a matching <code>sound\/<\/code> folder structure alongside your map, since audio isn&#8217;t embedded in the BSP.<\/li>\n<li>Consider writing a simple readme noting map type (de_\/cs_\/etc.), player count recommendation, and credits.<\/li>\n<li>Test your final packaged BSP on a clean install or a dedicated server without your Hammer environment present, to confirm nothing is silently depending on local files that won&#8217;t ship with the map.<\/li>\n<\/ul>\n<p>That covers the full pipeline: tool setup, interface fundamentals, brush-based geometry, leak-proofing, the full CS entity set, the four-stage compile process, performance optimization, and final packaging.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>\ufeff The Complete GoldSrc Mapping Guide: Building a Real Counter-Strike 1.6 Map This is a full walkthrough for building maps in classic Counter-Strike 1.6, running on the GoldSrc engine. It covers everything from tool setup to compiling, optimizing, and packaging a finished map \u2014 written for GoldSrc specifically, not Source or Source 2. The workflow, &hellip; <a href=\"https:\/\/danielmarcu.com\/blog\/?p=29\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;How to Make a CS 1.6 Map?&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-29","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/danielmarcu.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/29","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/danielmarcu.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/danielmarcu.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/danielmarcu.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/danielmarcu.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=29"}],"version-history":[{"count":4,"href":"https:\/\/danielmarcu.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/29\/revisions"}],"predecessor-version":[{"id":33,"href":"https:\/\/danielmarcu.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/29\/revisions\/33"}],"wp:attachment":[{"href":"https:\/\/danielmarcu.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=29"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/danielmarcu.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=29"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/danielmarcu.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=29"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}