Ports 'n' Doors

Overview

This demonstration is intended to help one understand the dead basics of how each section of a mapadd script works together, as well as getting a bit familiar with the game's input/output system. The result will be plain and a little unusual, but it should provide a good starting point for other tutorials.

It can be helpful while going through this page to run SMOD in a window so you can quickly and easily switch back and forth.
You can do this by right-clicking on it in your Steam games menu, choosing Properties, choosing Set Launch Options, and adding -window.

Firstly, we're going to set up a pair of plain (hovering) doors apart from each other. Once we open either door, we'll be teleported right to the other. Afterward, we'll also spawn some enemies in a random spots through the map. These will trigger a sound event once they're all killed.

How-To

About Coordinates

Before we start on the actual script, we need to grab coordinates for where we want to put things. To do this, we can load up a map in SMOD
and use the Impulse 90 command in the console. As you can see below, you'll have a set of numbers pop up in the console once you have.

PortDoor_impulsecon.jpg

These numbers tell us the XYZ coordinates for our current position and the Pitch/Yaw/Roll coordinates for the direction we're facing, the same for our in-game eyes, and the position and facing of whatever surface is under our crosshair's center. As you no doubt figured, we can use these to set the origin and angle values of the doors and our teleport points. Simply highlight the stuff you want to copy, press Control+C and paste it somewhere. For the doors (and most NPCs and physical objects), you should use the coordinates from your eyes or you'll have things stuck in the ground. The doors will hover a tiny bit but that's fine. For the teleports (and a lot of other invisible entities like it), you'll be using the "player position" coordinates instead.

Doors and 'Ports

Now let's begin our mapadd script by creating a new plain text file in SMOD\Mapadd\, using the map's name. In this example, I'll be using the map gm_construct, so I would make a file called gm_construct.txt. Once you've got coordinates for them, start the entities block to put in a pair of doors, with teleports in front of each. Make sure the doors have a model set or you're liable to crash. You should have something like that shown below.

"entities"
    {
    "prop_door_rotating"
        {
        "origin" "1278 2000 32"
        "angle" "0 90 0"
        "keyvalues"
            {
            "model" "models\props_c17\door01_left.mdl"
            }
        }
    "point_teleport"
        {
        "origin" "1278 1900 32"
        "angle" "0 90 0"
        }
    "prop_door_rotating"
        {
        "origin" "1278 4000 32"
        "angle" "0 270 0"
        "keyvalues"
            {
            "model" "models\props_c17\door01_left.mdl"
            }
        }
    "point_teleport"
        {
        "origin" "1279 4100 32"
        "angle" "0 270 0"
        }
    }

If you run the map now, you'll see that a whole lot of nothing happens as-is. To make things work like they should, more keyvalues need to be set and some input/output goodness used.

Below, the first door and teleport have each been given a targetname, which is used whenever entities are to interact with one another.
The door also has an output action set, which is used to send the player to Tele2 whenever the door opens all the way. The teleport's target keyvalue has been set too so that it will teleport the player whenever its Teleport input is triggered by one of our doors.

"prop_door_rotating"
        {
        "origin" "1278 2000 32"
        "angle" "0 90 0"
        "keyvalues"
            {
            "targetname" "Door1"
            "model" "models\props_c17\door01_left.mdl"
            "OnFullyOpen" "Tele2,Teleport,,0,-1"
            }
        }
    "point_teleport"
        {
        "origin" "1278 1900 32"
        "angle" "0 90 0"
        "keyvalues"
            {
            "targetname" "Tele1"
            "target" "!player"
            }
        }

Once you've given the second set their appropriate values, that should be that. Now once either door has been opened up, you'll magically end
up near its counterpart.

Critters and Noise

On to our randomly spawned creatures and the triggered sound. We'll start by creating a Randomspawn section above our existing script. After that, a block for a ground NPC (below, 4 antlions) or somesuch can be made.

"Randomspawn"
    {
    "npc_antlion"
        {
        "count" "4"
        "values" "targetname Ant spawnflags 256"
        }
    }
    "removenodes"
        {
        "origin" "704 132 -144"
        "radius" "800"
        }

Note the way the antlions have been given keyvalues; the format for this kind of section is quite different from the norm. One of the two keyvalues is a spawnflags number which are used to set entity properties, kind of like other keyvalues. In this case, it makes the antlions see farther than normal since the example map is quite large. You can use multiple flags by combining their values. For example, if we wanted a soldier to see farther and drop a health pack or battery once killed, we'd combine 256 and 8 to make it 264.

Moving on, I've also put in a removenodes block at our starting position. The purpose of this is to take all the nodes within 800 units (about 50 feet) of us and block NPCs from randomly spawning to them. This lends us some breathing room to look around and get ready for killing the opposition.

Speaking of killing, we still haven't given ourselves any equipment to nab the antlions with. While we're at it, I'm also going to set a new starting position for myself on the roof behind me. After grabbing the coordinates, I'll start a new labeled section since you can't mess with the player entity from Entities.

"Entities:NewStart"
    {
    "player"
        {
        "origin" "1200 175 128"
        "angle" "0 180 0"
        }
    "item_suit"
        {
        "origin" "1200 175 128"
        }
    "weapon_kar98"
        {
        "origin" "1200 175 128"
        }
    "item_ammo_357_large"
        {
        "origin" "1200 175 128"
        }
    }

In Entities, we'll also put an instant_trig so that the script runs everything in NewStart at the beginning of the map.

    "instant_trig"
        {
        "keyvalues"
            {
            "Label" "NewStart"
            "Timer" ".01"
            }
        }

We'll create and trigger our sound event in a similar way. In this sample piece, I want to use a simple "Boop!" sound, so I'll create another label:

"entities:AntDead"
    {
    "sound"
        {
        "soundname" "buttons\button17.wav"
        "targetname" "!player"
        }
    }

and another instant_trig with the AntDead label that triggers when all the entities named "Ant" are killed or deleted.
Only one last bit of work remains. Before we can play the sound, we need to load it into memory ahead of time. I can do this by creating a
Precache section above Randomspawn like so:

"Precache"
    {
    "sound" "buttons\button17.wav"
    }

Wrap-Up

All done. The script should work exactly as described in the overview and you should now have a better idea of how things on the general Mapadds page tie together. You should also be in working shape to jump into the other mapadd tutorials and examples on this wiki if you choose.

PortDoor1_t.jpg PortDoor2_t.jpg PortDoor3_t.jpg
mapaddex_dl.png The example script this article is based on can be downloaded here for reference.


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