|
|
|
|
All use of my digital work is covered by this
Creative Commons Deed.
Please do not use any of my work for commercial purposes, thank you. |
|
|
|
RTCW: Scripted Doors (1 of 1)
|
|
|
|
|
|
|
|
|
|
|
|
Return to Castle Wolfenstein (RTCW) has a lot of potential to make more interactive environment
via scripting. This example intends to show you how to create a scripted door which can be
operated via 1 or 2 switches in either MP or SP maps.
This example does assume that you are familiar with how to create a map, compile and run it in
the game. There is plenty of other sites around which deal with these topics. No point in duplicated effort.
The download link above contains the original map, a compiled bsp and relevant script files.
If you open the map file up in GTKRadiant you will notice that there is alot of entities around the doors and levers.
The entities work slightly different depending if you use MP or SP. Below I have labelled a top down section of the map
so that you can understand the entities I am talking about.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
A : The main door is made up from two script_mover's called "door_left/right" and have origin brushes at the base.
The path_corner entities are lined up with the origin brushes and are used for movement of the doors. All control of the doors
is operated via the script so no other entities are needed.
B : The levers on the walls either side of the doors are made up from script_movers with a func_static
brush casing. Func_static entities can be triggered on/off via the script so that you can change the appearance of the map.
An example of this is in MP_BASE in the tunnel where the main gates are. On the wall is some levers which are used to open the main gate.
During CheckPoint (CP) gameplay mode the gates and levers are removed via the script.
The levers have path_corners for movement during the opening of the door sequence. The timing of the levers are restricted via the
entities with a wait "key" to stop a player constantly open/closing the door all the time. Its a shame this timing function was not
implemented in the script system.
The levers are also surrounded by a 'func_invisible_user' trigger brush. These triggers are used in game to tell players that when
they are near something they can use/operate. Like 'func_static' entities the 'func_invisible_user' entity can be switches on/off
during gameplay. Depending on which game you play (SP/MP) the 'func_invisible_user' entity is used differently.
In MP(MultiPlayer) the 'func_invisible_user' entity has to be linked to a 'target_script_trigger' entity which then calls the
relevant routine in the script file. In SP(SinglePlayer) the 'func_invisible_user' has to be linked to the AI script via the 'ainame'
key which then uses the target field for the routine trigger. This is slightly confusing but needs to be considered if
you are making your map for SP or DM.
C : The 'target_script_trigger' is linked to the two 'func_invisible_user' triggers. This
entity is really only used in MP maps and does not need to be present in SP maps. I've included it so the map can be run
with both exe's for wolf.
D : A spawn for 2 AI creatures which will spawn when you go near the trigger in the other room. They will go
into a crouch position and wait for you to pop your head around the corner. They are not very intelligent and will not
follow you around the rooms either. Just created to show the different between SP and DM while running the map.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Usually before I start writing the script I find it easier to draw out the sequence of what is going to happen on paper.
Some people can just write the scripts as if writing a letter, but I need something visual to understand what is going on.
Above is a quick diagram I did of how the different entities in the map will interact with each other.
I find it easier to imagine the entities like a 'tech tree' with simple stuff like 'path_corner' entities at the bottom of the
sequence and 'target_script_trigger' entities at the top. Generally you keep all 'accum' variables at the top of the tree
because wolf does not have global variables. The variables have to sit in the routines that are going to maintain and conditionally test them,
so plan their location carefully.
You could get round the problem of global variables by having one routine BUT this would not work because RTCW is not multitasking
within routines. RTCW will happily run several routines together but not several functions inside of 1 routine. So you have to create seperate
sections of script.
Once I have planned out the sequence of entities and decided where I want the 'accum' variables I will write the 'entity tree'
backwards like with the 'script_mover/path_corner' entities first. This is purely up to you but I find it simpler as the
stuff at the bottom of the 'entity tree' is always quick and easy.
The initial script file is different depending on which game exe you are running :-
- MP uses the [map name].script file located under the map directory.
- SP uses the [map name].ai script as the primary file and the [map name].script file
second.
The SP wolf will look at the AI script first and run a standard routine called 'player'. This is a special routine
which must exist and controls how the player will start the map. You can define objectives, player items, special variables,
spawn functions and level specific functions and triggers under the 'player' routine. When running SP Wolf this is the
routine to check out as it contains all events which affect the player during game time.
In the AI script under the 'player' routine is the function 'door_trigscript' which is called via the 'func_invisible_user'
entities. This function/trigger will then call the routine in the other script file. (If you are confused at this point, trust me
I was as first, but after alot re-reading it will make sense)
The rest of the AI script deals with the startup of the map and what happens to the AI creatures and not much else to do with
the scripted doors. The AI script is included so that you can play the map in SP. Script_mover entities work perfectly well
without AI script files, except the odd entity or two like 'func_invisible_user'. ;)
The MP wolf uses 'target_script_trigger' entities to do the work of the AI script file, so that is why wolf MP really only
uses 1 script system.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
One problem with scripting for wolf is the serious lack of control structures like if/end, for/next, while/wend. So to get round
this problem you have to do the control structures via functions instead. It may sound wierd at first but all you are doing is
simply seperating the script code into smaller chunks with control tests at the front. (nudge, nudge, dont fall asleep just yet!)
|
|
|
|
|
|
In a traditional code/script program you could test a variable for being in a certain state with something like an 'if/end'
control structure. If the condition was true then the code/script below would be executed or the program would skip to
the end of the control structure and carry on with the next chunk of code.
Well RTCW does not have this luxury of simple control structures so you have to do things slightly different but ultimately
achieving the same goal. Like all things in life there is always a way round the limitation of a situation.
|
|
|
|
|
A typical wolf script structure where you define the entity scriptname at the top "routineA"
with the various functions below it like spawn/trigger etc.
The spawn function is excuted during the start of the script and sets the 'accum' variable 5 to zero.
"RoutineA" will then wait to be triggered via 'functionX'.
When "functionX" is triggered it then needs to execute a section of script code based on the 'accum' variable.
The section of code which needs to be executed is in a seperate function called "functionY".
So "functionX" calls "functionY" and then the 'accum' is tested at the beginning of "functionY". If the 'accum' variable
is not the correct value then the function automatically exits with the 'resetscript' command. This command will then return
control back to the "functionX".
A simple example of how you can create a control structure with RTCW and how to use the 'accum' variables. With this
code structure example under your belt lets get back to the door script example.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The door script is controlled from one routine called 'door_trigger1' so that the 'accum' variable is constant across the same
routine. RTCW does not have global variables so choose carefully where you are going to locate them. This routine has a spawn
function which sets up the door status variable and triggers the door into a close state. (I initially set up the doors slightly
opened so that the inside edges of the door are lit better.)
One thing to remember is that any entity movement defined in the 'spawn' function MUST have a pause before it.
The reason for this is that all entities are not spawned at the same time in the map and may not be ready for the script file.
The primary function is called 'main' which in turns calls the the up/down functions to move the lever/doors in either an up/open or
down/closed state. Each up/down function checks the 'accum' variable and stops if the wrong state is set. Otherwise the
routine will excute the required function, set the accum and finish.
The code is setup in a very simple form which can be adapted to many different styles of script_movers. Doors is a simple
example but it could have equally been a lift, platform, brush structure etc.
|
|
|
|
|
|
|
|
|
|
|