{"id":1639,"date":"2026-01-06T01:02:07","date_gmt":"2026-01-06T01:02:07","guid":{"rendered":"https:\/\/grimms3dworlds.ddns.net\/?page_id=1639"},"modified":"2026-01-20T11:37:24","modified_gmt":"2026-01-20T11:37:24","slug":"1639-2","status":"publish","type":"page","link":"https:\/\/grimms3dworlds.ddns.net\/index.php\/1639-2\/","title":{"rendered":""},"content":{"rendered":"\n<div class=\"tutorial-container\">\n <h1>Call of Duty 2 Multiplayer: Adding Animated Shutters and Swaying Wires Using Stock _shutter.gsc<\/h1>\n \n <p>This tutorial explains how to implement dynamic ambient effects (randomly jiggling shutters and swaying wires) in a CoD2 multiplayer map using the original stock script <code>maps\/mp\/_shutter.gsc<\/code>. These effects add great life to maps, as seen in classics like mp_toujane. The script is already included in the stock PK3 files and always available\u2014no custom file placement required.<\/p>\n\n <h2>1. Script Setup<\/h2>\n \n <p>The stock script <code>maps\/mp\/_shutter.gsc<\/code> is automatically called by <code>maps\\mp\\_load::main()<\/code>, which is included in every standard multiplayer map GSC. You do <strong>not<\/strong> need to add any extra line to your map&#8217;s main GSC file.<\/p>\n\n <div class=\"note\">\n <p><strong>Important Warning:<\/strong> Do <strong>not<\/strong> manually add <code>thread maps\\mp\\_shutter::main();<\/code> (or similar) to your map GSC. Doing so will run the script twice, causing duplicate rotations, wrong clamping, over-rotation (including full 360\u00b0 spins), crashes on restart, and blocking other map initialization (e.g. ambient sounds not loading).<\/p>\n <\/div>\n\n <div class=\"note\">\n <p><strong>Note:<\/strong> The original script includes a commented-out <code>windController()<\/code> thread that would periodically switch wind direction and fully open shutters in one direction. The developers left it disabled\u2014there may have been a good reason (e.g., performance, visual consistency, or gameplay concerns). The current behavior provides continuous random jiggle without directional resets.<\/p>\n <\/div>\n\n <h2>2. Creating Swaying Wires<\/h2>\n \n <p>Wires use a <code>script_brushmodel<\/code> linked to two <code>script_origin<\/code> entities at each end.<\/p>\n \n <ol>\n <li>Create a long thin brush for the wire (texture as cable\/metal).<\/li>\n <li>Convert it to <strong>script > brushmodel<\/strong>.<\/li>\n <li>Press <strong>N<\/strong>, set <code>targetname<\/code> to <code>wire<\/code>.<\/li>\n <li>Create two point entities (right-click empty grid > info > any, then in N window change <code>classname<\/code> to <code>script_origin<\/code>).<\/li>\n <li>Place one script_origin at each end of the wire.<\/li>\n <li>On the wire entity, add <code>target<\/code> key with a unique value (e.g., <code>wire1_ends<\/code>).<\/li>\n <li>On both script_origins, set <code>targetname<\/code> to the same value (<code>wire1_ends<\/code>).<\/li>\n <li>Alternative: Select wire first, then both origins, press <strong>W<\/strong> to auto-link.<\/li>\n <\/ol>\n \n <div class=\"image-pair\">\n <div class=\"image-item\">\n <p class=\"image-caption\">Radiant: Wire brushmodel with two script_origins and auto-link lines<\/p>\n<img decoding=\"async\" src=\"https:\/\/grimms3dworlds.ddns.net\/wp-content\/uploads\/2026\/01\/wire.png\" alt=\"wire in Radiant\" style=\"max-width:100%; height:auto; border-radius:4px;\">\n\n <\/div>\n <\/div>\n\n <h2>3. Creating Animated Shutters (Correct Pivot Method)<\/h2>\n \n <p>Shutters rotate randomly around a custom hinge pivot defined by an <strong>origin-textured brush<\/strong>. No script_origins or targets needed.<\/p>\n \n <ol>\n <li>Create the main shutter brush (rectangular, wood\/metal texture).<\/li>\n <li>Position it in its closed\/rest pose against the wall or frame.<\/li>\n <li>Create a small helper brush centered exactly on the hinge line (vertical edge for side swing, horizontal top edge for overhead).<\/li>\n <li>Apply the <strong>origin<\/strong> texture to <strong>all faces<\/strong> of the helper brush (search &#8220;origin&#8221; in textures > common\/tools).<\/li>\n <li>Select <strong>both<\/strong> brushes (shutter + origin helper).<\/li>\n <li>Right-click > <strong>script > brushmodel<\/strong> (merges into one entity).<\/li>\n <li>Press <strong>N<\/strong>, set <code>targetname<\/code> to one of the supported values below.<\/li>\n <\/ol>\n \n <table>\n <thead>\n <tr>\n <th>Targetname<\/th>\n <th>Grouping \/ Notes<\/th>\n <\/tr>\n <\/thead>\n <tbody>\n <tr>\n <td><code>shutter_left<\/code><\/td>\n <td>Base left-facing (grouped as left)<\/td>\n <\/tr>\n <tr>\n <td><code>shutter_right<\/code><\/td>\n <td>Base right-facing (grouped as right)<\/td>\n <\/tr>\n <tr>\n <td><code>shutter_left_open<\/code><\/td>\n <td>Treated as left group<\/td>\n <\/tr>\n <tr>\n <td><code>shutter_right_open<\/code><\/td>\n <td>Treated as left group (script quirk)<\/td>\n <\/tr>\n <tr>\n <td><code>shutter_left_closed<\/code><\/td>\n <td>Treated as left group<\/td>\n <\/tr>\n <tr>\n <td><code>shutter_right_closed<\/code><\/td>\n <td>Treated as right group<\/td>\n <\/tr>\n <\/tbody>\n <\/table>\n \n <div class=\"image-pair\">\n <div class=\"image-item\">\n <p class=\"image-caption\">Shutter brush next to origin-textured helper brush (before merging)<\/p>\n <img decoding=\"async\" src=\"https:\/\/grimms3dworlds.ddns.net\/wp-content\/uploads\/2026\/01\/shut1.png\" alt=\"Sh utter and origin brush selected in Radiant\" style=\"max-width:100%; height:auto; border-radius:4px;\">\n <\/div>\n <div class=\"image-item\">\n <p class=\"image-caption\">Origin texture applied (textures window)<\/p>\n <img decoding=\"async\" src=\"https:\/\/grimms3dworlds.ddns.net\/wp-content\/uploads\/2026\/01\/shut21-e1767661766188.png\" alt=\"Origin texture applied to helper brush\" style=\"max-width:100%; height:auto; border-radius:4px;\">\n <\/div>\n <\/div>\n\n <div class=\"image-pair\">\n <div class=\"image-item\">\n <p class=\"image-caption\">Entity info window (N key) with targetname set<\/p>\n <img decoding=\"async\" src=\"https:\/\/grimms3dworlds.ddns.net\/wp-content\/uploads\/2026\/01\/shut3-1.png\" alt=\"Entity window showing targetname for shutter\" style=\"max-width:100%; height:auto; border-radius:4px;\">\n <\/div>\n <div class=\"image-item\">\n <p class=\"image-caption\">In-game: Animated shutter jiggle<\/p>\n <img decoding=\"async\" src=\"https:\/\/grimms3dworlds.ddns.net\/wp-content\/uploads\/2026\/01\/shut4-1-e1767661171695.png\" alt=\"Animated shutter in-game\" style=\"max-width:100%; height:auto; border-radius:4px;\">\n <\/div>\n <\/div>\n\n <div class=\"note\">\n <p><strong>Important:<\/strong> The origin brush is invisible in-game and only defines the rotation pivot. Test the hinge in Radiant using the <strong>R<\/strong> key (rotate mode) after merging\u2014drag in 3D view to confirm perfect swing before compiling.<\/p>\n <\/div>\n\n <h2>Final Steps<\/h2>\n \n <ul>\n <li>Duplicate and place multiple wires and shutters around your map for variety.<\/li>\n <li>Perform a full compile (BSP \u2192 VIS \u2192 Lighting).<\/li>\n <li>Launch with <code>\/devmap yourmapname<\/code>.<\/li>\n <li>Enjoy subtle, realistic ambient movement!<\/li>\n <\/ul>\n\n <p>If effects don&#8217;t appear or behave strangely (e.g. over-rotation, no ambient sound), enable <code>\/developer 1<\/code> in console and check for script errors. Common issue: the script being called twice (once by _load.gsc and again manually).<\/p>\n<\/div>\n\n<style>\n .tutorial-container {\n font-family: 'Segoe UI', Arial, sans-serif;\n max-width: 900px;\n margin: 0 auto;\n padding: 20px;\n background: #ffffff;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n }\n h1, h2, h3 {\n color: #1a3c5e;\n margin-bottom: 15px;\n padding-bottom: 8px;\n }\n h1, h2 {\n border-bottom: 2px solid #e0e6ed;\n }\n h3 {\n border-bottom: 1px solid #e0e6ed;\n }\n p {\n color: #4a4a4a;\n line-height: 1.6;\n }\n .note p {\n background: #e7f3fe;\n border: 1px solid #b6d4fe;\n padding: 15px;\n color: #0c5460;\n border-radius: 5px;\n margin-bottom: 20px;\n }\n ul, ol {\n color: #4a4a4a;\n padding-left: 20px;\n }\n li {\n margin-bottom: 8px;\n }\n pre {\n position: relative;\n background: #1e1e1e;\n color: #ffffff;\n padding: 15px;\n border-radius: 5px;\n font-size: 14px;\n line-height: 1.4;\n max-height: 400px;\n overflow-y: auto;\n overflow-x: auto;\n white-space: pre;\n margin-bottom: 20px;\n }\n pre button {\n position: absolute;\n top: 10px;\n right: 10px;\n background: #007bff;\n color: #ffffff;\n border: none;\n padding: 8px 12px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n }\n pre button:hover {\n background: #0056b3;\n }\n table {\n width: 100%;\n border-collapse: collapse;\n margin-bottom: 20px;\n }\n th, td {\n border: 1px solid #ddd;\n padding: 8px;\n text-align: left;\n color: black;\n }\n thead tr {\n background: #f8f9fa;\n }\n .image-pair {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 20px;\n margin: 20px 0;\n }\n .image-item {\n display: flex;\n flex-direction: column;\n }\n .image-caption {\n font-weight: bold;\n color: #1a3c5e;\n margin-bottom: 10px;\n font-size: 14px;\n text-align: center;\n }\n .image-placeholder {\n background: #f0f0f0;\n border: 2px dashed #ccc;\n text-align: center;\n padding: 20px;\n margin: 0;\n color: #666;\n font-style: italic;\n max-width: 400px;\n height: 300px;\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n border-radius: 4px;\n }\n @media (max-width: 768px) {\n .image-pair {\n grid-template-columns: 1fr;\n }\n }\n<\/style>\n\n<script>\n    function copyCode(button) {\n        const pre = button.parentElement;\n        const code = pre.querySelector('code') ? pre.querySelector('code').innerText : pre.innerText.trim();\n        navigator.clipboard.writeText(code).then(() => {\n            button.textContent = 'Copied!';\n            button.style.background = '#28a745';\n            setTimeout(() => {\n                button.textContent = 'Copy';\n                button.style.background = '#007bff';\n            }, 2000);\n        }).catch(() => {\n            alert('Copy failed!');\n        });\n    }\n    document.addEventListener('DOMContentLoaded', function() {\n        document.querySelectorAll('pre').forEach(pre => {\n            const button = document.createElement('button');\n            button.textContent = 'Copy';\n            button.onclick = function() { copyCode(this); };\n            pre.appendChild(button);\n        });\n    });\n<\/script>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Call of Duty 2 Multiplayer: Adding Animated Shutters and Swaying Wires Using Stock _shutter.gsc This tutorial explains how to implement dynamic ambient effects (randomly jiggling shutters and swaying wires) in a CoD2 multiplayer map using the original stock script maps\/mp\/_shutter.gsc. These effects add great life to maps, as seen in classics like mp_toujane. The script [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1639","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/grimms3dworlds.ddns.net\/index.php\/wp-json\/wp\/v2\/pages\/1639","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/grimms3dworlds.ddns.net\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/grimms3dworlds.ddns.net\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/grimms3dworlds.ddns.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/grimms3dworlds.ddns.net\/index.php\/wp-json\/wp\/v2\/comments?post=1639"}],"version-history":[{"count":11,"href":"https:\/\/grimms3dworlds.ddns.net\/index.php\/wp-json\/wp\/v2\/pages\/1639\/revisions"}],"predecessor-version":[{"id":1680,"href":"https:\/\/grimms3dworlds.ddns.net\/index.php\/wp-json\/wp\/v2\/pages\/1639\/revisions\/1680"}],"wp:attachment":[{"href":"https:\/\/grimms3dworlds.ddns.net\/index.php\/wp-json\/wp\/v2\/media?parent=1639"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}