Door Breaching

Overview

For this demonstration, a pair of Combine soldiers appear to breach a door with an explosive and then rush inside. Because of a real door's properties, the script will be taking advantage of the explosion to mask what has really happened: the door has been swapped out for an physics object that looks just like it. Afterward is changing the script to blow a wooden door into pieces or to simply bust through a locked door with brute force, just for S&G.

The map used in this example piece is mapadd_door, a small and unadorned map specially built for this article.

Know that this isn't a how-to walkthrough so much as the author detailing what's occurring in the script, but it should be good enough to help you understand and replicate the effect on your own. Also know that some content in the sample scripts has been omitted from the page for the sake of brevity and such.

The reader should already be familiar with mapadd syntax, grabbing coordinates, using the input/output system, and other basics.

This example makes particular use of these entities:
aiscripted_schedule
env_physexplosion
env_shooter
filter_damage_type
instant_trig
npc_bullseye
prop_door_rotating
prop_physics
point_teleport
scripted_sequence

Blowing It Up

Smoke and Mirrors

Empty_t.jpg

Before doing much else, a suitable door must be set up between the rooms along with other things to make the swap happen smoothly. Below is a single blue door in exactly the spot it's needed, along with a prop acting as its twin and starting far outside the map. Nothing fancy here.

    "prop_door_rotating"
        {
        "origin" "0.0 -93.1 62.0"
        "angle" "0 0 0"
        "keyvalues"
            {
            "targetname" "BustDoor"
            "model" "models/props_c17/door01_left.mdl"
            "skin" "6"
            "hardware" "1" // Lever handle
            "spawnflags" "2048" // Begin locked.
            }
        }
    "prop_physics"
        {
        "origin" "-5000 -5000 -5000"
        "keyvalues"
            {
            "targetname" "BustDoorF"
            "model" "models/props_c17/door01_left.mdl"
            "skin" "6"
            }
        }

The invisible entity below is spawned right in front of the doorway. Its part in the script is to add some oomph to the explosion, and force the fake door fully out of the frame to ensure a clear path. Once used, it will send out a strong spherical shock wave — one that is targeted only at our fake.

"env_physexplosion"
        {
        "origin" "-1 -68 66"
        "keyvalues"
            {
            "targetname" "BustExp"
            "magnitude" "100"
            "targetentityname" "BustDoorF"
            }
        }

This next one's job is to to check the area around the doorway for the player. Once it's detected the player, it will tell the soldiers to begin acting out the breach by triggering a pair of scripted_sequences tied to them. Sequences will be explained in more detail later once the door rigging's complete.

"instant_trig"
        {
        "origin" "-25 -73 8"
        "keyvalues"
            {
            "radius" "80"
            "TouchName" "!player"
            "OnHitTrigger" "seq_Soldier_RSet,MoveToPosition,,1.25,-1"
            "OnHitTrigger" "seq_Soldier_LSet,BeginSequence,,.2,-1"
            }
        }

The next two big players are invisible. Once the explosion happens, these will set the rest of the action in motion. Both must be set in the Entities section to completely work.

    "filter_damage_type"
        {
        "keyvalues"
            {
            "targetname" "BustFilter"
            "Negated" "0" // Only allow...
            "damagetype" "64" // blast damage.
            }
        }
"npc_bullseye" // Monitors the doorway for an explosion.
        {
        "origin" "-25 -73 116" // In the ceiling in front of the door.
        "keyvalues"
            {
            "health" "1000"
            "damagefilter" "BustFilter" // Use BustFilter to filter out all non-explosive damage.
            "spawnflags" "65536" // Non-solid.
            "OnDamaged" "BustDoor,Kill,,0,-1" // Delete the real door.
            "OnDamaged" "BustPort,Teleport,,0,-1" // Place the fake.
            "OnDamaged" "BustExp,Explode,,0.02,-1" // Push the fake around.
            "OnDamaged" "seq_Soldier_LWait,BeginSequence,,1,-1" // Stand back up, rush inside.
            "OnDamaged" "seq_Soldier_RWait,BeginSequence,,.5,-1" //
            }
        }

Also in Entities is a teleport that will be used to bring the fake door into the room. Its origin is slightly different so the door isn't hampered too much by the frame once our shock wave is used.

"point_teleport"
        {
        "origin" "5.0 -93.1 62.0"
        "angle" "10 0 0"
        "keyvalues"
            {
            "targetname" "BustPort"
            "target" "BustDoorF"
            }
        }

Sappers and Sequences

On to the door-busting duo. Soldier01 on the left side of the room and Soldier02 on the right will use a small series of scripted_sequence entities to act out the breach. Sequences force entities to play specific animations and are typically used for in-game cutscenes and such. You can review animations through the Source SDK's model viewer.

In this example, the first and most important sequence is placed immediately left of the door. Below is the entity as it appears in the script.

    "scripted_sequence" // Soldier01 places a grenade by the door.
        {
        "origin" "-20 -33.1 8"
        "angle" "0 270 0"
        "keyvalues"
            {
            "targetname" "seq_Soldier_LSet"
            "m_iszEntity" "Soldier01"
            "m_iszIdle" "CombatIdle1_SMG1"    // Play this anim while waiting for BeginSequence, or before using Entry/Play.
            "m_iszPlay" "GrenPlace"    // Grenade dropped when this anim plays.
            "m_fMoveTo" "2"    // Run to this SS once called by MoveToPosition or BeginSequence.
            "spawnflags" "224"    // AI is essentially disabled.  Won't engage enemies, etc. while grabbed by the sequence.
            "OnBeginSequence" "seq_Soldier_RSet,BeginSequence,,0,-1"    // Partner's dropping a grenade.  Brace for blast.
            "OnEndSequence" "seq_Soldier_LWait,MoveToPosition,,0,-1"    // Our grenade is dropped.  Let's get the hell away.
            }
        }

The other sequences, named LWait, RSet, and RWait are set up alongside the room's walls and keep the soldiers a good distance from the grenade while it's left to explode. RSet is used about the same time as LSet to make Soldier02 run to his bracing position and stand to watch his buddy. Once the grenade is placed, both soldiers use their Wait sequences to duck (MoveToPosition) and then stand back up (Begin Sequence) once the explosion has taken place.

Once the explosion has been detected by our bullseye, the soldiers' sequences will force them to wait a moment before moving onward. The sequences then trigger a pair of scripted schedules, which order the duo to a pair of nodes in the next room:

    "aiscripted_schedule"
        {
        "keyvalues"
            {
            "targetname"    "AIS_Soldier01_Go00"
            "m_iszEntity"    "Soldier01"
            "forcestate"    "2"                 // Prep for potential contact.
            "goalent"        "Soldier01_n00"        // This is our target.
            "schedule"        "2"                // The target is something we want to run to.
            "interruptability" "2"                 // Advance at all costs.  Order will only be interrupted by the soldier's death.
            "spawnflags" "4"                    // This order can be triggered more than once.
            }
        }

That's it. Now when the player comes close to the door (presumably to jiggle the handle and find it locked), the two soldiers will lend a hand.

Metal1_t.jpg Metal2_t.jpg Metal3_t.jpg

Blasting It Apart

Now for a wooden door that bursts into a slew of wood fragments. Why not?

Since the door will be replaced with a shower of wood gibs now, the teleport and fake door are now unnecessary. Instead, a set of five env_shooters will be placed along the door's length in normal increments, each with a different model gib to spawn when triggered. The first such entity:

    "env_shooter"
        {
        "origin" "-1 -75.1 40"
        "keyvalues"
            {
            "targetname" "BustGib"
            "angles" "0 180 0"    // Fire the gibs outward toward the player (prior to shock wave, anyway).
            "shootmodel" "models\gibs\wood_gib01a.mdl"
            "m_iGibs" "4"        // # of wood gibs.
            "m_flGibLife" "10"    // # of seconds the gibs will remain.
            "m_flVariance" "50"    // Gibs' path will be diverted by up to 50 degrees.
            "simulation" "1"        // Gibs will bounce around like a prop_physics.
            "shootsounds" "1"    // Gibs will have wood sounds.
            "m_flVelocity" "1000"
            "delay" "0" // Shoot all the gibs at once.
            }
        }

The door and bullseye must also be fiddled with but most of the work's already done, thankfully. After giving the door a suitably wooden look ("skin" "13"), the bullseye must be told to trigger our new gib spawners like so:

    "npc_bullseye"
        {
        "origin" "-25 -73 116"
        "keyvalues"
            {
            "health" "1000"
            "OnDamaged" "BustDoor,Kill,,0.01,-1" // Delete the real door.
            "OnDamaged" "BustGib,Shoot,,0,-1" // Blast wood fragments all over the place.
            "OnDamaged" "BustExp,Explode,,0.02,-1" // Push the fragments around some more.
            "OnDamaged" "seq_Soldier_LWait,BeginSequence,,2,-1" // Stand back up, rush inside.
            "OnDamaged" "seq_Soldier_RWait,BeginSequence,,1.5,-1"
            }
        }

It could certainly be improved but we've now got a wooden door that scatters into twenty individual pieces once blown.

Wood1_t.jpg Wood2_t.jpg Wood3_t.jpg

Bashing It In

For a less dramatic approach, a swift elbow or boot can get the job done just as well. Civil Protection officers might be preferable for this task because of their animation set, but no matter. The soldiers will do just fine for a simple demonstration.

Working off the first script, the entities interacting with the door are now unnecessary. The teleport, bullseye, shock wave, and twin door can all go. The door and existing sequences will perform the breach on their own now.

    "prop_door_rotating"
        {
        "origin" "0.0 -93.1 62.0"
        "angle" "0 0 0"
        "keyvalues"
            {
            "targetname" "BustDoor"
            "model" "models/props_c17/door01_left.mdl"
            "skin" "6"
            "hardware" "1"
            "spawnflags" "2048"
            "speed" "225"
            "returndelay" "-1"
            "distance" "120"
            "soundmoveoverride" "physics\wood\wood_panel_impact_hard1.wav"
            }
        }

Above, the old door's been tweaked so it flies back with a loud sound once been opened, and will stay open afterward until the end of time. The next thing to do is get rid of the *Wait sequences since a grenade is no longer involved. Their counterparts are placed close to the door and control most of the action now:

    "scripted_sequence" // Soldier01 prepares to bust through the door.
        {
        "origin" "-30 -73.1 8"
        "angle" "0 0 0"
        "keyvalues"
            {
            "targetname" "seq_Soldier_LSet"
            "m_iszEntity" "Soldier01"
            "m_iszIdle" "CombatIdle1_SMG1"
            "m_iszPlay" "Melee_GunHit"
            "m_fMoveTo" "2"
            "spawnflags" "224"
            "OnBeginSequence" "BustDoor,Unlock,,0,-1"
            "OnBeginSequence" "BustDoor,OpenAwayFrom,Soldier01,.45,-1"
            "OnEndSequence" "AIS_Soldier01_Go00,StartSchedule,,0,-1"  // Soldier01 leads 02 inside the next room.
            "OnBeginSequence" "seq_Soldier_RSet,CancelSequence,,1,-1" // Bring 02 back to normal.  AIS can't grab otherwise.
            "OnBeginSequence" "AIS_Soldier02_Go00,StartSchedule,,1.1,-1"
            }
        }
    "scripted_sequence" // Soldier02 stands nearby at the ready.
        {
        "origin" "-20 -112.1 8"
        "angle" "0 90 0"
        "keyvalues"
            {
            "targetname" "seq_Soldier_RSet"
            "m_iszEntity" "Soldier02"
            "m_iszIdle" "CombatIdle1_SMG1"
            "m_fMoveTo" "2"
            "spawnflags" "224"
            }
        }

Mind that sometimes the work of timing animations with events (in this case, at OpenAwayFrom) can be made easier by the Model Viewer. Use the sequence tab to get to the frame you want something to happen at, and divide the value by 30. For instance, if I were to take the value 13.5 from the picture at bottom left and divide it by 30, it would give me 0.45 seconds. It may still take some trial and error afterward to get it just right, but this method can save some time and trouble.

Anywho, the script successfully works once the above changes have been made. With that, the demonstration part of this page is concluded.

mvsoldierelbow_t.jpg Bash1_t.jpg Bash2_t.jpg Bash3_t.jpg

Wrap-Up

It's the intent of this page to serve as a beginning point for your own script ideas. Always keep in mind that just about anything's possible, it's just a matter of figuring how to get there.

mapaddex_dl.png The example scripts and map this article is based on can be downloaded here for reference. Simply rename the one you want to see in action to mapadd_door.txt.


Customization

Mapadd Command Reference (Non-LUA)Command Reference (LUA)Getting StartedPorts 'n' Doors
Alarm, Alarm!Color Correction in SMODDoor BreachingMobile APCsWorking With Dropships
Supply Drop (LUA)Countdown (LUA)
kh0rn3's Mapadd Generator
Scripts addcontentsoverride_classsmod_custom_explosivesmodaclistSMOD Soundscripts

npc_gib_modelnpc_replace_modelnpc_shieldsetnpc_weapon_randomizenpc_weaponweight

excludeweaponsweapon_categoryweapon_customConsole Command List
Other Crosshair CustomizationGenerating AI NodesUsing the NodemakerSubViewCam
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License