Skip to main content
Version: 0.4.0 Nightly

Trolleybuses

neoOMSI runs trolleybuses made for the TrolleyGrid plugin (Ackerman Projects, OMSI 2.3.004) natively: the poles run on the map's overhead wires, the bus gets traction power only while both are on, and they come off when driven badly. The plugin's library (TrolleyWirePlugin.dll) is never loaded; its settings and its list of trolleybuses are read from the files it installs in plugins\.

This page says what neoOMSI looks for, so that a bus or a map can be built or converted for it. Everything here also works without the plugin installed: missing files fall back to the values TrolleyGrid 1.0 Open Beta ships with.

Settings files​

FilePurpose
plugins\TrolleyWirePlugin.cfgWire, pole, physics, spark and sound settings ([global], [physics], [sparks], [sound])
plugins\TrolleyWireVehicles.iniOne [vehicle:<name>] section per trolleybus: where its poles are

Both are plain key=value files. The first content root that has a file wins. A missing key keeps its default.

The vehicle​

What makes a bus a trolleybus​

A vehicle is a trolleybus when its scripts declare the variable shtanga_wire_present (in any varlist of its [varnamelist]). Nothing else is checked; a bus without it is left alone.

Where the poles are​

Pole geometry comes from TrolleyWireVehicles.ini. An entry belongs to a bus when its bus_file matches the end of the bus's .bus path (case does not matter; a bare file name matches in any folder):

[vehicle:my_trolleybus]
enabled=1
bus_file=Vehicles\My Trolleybus\my_trolleybus.bus
; pole bases (model frame: x right, y forward, z up)
pole_base_left_x=-0.256101
pole_base_right_x=0.256101
pole_base_forward=0.226053
pole_base_height=3.116170
; the shoe's contact point with the pole at rest (hooked down)
contact_left_x=-0.261714
contact_right_x=0.253469
contact_forward=-5.940704
contact_height=5.071949
  • The distance from base to contact point is the pole's length.
  • pole_carrier_bus_file=<file>.bus puts the poles on a coupled part (an articulated trolleybus's rear section) instead of the bus itself.
  • Optional: yaw_factor_left/right, pitch_factor, shoe_factor_left/right (scale the output angles), shoe_visual_drop_m / ai_shoe_visual_drop_m (lower the drawn shoe), contact_reach_release_error_m, contact_reach_release_time.
  • Without an entry, or for keys it leaves out, the [global] values of TrolleyWirePlugin.cfg are used (pole_base_*, contact_rest_*: the ZiU-682G).

Variables​

neoOMSI writes these once a frame, before the scripts run:

VariableMeaning
shtanga_lev_pitch, shtanga_prav_pitchPole raised from its rest pose (degrees)
shtanga_lev_rot, shtanga_prav_rotPole swung about the vertical (degrees, positive: tip to the left)
shtanga_lev_shoe_rot, shtanga_prav_shoe_rotShoe turned about its pivot to lie along the wire (degrees)
shtanga_lev_shoe_pos_x/y/z, shtanga_prav_shoe_pos_x/y/zContact point (model frame)
shtanga_wire_present1 while both poles are on the wire (power)
shtanga_contact_force_left/rightContact force (N)
shtanga_dewired_left/right1 from coming off until the pole is back on the wire
shtanga_engine_trip1 while a pole is off (cut the traction)
shtanga_manual_command_left/right0 while the pole is hooked down, else 1
shtanga_spark_left/right1 while the shoe sparks (for a [light_enh_2])
shtanga_speed_limit_active, shtanga_complex_overspeedA shoe is at a switch or crossing / too fast there

And reads these, set by the scripts:

VariableMeaning
shtanga_switch_pedalAt a switch: 0.05 or more takes the leftmost branch, less the rightmost
shtanga_manual_grab_left/rightGoing to 1 (a click on the pole) raises a hooked pole, or pulls down a raised one
cp_zummerThe cab's buzzer sounds while a pole is off only when this is 1 (or missing)
shtanga_wire_reset1 puts the poles on the nearest wire again (neoOMSI writes 0 back)

For the AI, write shtanga_switch_pedal from AI_Blinker_L/R (left blinker: 1). An AI bus's poles follow the wire and never come off: where its wire ends they go down quietly and look for a wire again every lost_reset_frames frames. Only the pole angles and the sparks are written for it.

The model​

Animate each pole with two [newanim] blocks about its base (origin_trans at the pole base): first origin_rot_x 90 with anim_rot on shtanga_lev_pitch, then origin_rot_y 90 on shtanga_lev_rot. The shoe takes shtanga_lev_shoe_rot about its own pivot first (origin_rot_y 90), then the pole's two. Model the pole in its hooked-down pose. Show the moving pole with [visible] cp_SHTANGALEV 1 and a hooked one with 0; the scripts copy shtanga_manual_command_left into cp_SHTANGALEV for the player's bus. The TrolleyGrid ZiU-682G files are a complete example.

The map​

Wires​

A spline carries wires when its file name contains one of spline_keywords ([global] of TrolleyWirePlugin.cfg, comma separated, case does not matter). Default: Troll_lines_01.sli, Troll_lines_02.sli, Troll_lines, Troll_line, Trolleybus, trolley.

Where the two wires hang is read from the spline's .sli profiles: the left wire is the middle of all profile points left of the spline (x < 0), the right wire the middle of those right of it, and the height is the lowest profile point (the wires' underside). Without points on a side, wire_x_left, wire_x_right and wire_height are used (-0.255, 0.255, 5.8 m). A mirrored spline is flipped.

How spans join​

  • Wire ends closer than 0.3 m that point against each other are one wire.
  • An end with no such partner is joined across a gap to every wire that starts up to exact_reacquire_max_move (3.75 m) ahead, no more than 40° off its way and running on within 50° of it. Two such continuations make a switch; the shoes take the left or the right one by the pedal. This is how Tver's switches are laid: the wires stop about a metre before the switch object and go on about two metres after it.
  • Wires that cross each other without a break are not joined; each shoe stays on its own.

Keep the wires of one direction as one chain of splines, and leave a gap of under 3.75 m at switches. Spans running side by side (the other direction) are never joined.

Switch and crossing objects​

Objects only mark where a switch or crossing is: there the speed limit (complex_speed_limit_kmh, 25 km/h, within complex_contact_radius of the object) applies and the switch and crossing sounds play. The geometry comes from the splines alone.

An object is recognised by its file name ([global], comma separated, case does not matter; neoOMSI's own keys, TrolleyGrid itself only knows Tver's objects):

KeyDefaultKind
cross_keywordsTroll_strelka_OnKrest, Troll_strelka_TwoKrest, Trolley_crossCrossing (checked first)
switch_keywordsTroll_strelka, Trolley_switchSwitch

A map with its own objects can add its names, for example:

[global]
switch_keywords=Troll_strelka, Trolley_switch, Fahrleitung_Weiche
cross_keywords=Troll_strelka_OnKrest, Troll_strelka_TwoKrest, Trolley_cross, Fahrleitung_Kreuzung

Sounds​

Played from Sounds\AckerTroll\ of the OMSI folder as TrolleyGrid installs them: switch_left_sep.wav, switch_left_merg.wav, switch_right_sep.wav, switch_right_merg.wav and cross.wav (with _int variants inside the bus), iskra.WAV (spark) and wheel_sliding.wav (the shoes gliding along). The buzzer is Sound\zummer_115.wav of the bus.

Not the plugin's behaviour​

The settings' values are TrolleyGrid's, but how neoOMSI combines them (the contact force, the sideways force, a pole raised beside the wire, the catcher) is its own model and has not yet been compared with the plugin in OMSI 2.3.004. OMSI_DEBUG_TROLLEY=1 logs both poles of the player's bus every frame.