-
Notifications
You must be signed in to change notification settings - Fork 2
Obstacle Course Tutorial: Building a level
First off we'll need a DB prim:
- Create a box prim and stretch it out as a platform.
- Create a cube and name it DB. Make it hollow, and add a little bit of path cut. The hollow/cut isn't necessary in the current version, but might be used in a future one.
This is the easy, but time consuming part. Just place the unscripted parts where you want them to be.
The Game Controller is the prim that controls everything about your level. The philosophy of ObstacleScript is that every level is its own unique mini game with unique rulesets and code. From the script templates folder, drop Level, Rezzer, and Spawner into the Game Controller.
Then wear the HUD and say debug Level
in chat to update these scripts with the latest version.
Drop these 3 template scripts from the script folder into the Game Controller: #Dialog
, #Game
, and #Obstacles
. Then drop any assets you want to use into the Game Controller. It's not that important that you drop the assets in immediately, but they need to be there before you play the game. If you're looking for official assets, rez the HUD to the ground (or edit linked parts and scroll down) and edit the red box.
An Asset is a scripted object that gets spawned by the Game Controller, such as a crusher wall or tentacle.
Place the crusher walls where you want them and edit their description. The first value is a vector of the wall's scale. If you resize the wall, you'll have to change this vector accordingly. The second one is a unique ID. The first crusher wall should have the ID 0, next 1, then 2 etc. The third value is a vector of where the wall should move when retracting relative to the wall's local axis. The final value is the time in seconds the wall should take to reach its destination.
Next type SAVE
into chat to store all the spawned Assets in the Game Controller database. Type LIST
to see what the database looks like. See the home page for a full list of chat commands.
Next edit the #Obstacles
script to look like this. The CRUSHERS functions are defined in the CrusherWall obstacles header. You can write your own algorithm if you don't want to use mine. See said header file for information on how to send commands to the walls.
Rez the water asset and stretch/position it to your liking. Then take a copy of it and drop it into the Game Controller.
Type SAVE
to store it.
Rez them out and save them, there isn't much configuration to be done here.
I suggest you use the Trap Obstacle Header File to simplify use of traps. But you're free to write your own. Here I've added a rudimentary trap handler to #Game that auto seats players on the trap when the trap is triggered. Note that having the canTrapPlayer callback always return TRUE means that the player will be immediately trapped again after unsitting. We'll go into more detail about proper trap management in the tutorial on scripting.
The crusher tentacle description has 2 arguments. The first is a unique ID and the second is the texture. If you want to use the inflatable texture instead of the default one, put 1 as the second argument. Position and save it as per usual.
I've added 2 lines to my #Obstacles script: setInterval("TENT", 2);
in onStateEntry to set a repeating timer every 2 seconds. And Trap$attackAll("*", [])
in the timer handler which tells all traps in the level that have the attack task defined in the Trap Obstacle Header File implemented to use their attack, whatever it may be. Normally you'd call these by ID. But since the crusher tentacle is the only trap in this stage that accepts that method, I just send out "*" to trigger all of them regardless of their ID. The seating is handled by the same trap handler we put into #Game for Wall tentacles.
Rez, position, and save the tumbling beam. Technically the tumbling beam is just a ladder. But we'll capture the ladder event and do a quick time event in #Game.
Here we capture the onStairSeated event and check for the name of the object the player sat on. If it's "TumblingBeam", we'll start a quick time event with the callback "TUMBL" for whenever it ends. We also capture the onPlayerQteEnded event, and if the callback was "TUMBL" and unsuccessful, unseat the player.
Rez it out and alter the description. See the Trapdoor header file for how the description is structured. Save it as per usual.
The level also uses a custom, shorter version of the trapdoor. All you have to do after editing an Asset is to take a copy and drop it into the Game Controller. Then save it as per usual.
When a user steps on the trapdoor, the onTrapdoorTrigger( trap, label, player )
event will be raised on all scripts in the Game Controller. Capture it and send Trapdoor$trigger( label )
in order to actually activate the trapdoor. This is part of the philosophy that each stage is a mini game on its own, and your level decides how assets should behave.
Rez a trigger and position/resize it to your liking. Update the description. The first value is the size of the trigger, just copy the size of the box and put it there. The second is a unique ID for the trigger, which is passed to the onTrigger( object, player, label )
level event. The final value is flags. See the trigger header file for more info.
Next, let's tie everything together in the Scripting Tutorial.