Bus Routes

This article gives the steps to create buslines, a route for the bus, which is composed of a number of bus stops.

Files and Folders setup

  1. Create two new folders in the level you want to modify:

    • scenarios
    • buslines

    For example, if you are modifying the “smallgrid” level, create the folders in ..\levels\smallgrid\

If these folders already exist in the level you are modifying, skip this step.

  1. Inside the scenarios folder, create a new folder and name it “bus”.

    Inside the bus folder, you would need to create a bus_level.json file. The content of the files should be as follows:

[
    {
        "name": "bus_level",
        "description": "bus_level",
        "authors": "Your Name",
        "introType": "none",
        "difficulty": "22",
        "date": 1494325025,
        "levelObjects": {
            "tod" : {
                "time" : 0.11,
                "play" : false
            }
        },
        "vehicles": {
            "scenario_player0": {
                "playerUsable": true,
                "startFocus": true
            },
            "*": {"playerUsable": false}
        },
        "radiusMultiplierAI": 2,
        "extensions": ["busdriver"],
        "busdriver": {
            "routeID": "1",
            "variance": "a"
        },
        "statistics":
        {
            "disableEndUI": true
        }
    }
]
  • Modify the first two variables, "name" and "description" by replacing the level part with the name of your level, for instance, use bus_utah.json if you are modifying the level “Utah”. Remember that this naming rule is not strict. In this example the "bus\_grid.json" would be used for level smallgrid.
  • The "busdriver" object should contain the default route that the should be played, hence modify the "routeID" and "variance" accordingly.
If the a json file for the bus scenario exists in the bus foler, skip this step.

  1. Create a simple text file in your buslines folder, with content similar to the template shown below.

Save and name it levelName.buslines.json. Ensure that the .json filename is unique.

{
    "version": 1,
    "routes":[
        {"routeID":"1",
            "variance":"a",
            "direction":"Rexoni Diner",
            "routeColor": "#3b9c00",
            "vehicle" : {
                "model": "citybus",
                "config": "base"
            },
            "tasklist":[
                "tmpl_bs_07",
                "tmpl_bs_13",
                "tmpl_bs_02",
                "tmpl_bs_23",
                "tmpl_bs_26",
            ],
            "spawnLocation": {
                "pos": {"x": -613.572,"y": 199.223,"z": 113.173},
                "rotAngAxisF": {"x": 0,"y": 0,"z": 1,"w": 224.173}
            },
            "requiredWaypoints":{
                "wcu_bs_29":{
                    "wp":["wcu_cp_agave"],
                    "failmsg":"You got too far-off the route" },
                "wcu_bs_27":{
                    "wp":["wcu_cp_hwy"],
                    "failmsg":"You got too far-off the route" }
            },
            "navhelp":{
                "wcu_bs_13":["wpTown_16","Bridge36_3","Bridge36_1"],
                "wcu_bs_26":["bs_raceTrack_1","Bridge4_B1","Bridge4_A1","Bridge4_A2","countryside_road_1","countryside_road_2"],
                "wcu_bs_29":["Junction_mountain_A","Bridge1_B"],
                "wcu_bs_27":["countryside_road_3","Bridge2_A1","Bridge2_A2","Bridge2_A3","Bridge17_A","Bridge17_B","Bridge17_E"],
                "wcu_bs_28":["countryside_road_4"],
            },
            "previews":[
                "01_RexDiner.png"
            ]
        },
        {"routeID":"2",
            "variance":"a",
            "direction":"Khaki Bay",
            "routeColor": "#fff200",
            "tasklist":[
                "tmpl_bs_04",
                "tmpl_bs_01",
                "tmpl_bs_05_b",
                "tmpl_bs_14_b",
                "tmpl_bs_19_b",
                "tmpl_bs_25_b",
                "tmpl_bs_24_b",
                "tmpl_bs_27_b",
                "tmpl_bs_21",
                "tmpl_bs_17"
            ],
            "vehicle" : {
                "model": "citybus",
                "config": "base"
            },
            "spawnLocation": {
                "pos": {"x": -337.572,"y": 605.564,"z": 75.0979},
                "rotAngAxisF": {"x": 0,"y": 0,"z": 1,"w": 135.337}
            },
            "requiredWaypoints":{
                "wcu_bs_27":{
                    "wp":["wcu_cp_hrzn"],
                    "failmsg":"You got too far-off the route" }
            },
            "navhelp":{
                "wcu_bs_21":["Bridge17b_A"],
                "wcu_bs_17":["tennis_1","tennis_2"],
            },
            "previews":[
                "02_KhahkiBay.png"
            ]
        },
    ]
}

JSON Guidelines

A few guidelines to creating your levelName.buslines.json document may come in handy at this point.

The .json file is made up of a json object that contains 2 variables: The “version” is a number that represents the version of buslines file. The “routes” is an array of json objects, with each object defining a bus route. Now each bus route object contains:

  • routesID must be of string type, although it is actually a number e.g. "routeID":"101"
  • direction ideally every route has two directions: one from A to B and another from B to A. This variable is used for display purposes. As a result, it is good to use naming conventions that can be easily recognized.
  • variance is a string that describes a specific variant of the route. This is needed and used internally when a route ID has more than one variant.
  • routeColor is a string representing route Color in html hexadecimal
  • vehicle is the vehicle to use. Keep model as citybus and config as base
  • tasklist is a json array of strings (no space in between), which represents the triggers for your bus stops.
  • requiredWaypoints is an optional json object that indicates compulsory points the vehicle must go through, and failure message if the vehicle does not go through them. Each element of the required way point object is also an object that contains 2 variables: an array containing the string-id of the way point that must be passed, and failure message that is displayed when the way point is not passed.
  • spawnLocation is a json object containing 2 objects: "pos" and rotAngAxisF, which represent the starting position and orientation of the vehicle. The rotation object could be either of two types:
    • rot: a quaternion representation of rotation (given by LUA)
    • rotAngAxisF: “angle and axis” representation of rotation used in the editor. The x, y, z denote the axis of rotation and w , the angle in degrees. This type is recommended because it's easy to use.
  • navhelp which is an optional json object that contains arrays named after the ids of the stops that require navigation help. These arrays contain waypoints (strings), through which the navigation arrow would pass.
  1. Rename and modify the variables and values in the levelName.buslines.json document, as desired and as directed in the previous step.

  2. Save the file.

Spawnpoints

  1. Load the game and go to Play > Bus Routes > Select Map. Then, select the map to be modified (where the new folders were created) and choose a direction (e.g. “Rexoni Diner”). Don’t worry if the vehicle spawns mid-air or underground, the next steps are going to adjust the spawnpoint.

  2. Press Shift+C to toggle Free Camera. Navigate through the map (using navigation keys W A S D) till you choose and reach the desired location for starting the trip. Try to move the view as close to the ground as possible.

  3. Press F11 to open the World Editor.

  4. Click the Camera tab, and click Place Player at Camera.

  1. Click on the vehicle to display the vehicle marker. If the marker is not showing, go to the Scene Tree editor’s tool (if not there, add it from the Window tab).

    Scroll down to the end to the ScenarioObjectsGroup folder. In this folder, select the scenario\_player0, and this should select your vehicle and display its marker.

  1. You can set your position and rotation by typing the values directly in the Transform tab of the Inspector editor’s tool or by respectively using the Translate and Rotate editor tools.

  1. Once you are satisfied with your desired starting position and orientation, copy these values from the Inspector’s transform tab to spawnLocation in your levelName.buslines.json file.

  2. Save the file.

Bus stops

  1. In the Scene Tree click the ScenarioObjectsGroup folder and then the New folder icon in the top-left of the Scene Tree window.

Name the new folder busstops and open the folder.

  1. In the game, press Shift+C to toggle Free Camera and return to the vehicle’s camera. Then navigate through the map till you reach the desired location for your bus stop.

  2. In the World Editor Toolbar:

  • Click the Add Object button
  • Click the BeamNG icon in the toolbar that appears below the main one
  • Click the LUA Trigger icon
  • Click anywhere in the 3D view

This creates a LUA trigger where you clicked in the 3D view, and the object will also appear in the Scene Tree list.

LUA Triggers are visible only if selected, unless the Triggers option is enabled in the Visualization menu (Access this menu from the tab Window button

  1. Modify the position, rotation and scale of the box trigger as described in step 11.

    In the scale of the trigger, make the “x” value accommodate the width of the vehicle and make the “y” value accommodate the length of the vehicle.

Since this trigger will be activated when the trigger box contains the vehicle, give the box dimensions, such that it is big enough to contain the vehicle. Also, it is advisable to let the bounding box, go a little below ground level.

  1. When the desired size and location is achieved, go to the Inspector window of the World Editor. Copy the trigger identifier from your tasklist in the levelName.buslines.json file (e.g tmpl_bs_07) and paste it by the name option in the Inspector panel.

Remember that this identifier must be a single string with no space within it, as indicated in step 3. It is recommended to keep the name short.

  1. With the trigger selected, go in the Inspector change the following in the Trigger section:
    • TriggerType > Box
    • TriggerMode > Contains
    • TriggerTestType > Bounding box
    • TickPeriod > 1000

  1. When this is done, scroll down the Inspector window to the Dynamic Fields section

  1. Insert type and click Add, then insert busstop

  1. Add another entity to the Dynamic Fields named stopName and insert the actual name of the bus stop, which would be displayed in the game (e.g. Fleet Street)

  2. Repeat steps 15 to 22 for each bus stop you want to create.

  3. Saving requires additional details
Last modified: March 24, 2021

Any further questions?

Join our discord
Our documentation is currently incomplete and undergoing active development. If you have any questions or feedback, please visit this forum thread.