OpenLoco v25.04 is out! This month, we’ve made a bunch of progress on the reimplementation of the company AI, as well as a few exciting new features. Let’s dig into the details in this dev log. For a summary of changes please find the changelog on GitHub.

A faster way to build tracks

Locomotion’s UI represented quite a departure from the Transport Tycoon games that preceded it. This is perhaps most notable in the way tracks and roads are built in the game, which clearly inherits from the RollerCoaster Tycoon games Locomotion shares its engine with. While the resulting construction window provides a quick overview of available track pieces, it doesn’t necessarily make for the fastest way to construct those tracks.

In earlier versions of OpenLoco, we tried to mitigate this somewhat by allowing players to hold down the construction button for repeated building. This still only sped things up a little, though. This month, we have a more exciting change: you can now drag the construction marker to fill an area with the selected track pieces (#3073)! This feature was inspired by how track building works in OpenTTD. Here’s quick video of the new tool in action:

To achieve this, the selection tool is now activated when the mouse button is released (ToolUp event) instead of immediately when the button is pressed (ToolDown event). Now, when ToolDown is activated, the initial tile position is stored. When the player starts moving the mouse (ToolDrag event), the current tile position is stored. If the two positions aren’t identical, the new ‘dragging’ mode is activated. You’ll now just see a map selection grid, showing what tiles will be filled with track pieces. If you let go, the new pieces will be built immediately.

Conversely, if the two positions are identical, then the game takes the vanilla code path: you’ll see a ghost track piece, and clicking will build that piece, and activate ‘interactive’ mode, just like it always did.

NB: this currently only extends to the track/road and station construction tabs. The signal and overhead tabs have not been adapted. We’re not sure how best to implement them yet, but they will likely be adapted in the future as well.

More work on the company AI

This month, Duncan continued his mission to fully reimplement the company AI functions. First, he tackled how the AI works out what vehicle types to use, and building up a train from the available vehicle types (#3056). Applying the AI’s play style restrictions, as mentioned in the previous dev log, was also finalised #3054.

Duncan also uncovered how the AI places stations, and decides how big to make them (#3066). Perhaps more interestingly, he uncovered how the AI turns its ‘planned’ tracks and roads into ‘real’ tracks and roads #3070. The AI actually places invisible track/road elements as it plans, which is what triggers the error popups if you try to cross it.

Finally, for this month, Duncan reimplemented how track/road elements are removed for AI companies, e.g. in the event of them going bankrupt (#3078). Nice work, Duncan!

View vehicles stopping at station

Way back in v21.07, we added the ability to filter the vehicle list by station or cargo (#997). While this has worked well for filtering by cargo type, filtering by station has always been a bit cumbersome. As it’s possible to have more stations in-game than the dropdown menus support viewing, you basically needed to have the desired station window open along with the vehicle list for it to allow filtering. Surely we could do better?

In the mean time, we have fully implemented the paint functions, including the ones having to do with drawing the actual vehicles. This meant we could finally implement a much more flexible solution! Enter #3081.

Station windows now have a tab for each of the vehicle types that are explicitly set to stop at that particular station. For example, a station can have trains and trams stop there, or boats and aircraft. Effectively, each station window now harbours a mini vehicle list of its own! We hope you’ll like the changes.

Viewport invalidation fixes

A minor, but longstanding bug in OpenLoco was that parts of the UI would not get redrawn under certain circumstances, most notably menus and dropdowns when panning the viewport (#1232). The cause for this was finally identified and fixed in #3067.

Speaking of viewports, the drawing logic was also reworked a bit in #3061 and #3062. Not only do we match the original intent better, it also should no longer lead to crashes on very large screens. Nice work!

Object pointer rework

Some of the in-game objects store pointers to loaded data internally. Like the game itself, these are all 32-bit addresses, reserving 4 bytes per address. To prepare for us switching to 64-bit address space, we decided to rework these to use relative offsets instead of absolute addresses. These will work for both 32-bit and 64-bit builds, thus solving the problem. While 64-bit builds are still a way off, pending full reimplementation, at least the industry objects (#3037) and airport objects (#3071) are now ready for them.

More work on vehicle functions

New contributor @fionasoft worked on reimplementing a vehicle function that was still relying on vanilla code: VehicleHead::landCrashedUpdate (#3060). This uncovered a few fun assumptions around vehicle parts exploding after a crash. Turns out the vehicle tile coordinates are being used to pack extra information in the event of a crash! We now get why that happens, but it took a while to wrap our heads around it!

Updated: