Sunday, 10 January 2016

Create your own Rail Fan Scenarios!

Creating Rail Fan or Trainspotting scenarios is almost identical to making a standard scenario, so if you've already got the hang of making your own scenarios then this will be easy!  If you haven't, this might be an interesting place to start because these are generally a bit easier than scenarios due to the player not actually moving anywhere.

The first step is to actually get in to the world editor and create a scenario, so from the main screen click the Build menu, then select the Scenario tab.

Scroll through the list that's presented until you find the route you want to make your Railfan scenario, select it and then click New Scenario.

On the dialog box that comes up, type in a name for the scenario, select "Standard scenario" as the type and then in the "Set Location" area see if the location you want is roughly there (on all steam DLC routes you should find one location for each station on the route), if not then select Route Origin.  Click Create.

Required Assets


Think about the kinds of trains you're going to want to include and let's get them enabled in the Object Set Filter.  Be selective about what you include because every tick box you enable is a piece of DLC that someone must own to run this scenario if you choose to share it on Steam Workshop.  Also, keep in mind that the game will load every asset contained in that package even if you just use one wagon out of it, so try not to pick a large package without making as much use of it as possible.

To enable items, you need to open the Object Set Filter, highlighted on the screen capture.

Once you click this, a window will be available on the top right hand side (you may need to move your mouse over it to make it fly out and be visible).  This will contain a drop-down box containing "providers" and a list of "products" for each one.  You will find most Dovetail steam content in either the "RSC" or "DTG" provider.  You should generally be able to recognise or guess what's in each of the products based on their name.  Tick the MIDDLE checkbox in order to enable it's rail vehicles for your scenario.


One important asset you must enable is the Railfan "loco" - this is included in new DTG products and there is a copy in each of the provider/product packages for the routes contained within TS2016.  For example, if you find provider DTG and product ExeterKingswear you will enable the Riviera in the 50's assets, which will give you the Railfan "loco".  If you don't have one of these products you could just use a regular loco.

The Player


The first thing you're going to want to do is find somewhere to place the invisible "player train".  Ideally this should be situated on a siding or a track that isn't going to be used, somewhere in the close vicinity of the station.

If you click on the loco selection icon in the middle-left flyout and then scroll through the list you should find the simply named "Railfan" entry as shown on this screen capture.

Once selected, simply place it somewhere just as you would a normal locomotive.  It looks like the cinematic camera icon.


As you can see, it's pretty small, and if you try to place it in the same are as a track marker you likely won't be able to see it - so find somewhere clearly visible and it should place fine.

Next, place a driver icon on it in the usual way.

Click on the timetable icon in the top left flyout and then you can start setting the player side of things up, this is really where the framework for the Rail fan scenario will be created.













As shown in the image to the left, essentially you want to add three instructions.













1. Trigger Instruction - this will be used to set up the LUA script that we write shortly.  Put "start" in the first smaller text field, you'll find out what it does soon.

2. Stop At - use this to tell the player train it needs to go somewhere, anywhere that's not near you will do, but it must be somewhere you could get to.  The player train won't be moving so it's fine.  Also keep it simple, add a new marker if necessary.

3. Final Destination - it's the player train so it must have a Final Destination instruction, just make it the same as the marker you set for the Stop At instruction.

The LUA Script

Now that the player train is set up we need to set the LUA script up.  If you're not a developer or haven't done any LUA scripting at all this might seem daunting, the good news is that it's really mostly a copy-paste task and you can re-use the same basic script over and over with almost no changes at all.

While still within the timetable window, click on the Script icon on the toolbar at the top of the service instructions:






In the window that pops up, don't worry if it gives an error about not being able to read a file - we haven't created it yet.  Click the Open Folder button and a Windows explorer application will open, pointing to the folder where the scenario data files are kept.

Create a new text file in here called ScenarioScript.lua and open it in your favourite text editor - I use Notepad++ but there are many great editing tools out there that will do the job nicely, even Notepad will do in a pinch :)

When you create the file, ensure that it does not retain the .txt extension.  When you're done, in Explorer it should show up as a file of type "LUA file".  If it still shows up as a file of type "Text file" then this is incorrect and means that internally in Windows it still thinks the file is ScenarioScript.lua.txt - even if all you can see is ScenarioScript.lua.  Click the View menu and on there ensure "filename extensions" is ticked.  If it isn't then when you tick it, you should see the full name of your file revealed and you can then rename it to fix it.

Next i'm just going to paste the whole file in, and then we can talk about what it is actually doing:

-- true/false defn
FALSE = 0
TRUE = 1

-- condition return values
CONDITION_NOT_YET_MET = 0
CONDITION_SUCCEEDED = 1
CONDITION_FAILED = 2

-- Message types
MT_INFO = 0   -- large centre screen pop up
MT_ALERT = 1  -- top right alert message

MSG_TOP = 1
MSG_VCENTRE = 2
MSG_BOTTOM = 4
MSG_LEFT = 8
MSG_CENTRE = 16
MSG_RIGHT = 32

MSG_SMALL = 0
MSG_REG = 1
MSG_LRG = 2

function OnEvent(event)
    return _G["OnEvent" .. event]();
end

function TestCondition(condition)
    return _G["TestCondition" .. event]();
end

function OnEventStart()
    SysCall("ScenarioManager:LockControls")
    SysCall("CameraManager:ActivateCamera", "startcamera", 0)
    SysCall("ScenarioManager:TriggerDeferredEvent", "WelcomeMessage", 17)
end

function OnEventWelcomeMessage()
    SysCall("ScenarioManager:UnlockControls")
    SysCall("ScenarioManager:ShowInfoMessageExt", "Knebworth Trainspotting", "Wait, we stopped?!", 15, MSG_LEFT+MSG_TOP, MSG_SMALL, TRUE)
    SysCall("CameraManager:ActivateCamera", "FreeCamera", 0)
    SysCall("ScenarioManager:TriggerDeferredEvent", "End", 300)
end

function OnEventEnd()
    SysCall("ScenarioManager:ShowInfoMessageExt", "Knebworth Trainspotting", "Time to go!", 15, MSG_LEFT+MSG_TOP, MSG_SMALL, TRUE)
    SysCall("ScenarioManager:TriggerDeferredEvent", "Complete", 0)
end

function OnEventComplete()
    SysCall("ScenarioManager:TriggerScenarioComplete", "Finished!")
end


The first block lists a selection of "constants" which are used to make the rest of the code a bit more readable.  You shouldn't ever need to edit these constants but if you start getting more complex with your scripting you may wish to add more to them - you'll know it when you want to!

The first two functions "OnEvent" and "TestCondition" set up a basic system that will make handling events more straight forward, you'll never need to edit these functions.

After this is when we start to get to the bits that are specific to our Rail fan scenario.

The function OnEventstart() is called by the game when our scenario starts.  You'll recall earlier we set up a trigger instruction and put "start" in the field - this is where that happens.  If you put "fred" in that field, then you'd need to rename this function "OnEventfred()" for it to work, whatever you put in that trigger field is what will end up being called in the script.  For simplicity, i'd just leave it as "start".

OnEventstart() locks the controls - you can choose to eliminate this line if you prefer, it just prevents the user from doing anything while you're introducing the scenario.  The next thing it does is to activate a cinematic camera called "startcamera" - you can add cinematic cameras later following one of my other tutorials, I won't go in to details and repeat that tutorial again here.  finally, it uses "TriggerDeferredEvent" to tell the script when to carry on - you should set this up so that it matches the time for your cinematic camera, if it lasts 25 seconds then put a "25" where there is a "17" in this line, it's that simple.  If you get it too short it will simply cut the cinematic camera sequence short.  Once this timeout expires it will call the next function - note the event is "WelcomeMessage" and therefore this leads us to the next function:

OnEventWelcomeMessage() unlocks the controls (if you remove the lock, you can remove the unlock too of course), pops up a message introducing the scenario to the player, activates the "free" camera allowing the player to move freely around the route and then sets up a timer to end the scenario.  This number is in seconds, the example above is 300, which is 5 minutes.  Once this timeout expires it will fire a further event "End" - bringing us to:

OnEventEnd() - this pops up a farewell message and then sets up another deferred event which will happen immediately.  This is just to return control to the game and let it handle the pop-up box.  The event is Complete:

OnEventComplete() will then finally issue a TriggerScenarioComplete system call which will cause the game to pop up the "Scenario Complete!" message box and end the scenario successfully, giving the user their green tick for completing the scenario.

Ok, so there's plenty to go through there and i'd recommend just reading through that description a couple more times until you understand it a bit better.  Remember that as long as you use the same names in future scenarios for things like "start" and "startcamera" you can literally copy/paste this script in to each Rail fan scenario you use and then make just two changes to make the whole thing work.

Change #1 - How long is your cinematic sequence? Set the time for that in OnEventstart(), it's set to 17 in the example above.

Change #2 - How long is your scenario? Set the time for that in OnEventWelcomeMessage(), it's set to 300 (5 minutes) in the example above.

Once the script is done, save it from your text editor and return to the game.  Click the "Reload" and "Compile" buttons and that's all you need to do.  If you find you need to make any adjustments just re-edit the file in your text editor, click the Script button on the toolbar in the timetable mode, click Reload and then click Compile.

Adding AI trains


Add AI trains in the nomal way!

Well.. nearly.  Remember the player train isn't moving, the player is naturally going to be sitting fairly well in the initial environment you set up for them.  Start trains close(ish) to the station so that they go through at the speed you want and work your way out away from the station setting up trains to come in one after the other almost like a parade of trains in a simple presentation.  The moment trains are out of visual sight aim to get them to disappear in to a portal as quickly as possible so that they're no longer in your way or consuming processing time on the computer.  This will also make it easier to set multiple trains to go through as you can just throw them all in to a portal and not have to worry about whether one train is blocking another.

General Tips for a Rail Fan scenario


Don't make it too long or it gets boring, remember the absolute entirety of what is keeping the player interested is those AI trains.  A 5 minute gap, however realistic it might be, can be interminably long with absolutely nothing else happening in the game.  Could you set up something in a nearby yard perhaps with a shunter to keep things moving during quieter times?  Perhaps beef up the timetable and make it slightly "hyper real" in order to keep it interesting.

Find the right place to set your scenario up so that you can acheive the above, you might want to recreate trainspotting at your local station, but if there are really only a couple of trains an hour then it's just not going to hold enough interest for anyone but you.  If you're just doing it for you, that's perfectly fine, but if you want to share it then you have to keep it interesting and put that above all else.

Perhaps use pop-ups to suggest "go to the north end of the platform for a great view" - where should the player actually stand for a good view? Have you any tips on how best they can enjoy this scenario?

Don't forget to get things like the scenario end functionality working, it's really nice to have a scenario actually tell you it is finished and then say "Scenario Complete" rather than leaving the player to wonder if this is just a quiet bit in the scenario or if it's all done now? The script above does this for you and while LUA script might be daunting I would encourage you to make the effort to get it working for you as it ups the professionalism of your rail fan scenarios considerably.

Some of the more interesting scenarios i've seen actually end with an AI train coming in and stopping on the platform that the player is notionally supposed to be on, as the doors open the end message comes up saying that it's time to catch your train and leave - that's awesome!

You can tune where the camera starts at the beginning of the scenario by moving the scenario marker around and placing it in the right place at the right angle.  Experiment to understand how this works and get the best effect.  Some have started it on the platform next to a soon-to-depart AI train (as if you just got off it), or even by a car in a car park.






That's all you need to know, I look forward to seeing your awesome Rail Fan scenarios on Workshop!

I hope this tutorial has been useful, I have a YouTube video to be uploaded soon which goes through all of these steps visually.  Hopefully this blog entry has expanded on what I discussed in the live stream for those who were watching and will help you get the most out of it.