Battery Frontdoors

In this tutorial: opening a door via a lever like the frontdoors in battery.

A prefab for this tutorial is available here: prefab_battery_front_doors

The Lever
———————

Entities you need:

– 1 func_invisible_user // this thing is the button
– 1 target_script_trigger // triggers a code section in script when activated
– 1 script_mover // the lever which moves
– 2 path corners // endpoints for moving the script_mover

By now you should have looked at the prefab how it is arranged. Here the key-pairs for our entities:

“classname” “func_invisible_user”
“cursorhint” “hint_button”
“target” “frontdoor_trigscript”
“scriptname” “frontdoor_invtrig1”
“targetname” “frontdoor_invtrig1”

“targetname” “frontdoor_trigscript”
“origin” “-144 976 360”
“classname” “target_script_trigger”
“scriptname” “frontdoor_trigger1”
“target” “main”

“classname” “script_mover”
“targetname” “frontdoor_lever1”
“scriptname” “frontdoor_lever1”

“origin” “-176 991 310”
“targetname” “frontdoor_lever1_uppos”
“classname” “path_corner”

“classname” “path_corner”
“targetname” “frontdoor_lever1_downpos”
“origin” “-176 991 296”

The Doors
———————

Entities you need:

– 2 script_movers // the doors which move
– 4 path_corners // endpoints for moving the script_mover

Here the key-pairs for our entities:

“classname” “script_mover”
“spawnflags” “2”
“targetname” “frontdoor_left”
“scriptname” “frontdoor_left”

“classname” “script_mover”
“targetname” “frontdoor_right”
“spawnflags” “2”
“scriptname” “frontdoor_right”

“origin” “-400 762 264”
“classname” “path_corner”
“targetname” “frontdoor_left_pc2”

“targetname” “frontdoor_left_pc1”
“classname” “path_corner”
“origin” “-400 816 264”

“targetname” “frontdoor_right_pc2”
“classname” “path_corner”
“origin” “-400 886 264”

“origin” “-400 832 264”
“classname” “path_corner”
“targetname” “frontdoor_right_pc1”

The mapscript
———————

game_manager
{
spawn
{
wait 200
wm_allied_respawntime 1
wm_axis_respawntime 1
wm_set_round_timelimit 20
wm_setwinner 0

// Set doors to operable at game start (0 = operable, 1 = disabled)
globalaccum 1 set 0
}
}

frontdoor_trigger1
{
spawn
{
accum 5 set 1 // Initial state is down
wait 500 // Wait for everything to settle
trigger frontdoor_trigger1 main // Open front door of complex initially
}

trigger main
{
globalaccum 1 abort_if_not_equal 0
trigger frontdoor_trigger1 up
trigger frontdoor_trigger1 down

}

trigger up
{
accum 5 abort_if_not_equal 1 // Ready to run up routine == 1
resetscript // return to trigger that called it

trigger frontdoor_lever1 up
accum 5 set 0 // Setup accum for up routine
}

trigger down
{
accum 5 abort_if_not_equal 0 // Ready to run down routine == 0
resetscript // return to trigger that called it

trigger frontdoor_lever1 down
accum 5 set 1 // Setup accum for up routine
}
}

frontdoor_lever1
{
spawn
{
}

trigger down
{
gotomarker frontdoor_lever1_downpos 16
playsound sound/movers/switches/butn2.wav
trigger frontdoor_left open
trigger frontdoor_right open
}

trigger up
{
gotomarker frontdoor_lever1_uppos 16
playsound sound/movers/switches/switch.wav
trigger frontdoor_left close
trigger frontdoor_right close
}
}

frontdoor_left
{
spawn
{
}

trigger open
{
wait 500
playsound sound/movers/misc/big_gate1.wav volume 127
wait 350
enablespeaker frontdoor_sound
gotomarker frontdoor_left_pc2 15 wait
disablespeaker frontdoor_sound
playsound sound/movers/misc/big_gate3.wav volume 127
}

trigger close
{
wait 500
playsound sound/movers/misc/big_gate1.wav volume 127
wait 400
enablespeaker frontdoor_sound
gotomarker frontdoor_left_pc1 15 wait
disablespeaker frontdoor_sound
playsound sound/movers/misc/big_gate3.wav volume 127
}
}

frontdoor_right
{
spawn
{
}

trigger open
{
wait 850
gotomarker frontdoor_right_pc2 18 wait
playsound sound/movers/misc/big_gate3.wav volume 127
}

trigger close
{
wait 500
playsound sound/movers/misc/big_gate1.wav volume 127
wait 350
gotomarker frontdoor_right_pc1 18 wait
playsound sound/movers/misc/big_gate3.wav volume 127
}
}

How everything works
———————

frontdoor_trigger1 is the main entry point. It is our target_script_trigger entity. It gets activated by our func_invisible_user entity. Once activated it will enter the script in frontdoor_trigger1 -> main.

trigger main
{
globalaccum 1 abort_if_not_equal 0
trigger frontdoor_trigger1 up
trigger frontdoor_trigger1 down

}

There it checks if the globalaccum 1 is 0, and if not, it will abort and just return (do nothing). This is how the battery doors work, because the doors can’t be moved once the generator is destroyed. When globalaccum 1 is 0 however, then the door is operable and it will go to the two trigger code sections called “trigger frontdoor_trigger1 up” and “trigger frontdoor_trigger1 down”.

Inside one of these it looks like this:

accum 5 abort_if_not_equal 1 // Ready to run up routine == 1
resetscript // return to trigger that called it

trigger frontdoor_lever1 up
accum 5 set 0 // Setup accum for up routine

Ignore the accum 5 thing for now. This will be for you to figure out (i am really justr too lazy to explain *cogh* ). Try what happens when you remove these lines.

After it passed the accum 5 test the script gets reset with “resetscript” command (this says that any currently running scripts will get aborted). From there it goes to “trigger frontdoor_lever1 up” or “trigger frontdoor_lever1 down”. Here is where the interesting stuff is happening. Let’s just look at trigger up (trigger down is similar).

trigger up
{
gotomarker frontdoor_lever1_uppos 16
playsound sound/movers/switches/switch.wav
trigger frontdoor_left close
trigger frontdoor_right close
}

Here the lever gets moved. “gotomarker frontdoor_lever1_uppos 16” simply says: go to the path corner labeled with the targetname “frontdoor_lever1_uppos”. Do so with a speed of 16. Then a sound is played with the playsound command (which happens pretty much just a few nanoseconds later …). Then we jump into the sections to close the two gates. Here we look at just one gate. The other is similar:

trigger close
{
wait 500
playsound sound/movers/misc/big_gate1.wav volume 127
wait 400
enablespeaker frontdoor_sound
gotomarker frontdoor_left_pc1 15 wait
disablespeaker frontdoor_sound
playsound sound/movers/misc/big_gate3.wav volume 127
}

What happens here is that after 500 milliseconds a sound is played with the playsound command. After another 400 milliseconds another sound is played with the enablespeaker command. The difference between these two commands is that the playsound command is related to the entity and will play its sound around the location of this entity. The enablespeaker, on the other hand, is an entire new beast. It is connected to the ingame speakereditor. No panic however: the speakereditor is just another way of modifying sounds in your map. It is easy to do and actually quite handy.

The speakereditor is the last piece of work for us to do (see “Speaker Editor Work” in this tutorial). If we would not do this work, then the door slide sound will simply be missing.

Continuing in the script, after the two sounds are played the entity gets actually moved with the gotomarker command. “gotomarker frontdoor_left_pc1 15 wait” simply says: go to the path corner labeled with the targetname “frontdoor_left_pc1”. Do so with a speed of 15 and wait with executing the next command until the movement is actually finished.

Note that it is the origin of the script_mover actually moving there. Imagine it just like a point moving to another point. So the origin of the script_mover moves to the origin of the path_corner.

After the door moved to its specified place, we are done! All that is left to do is disable the speaker entity again, and play another short closing sound.

Speaker Editor Work
———————

As a final step we need to dump a speaker entity in the map, right above the gate. We describe only a few basic commands of the speakereditor, for more info check: http://magics-territory.com/et/et_info/level_designers_reference/etdocs/speakereditor.html

To get into the editor type: “editspeakers”. Once in you want to dump a sound entity. Go to the place where you want to dump it and type “dumpspeaker”. Once dumpped, point your crosshair at it and type “modifyspeaker”. Now enter the values like in the pic:

Type “editspeakers” again to leave the speaker editor, then quit the map. Upon restart, your new entity should be functional and reachable with the enablespeaker command.

Small sideinfo: the sound script will get saved to /sound/maps/mapname.sps. For me it looks like this:

speakerScript
{
speakerDef {
noise “sound/movers/misc/big_gate2.wav”
origin -415.86 823.12 425.11
targetname “frontdoor_sound”
looped “off”
broadcast “no”
volume 127
range 1250
}
}

That’s it. Have fun!