Skip to content

[Plugin] Fix regression from #24142 breaking ScTrackIterator on specific track pieces #24446

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 25, 2025

Conversation

Basssiiie
Copy link
Member

@Basssiiie Basssiiie commented May 19, 2025

Hi all,

This is a small fix for a mistake I made a while back in #24142. I said my change did affect ScTrackIterator, and while I did test it, it was not thoroughly enough and it broke the iterator's previous() and next() methods on very specific track pieces. 😫 On top of that, I misinterpreted the purpose of GetTrackSegmentOrigin(), where I thought it was meant to return the position of sequence 0 of a track piece, but it's actual purpose is just the track segments origin which CAN actually be somewhere else than at the position of sequence 0 (hence that it broke the ScTrackIterator).

With this PR I'm reverting that change, and putting a proper fix in just moveToTrack() similar to ones that were already applied in the various ScTrackIterator methods and properties.

I have also written an additional test script to compare how the ScTrackIterator operates prior to my fix vs. develop vs. this PR, and can confirm this PR outputs exactly the same data and behaviour as the game did prior to #24142. (And develop outputs incorrect results.) Especially "Log all tracks" button is useful to dump an entire ride's track and compare the json across different OpenRCT2 versions with a compare tool.

Click here for that test script.
/// <reference path="../bin/openrct2.d.ts" />
// @ts-check

function toTile(value, size)
{
	return Math.floor(value/(size || 32));
}

function xyz(coords)
{
	if (!coords) return "null";
	return toTile(coords.x)+", "+toTile(coords.y)+", "+toTile(coords.z, 8)+", dir: "+coords.direction;
}

function find(array, func)
{
	for (var i = 0; i < array.length; i ++)
	{
		var elem = array[i];
		if (func(elem))
		{
			return i
		}
	}
	return -1
}

registerPlugin({
	name: "Test track iterator",
	version: "1",
	authors: ['Basssiiie'],
	targetApiVersion: 82,
	type: "local",
	licence: "MIT",
	main() {
		ui.registerMenuItem("Test track iterator", function() {
			ui.activateTool({
				id: 'test-track-iterator',
				cursor: 'cross_hair',
				filter: ["ride"],
				onDown: function(args) {

					var coords = args.mapCoords;
					var tileElementIdx = args.tileElementIndex;
					if (!coords || tileElementIdx === undefined) return;
					var x = Math.floor(coords.x / 32);
					var y = Math.floor(coords.y / 32)
					var tile = map.getTile(x, y);
					var track = tile.getElement(tileElementIdx);
					if (track.type !== "track") return;

					ui.tool.cancel();
					console.log("Track at "+x+", "+y+" selected (idx: "+tileElementIdx+")");

					var iterator = map.getTrackIterator(coords, tileElementIdx);
					ui.tileSelection.tiles = [iterator.position];
					var window = ui.openWindow({
						classification: "test-track-iterator",
						title: "Test track iterator",
						width: 200,
						height: 265,
						onUpdate: function()
						{
							var position = iterator.position;
							var segment = iterator.segment;
							window.findWidget("label").text =
								"Current: "+xyz(position)
								+"\nNext: "+xyz(iterator.nextPosition)
								+"\nPrevious: "+xyz(iterator.previousPosition)
								+"\nTrack type: "+segment.type
								+"\nTrack desc.: "+segment.description
								+"\nElements: "+segment.elements.length
								+"\nSubpositions: "+segment.getSubpositionLength(0, position.direction);
							window.findWidget("viewport").viewport.moveTo(position)
						},
						widgets: [
							{
								name: "viewport",
								type: "viewport",
								x: 10,
								y: 25,
								width: 180,
								height: 100,
							},
							{
								name: "label",
								type: "label",
								x: 10,
								y: 135,
								width: 180,
								height: 15,
							},
							{
								name: "previous",
								type: "button",
								x: 10,
								y: 215,
								width: 85,
								height: 15,
								text: "Previous",
								onClick: function() {
									iterator.previous();
									ui.tileSelection.tiles = [iterator.position];
								}
							},
							{
								name: "next",
								type: "button",
								x: 105,
								y: 215,
								width: 85,
								height: 15,
								text: "Next",
								onClick: function() {
									iterator.next();
									ui.tileSelection.tiles = [iterator.position];
								}
							},
							{
								name: "next",
								type: "button",
								x: 10,
								y: 240,
								width: 180,
								height: 15,
								text: "Log all tracks",
								onClick: function() {
									var current = iterator.position
									var x = Math.floor(current.x / 32);
									var y = Math.floor(current.y / 32)
									var idx = find(map.getTile(x, y).elements, function(elem)
									{
										return elem.type === "track" && elem.baseZ === current.z && elem.direction === current.direction;
									});
									if (idx === -1) return;
									var iterator2 = map.getTrackIterator(current, idx);
									var pieces = [];

									do
									{
										var piece = xyz(iterator2.position)
										if (find(pieces, function(e) { return e.pos === piece }) != -1) break;
										pieces.push({
											idx: pieces.length,
											type: TrackElemType[iterator2.segment.type],
											pos: piece,
											next: xyz(iterator2.nextPosition),
											previous: xyz(iterator2.previousPosition)
										})
									}
									while (iterator2.next())

									iterator2 = map.getTrackIterator(current, idx);
									var offset = 0;
									while (iterator2.previous())
									{
										var piece = xyz(iterator2.position)
										if (find(pieces, function(e) { return e.pos === piece }) != -1) break;
										pieces.unshift({
											idx: --offset,
											type: TrackElemType[iterator2.segment.type],
											pos: piece,
											next: xyz(iterator2.nextPosition),
											previous: xyz(iterator2.previousPosition)
										})
									}
									console.log(JSON.stringify(pieces));
								}
							},
						]
					})
				}
			})
		})
	}
});

var TrackElemType =
[
	"Flat",
	"EndStation",
	"BeginStation",
	"MiddleStation",
	"Up25",
	"Up60",
	"FlatToUp25",
	"Up25ToUp60",
	"Up60ToUp25",
	"Up25ToFlat",
	"Down25",
	"Down60",
	"FlatToDown25",
	"Down25ToDown60",
	"Down60ToDown25",
	"Down25ToFlat",
	"LeftQuarterTurn5Tiles",
	"RightQuarterTurn5Tiles",
	"FlatToLeftBank",
	"FlatToRightBank",
	"LeftBankToFlat",
	"RightBankToFlat",
	"BankedLeftQuarterTurn5Tiles",
	"BankedRightQuarterTurn5Tiles",
	"LeftBankToUp25",
	"RightBankToUp25",
	"Up25ToLeftBank",
	"Up25ToRightBank",
	"LeftBankToDown25",
	"RightBankToDown25",
	"Down25ToLeftBank",
	"Down25ToRightBank",
	"LeftBank",
	"RightBank",
	"LeftQuarterTurn5TilesUp25",
	"RightQuarterTurn5TilesUp25",
	"LeftQuarterTurn5TilesDown25",
	"RightQuarterTurn5TilesDown25",
	"SBendLeft",
	"SBendRight",
	"LeftVerticalLoop",
	"RightVerticalLoop",
	"LeftQuarterTurn3Tiles",
	"RightQuarterTurn3Tiles",
	"LeftBankedQuarterTurn3Tiles",
	"RightBankedQuarterTurn3Tiles",
	"LeftQuarterTurn3TilesUp25",
	"RightQuarterTurn3TilesUp25",
	"LeftQuarterTurn3TilesDown25",
	"RightQuarterTurn3TilesDown25",
	"LeftQuarterTurn1Tile",
	"RightQuarterTurn1Tile",
	"LeftTwistDownToUp",
	"RightTwistDownToUp",
	"LeftTwistUpToDown",
	"RightTwistUpToDown",
	"HalfLoopUp",
	"HalfLoopDown",
	"LeftCorkscrewUp",
	"RightCorkscrewUp",
	"LeftCorkscrewDown",
	"RightCorkscrewDown",
	"FlatToUp60",
	"Up60ToFlat",
	"FlatToDown60",
	"Down60ToFlat",
	"TowerBase",
	"TowerSection",
	"FlatCovered",
	"Up25Covered",
	"Up60Covered",
	"FlatToUp25Covered",
	"Up25ToUp60Covered",
	"Up60ToUp25Covered",
	"Up25ToFlatCovered",
	"Down25Covered",
	"Down60Covered",
	"FlatToDown25Covered",
	"Down25ToDown60Covered",
	"Down60ToDown25Covered",
	"Down25ToFlatCovered",
	"LeftQuarterTurn5TilesCovered",
	"RightQuarterTurn5TilesCovered",
	"SBendLeftCovered",
	"SBendRightCovered",
	"LeftQuarterTurn3TilesCovered",
	"RightQuarterTurn3TilesCovered",
	"LeftHalfBankedHelixUpSmall",
	"RightHalfBankedHelixUpSmall",
	"LeftHalfBankedHelixDownSmall",
	"RightHalfBankedHelixDownSmall",
	"LeftHalfBankedHelixUpLarge",
	"RightHalfBankedHelixUpLarge",
	"LeftHalfBankedHelixDownLarge",
	"RightHalfBankedHelixDownLarge",
	"LeftQuarterTurn1TileUp60",
	"RightQuarterTurn1TileUp60",
	"LeftQuarterTurn1TileDown60",
	"RightQuarterTurn1TileDown60",
	"Brakes",
	"Booster",
	"Maze",
	"LeftQuarterBankedHelixLargeUp",
	"RightQuarterBankedHelixLargeUp",
	"LeftQuarterBankedHelixLargeDown",
	"RightQuarterBankedHelixLargeDown",
	"LeftQuarterHelixLargeUp",
	"RightQuarterHelixLargeUp",
	"LeftQuarterHelixLargeDown",
	"RightQuarterHelixLargeDown",
	"Up25LeftBanked",
	"Up25RightBanked",
	"Waterfall",
	"Rapids",
	"OnRidePhoto",
	"Down25LeftBanked",
	"Down25RightBanked",
	"Watersplash",
	"FlatToUp60LongBase",
	"Up60ToFlatLongBase",
	"Whirlpool",
	"Down60ToFlatLongBase",
	"FlatToDown60LongBase",
	"CableLiftHill",
	"ReverseFreefallSlope",
	"ReverseFreefallVertical",
	"Up90",
	"Down90",
	"Up60ToUp90",
	"Down90ToDown60",
	"Up90ToUp60",
	"Down60ToDown90",
	"BrakeForDrop",
	"LeftEighthToDiag",
	"RightEighthToDiag",
	"LeftEighthToOrthogonal",
	"RightEighthToOrthogonal",
	"LeftEighthBankToDiag",
	"RightEighthBankToDiag",
	"LeftEighthBankToOrthogonal",
	"RightEighthBankToOrthogonal",
	"DiagFlat",
	"DiagUp25",
	"DiagUp60",
	"DiagFlatToUp25",
	"DiagUp25ToUp60",
	"DiagUp60ToUp25",
	"DiagUp25ToFlat",
	"DiagDown25",
	"DiagDown60",
	"DiagFlatToDown25",
	"DiagDown25ToDown60",
	"DiagDown60ToDown25",
	"DiagDown25ToFlat",
	"DiagFlatToUp60",
	"DiagUp60ToFlat",
	"DiagFlatToDown60",
	"DiagDown60ToFlat",
	"DiagFlatToLeftBank",
	"DiagFlatToRightBank",
	"DiagLeftBankToFlat",
	"DiagRightBankToFlat",
	"DiagLeftBankToUp25",
	"DiagRightBankToUp25",
	"DiagUp25ToLeftBank",
	"DiagUp25ToRightBank",
	"DiagLeftBankToDown25",
	"DiagRightBankToDown25",
	"DiagDown25ToLeftBank",
	"DiagDown25ToRightBank",
	"DiagLeftBank",
	"DiagRightBank",
	"LogFlumeReverser",
	"SpinningTunnel",
	"LeftBarrelRollUpToDown",
	"RightBarrelRollUpToDown",
	"LeftBarrelRollDownToUp",
	"RightBarrelRollDownToUp",
	"LeftBankToLeftQuarterTurn3TilesUp25",
	"RightBankToRightQuarterTurn3TilesUp25",
	"LeftQuarterTurn3TilesDown25ToLeftBank",
	"RightQuarterTurn3TilesDown25ToRightBank",
	"PoweredLift",
	"LeftLargeHalfLoopUp",
	"RightLargeHalfLoopUp",
	"LeftLargeHalfLoopDown",
	"RightLargeHalfLoopDown",
	"LeftFlyerTwistUp",
	"RightFlyerTwistUp",
	"LeftFlyerTwistDown",
	"RightFlyerTwistDown",
	"FlyerHalfLoopUninvertedUp",
	"FlyerHalfLoopInvertedDown",
	"LeftFlyerCorkscrewUp",
	"RightFlyerCorkscrewUp",
	"LeftFlyerCorkscrewDown",
	"RightFlyerCorkscrewDown",
	"HeartLineTransferUp",
	"HeartLineTransferDown",
	"LeftHeartLineRoll",
	"RightHeartLineRoll",
	"MinigolfHoleA",
	"MinigolfHoleB",
	"MinigolfHoleC",
	"MinigolfHoleD",
	"MinigolfHoleE",
	"MultiDimInvertedFlatToDown90QuarterLoop",
	"Up90ToInvertedFlatQuarterLoop",
	"InvertedFlatToDown90QuarterLoop",
	"LeftCurvedLiftHill",
	"RightCurvedLiftHill",
	"LeftReverser",
	"RightReverser",
	"AirThrustTopCap",
	"AirThrustVerticalDown",
	"AirThrustVerticalDownToLevel",
	"BlockBrakes",
	"LeftBankedQuarterTurn3TileUp25",
	"RightBankedQuarterTurn3TileUp25",
	"LeftBankedQuarterTurn3TileDown25",
	"RightBankedQuarterTurn3TileDown25",
	"LeftBankedQuarterTurn5TileUp25",
	"RightBankedQuarterTurn5TileUp25",
	"LeftBankedQuarterTurn5TileDown25",
	"RightBankedQuarterTurn5TileDown25",
	"Up25ToLeftBankedUp25",
	"Up25ToRightBankedUp25",
	"LeftBankedUp25ToUp25",
	"RightBankedUp25ToUp25",
	"Down25ToLeftBankedDown25",
	"Down25ToRightBankedDown25",
	"LeftBankedDown25ToDown25",
	"RightBankedDown25ToDown25",
	"LeftBankedFlatToLeftBankedUp25",
	"RightBankedFlatToRightBankedUp25",
	"LeftBankedUp25ToLeftBankedFlat",
	"RightBankedUp25ToRightBankedFlat",
	"LeftBankedFlatToLeftBankedDown25",
	"RightBankedFlatToRightBankedDown25",
	"LeftBankedDown25ToLeftBankedFlat",
	"RightBankedDown25ToRightBankedFlat",
	"FlatToLeftBankedUp25",
	"FlatToRightBankedUp25",
	"LeftBankedUp25ToFlat",
	"RightBankedUp25ToFlat",
	"FlatToLeftBankedDown25",
	"FlatToRightBankedDown25",
	"LeftBankedDown25ToFlat",
	"RightBankedDown25ToFlat",
	"LeftQuarterTurn1TileUp90",
	"RightQuarterTurn1TileUp90",
	"LeftQuarterTurn1TileDown90",
	"RightQuarterTurn1TileDown90",
	"MultiDimUp90ToInvertedFlatQuarterLoop",
	"MultiDimFlatToDown90QuarterLoop",
	"MultiDimInvertedUp90ToFlatQuarterLoop",
	"RotationControlToggle",
	"FlatTrack1x4A",
	"FlatTrack2x2",
	"FlatTrack4x4",
	"FlatTrack2x4",
	"FlatTrack1x5",
	"FlatTrack1x1A",
	"FlatTrack1x4B",
	"FlatTrack1x1B",
	"FlatTrack1x4C",
	"FlatTrack3x3",
	"LeftLargeCorkscrewUp",
	"RightLargeCorkscrewUp",
	"LeftLargeCorkscrewDown",
	"RightLargeCorkscrewDown",
	"LeftMediumHalfLoopUp",
	"RightMediumHalfLoopUp",
	"LeftMediumHalfLoopDown",
	"RightMediumHalfLoopDown",
	"LeftZeroGRollUp",
	"RightZeroGRollUp",
	"LeftZeroGRollDown",
	"RightZeroGRollDown",
	"LeftLargeZeroGRollUp",
	"RightLargeZeroGRollUp",
	"LeftLargeZeroGRollDown",
	"RightLargeZeroGRollDown",
	"LeftFlyerLargeHalfLoopUninvertedUp",
	"RightFlyerLargeHalfLoopUninvertedUp",
	"LeftFlyerLargeHalfLoopInvertedDown",
	"RightFlyerLargeHalfLoopInvertedDown",
	"LeftFlyerLargeHalfLoopInvertedUp",
	"RightFlyerLargeHalfLoopInvertedUp",
	"LeftFlyerLargeHalfLoopUninvertedDown",
	"RightFlyerLargeHalfLoopUninvertedDown",
	"FlyerHalfLoopInvertedUp",
	"FlyerHalfLoopUninvertedDown",
	"LeftEighthToDiagUp25",
	"RightEighthToDiagUp25",
	"LeftEighthToDiagDown25",
	"RightEighthToDiagDown25",
	"LeftEighthToOrthogonalUp25",
	"RightEighthToOrthogonalUp25",
	"LeftEighthToOrthogonalDown25",
	"RightEighthToOrthogonalDown25",
	"DiagUp25ToLeftBankedUp25",
	"DiagUp25ToRightBankedUp25",
	"DiagLeftBankedUp25ToUp25",
	"DiagRightBankedUp25ToUp25",
	"DiagDown25ToLeftBankedDown25",
	"DiagDown25ToRightBankedDown25",
	"DiagLeftBankedDown25ToDown25",
	"DiagRightBankedDown25ToDown25",
	"DiagLeftBankedFlatToLeftBankedUp25",
	"DiagRightBankedFlatToRightBankedUp25",
	"DiagLeftBankedUp25ToLeftBankedFlat",
	"DiagRightBankedUp25ToRightBankedFlat",
	"DiagLeftBankedFlatToLeftBankedDown25",
	"DiagRightBankedFlatToRightBankedDown25",
	"DiagLeftBankedDown25ToLeftBankedFlat",
	"DiagRightBankedDown25ToRightBankedFlat",
	"DiagFlatToLeftBankedUp25",
	"DiagFlatToRightBankedUp25",
	"DiagLeftBankedUp25ToFlat",
	"DiagRightBankedUp25ToFlat",
	"DiagFlatToLeftBankedDown25",
	"DiagFlatToRightBankedDown25",
	"DiagLeftBankedDown25ToFlat",
	"DiagRightBankedDown25ToFlat",
	"DiagUp25LeftBanked",
	"DiagUp25RightBanked",
	"DiagDown25LeftBanked",
	"DiagDown25RightBanked",
	"LeftEighthBankToDiagUp25",
	"RightEighthBankToDiagUp25",
	"LeftEighthBankToDiagDown25",
	"RightEighthBankToDiagDown25",
	"LeftEighthBankToOrthogonalUp25",
	"RightEighthBankToOrthogonalUp25",
	"LeftEighthBankToOrthogonalDown25",
	"RightEighthBankToOrthogonalDown25",
	"DiagBrakes",
	"DiagBlockBrakes",
	"Down25Brakes",
	"DiagBooster",
	"DiagFlatToUp60LongBase",
	"DiagUp60ToFlatLongBase",
	"DiagFlatToDown60LongBase",
	"DiagDown60ToFlatLongBase",
	"LeftEighthDiveLoopUpToOrthogonal",
	"RightEighthDiveLoopUpToOrthogonal",
	"LeftEighthDiveLoopDownToDiag",
	"RightEighthDiveLoopDownToDiag",
	"DiagDown25Brakes",
	"Count",
]

Example on develop:
image

Example on release v0.4.21 (prior to the failed fix):
image

Example on this PR:
image

Save file from the screenshots (has multiple rides with affected track pieces):
Six Flags old version with track pieces.zip

Example that the new fix does keep the issue from the previous PR fixed as well:
image

Thank you for your time. My apologies for misinterpreting the code and missing out on some test cases in the previous faulty PR and fix.

Basssiiie added a commit to Basssiiie/OpenRCT2-Unity that referenced this pull request May 19, 2025
@Gymnasiast
Copy link
Member

@Sadret Does this look all right to you?

@Basssiiie Basssiiie force-pushed the fix-plugin-track-segment-origin branch from 30fd455 to 2885136 Compare May 25, 2025 14:07
@AaronVanGeffen AaronVanGeffen added this to the v0.4.23 milestone May 25, 2025
@Sadret
Copy link
Contributor

Sadret commented May 25, 2025

@Sadret Does this look all right to you?

As I already said in #24142, I have no experience of this. I trust Bassie to do the right thing :)

@ZehMatt ZehMatt added the changelog This issue/PR deserves a changelog entry. label May 25, 2025
@ZehMatt ZehMatt merged commit 5fe3f7b into OpenRCT2:develop May 25, 2025
23 checks passed
tupaschoal added a commit that referenced this pull request Jun 7, 2025
- Feature: [#22476] “Time since last inspection” statistic is available in the rides window.
- Feature: [#24313] [Plugin] Add API for setting a ride vehicle’s sprite to a smoke plume.
- Improved: [#24345] Vehicle fallback sprites are less likely to glitch with the track.
- Improved: [#24362, #24491] The Windows installer is now translated as well.
- Improved: [#24364] Improve the fallback vehicle sprites for Zero G Rolls, and allow small ones to be built without cheats if the fallbacks are available.
- Improved: [#24368] Clicking the in-game update notication now leads to a more user-friendly download page.
- Improved: [#24400] Ride list in preservation window is now sorted alphabetically.
- Improved: [#24409] Steam installs of RCT Classic are now detected automatically.
- Improved: [#24413] Better performance when moving the viewport on Windows and Linux platforms.
- Improved: [#24417] Improve the fallback vehicle sprites for Dive Loops.
- Improved: [#24433] The ride, new ride, scenery, path, viewport, park and tool windows no longer redraw every frame if they have not changed.
- Improved: [#24467] Apply tweening only to on-screen entities when not zoomed out for better performance with uncapped FPS.
- Improved: [#24474] More efficiently search viewports when playing Audio.
- Improved: [#24479] More descriptive error messages for `set` commands in the in-game console.
- Improved: [#24563] The Linux .desktop file will now request the more powerful dedicated GPU on hybrid graphics systems.
- Change: [#24342, #24484] g2.dat is now split into g2.dat, fonts.dat and tracks.dat.
- Change: [#24362] The Windows installer now prevents installing to the same folder as RollerCoaster Tycoon 2 or Classic.
- Change: [#24418] Small & Large Zero G Rolls can now be built on the LIM Launched RC without cheats if vehicle sprites are available.
- Fix: [#5269] Font bugs when using the Russian release of RCT2 as the base game.
- Fix: [#11071, #22958] The virtual floor does not always draw correctly.
- Fix: [#18220] Some custom RCT1 scenarios are detected as competition DLC scenarios.
- Fix: [#20095] UCES Halloween - Cemetery Ridge scenario has mismatched entrance/exit on haunted house.
- Fix: [#20158] Custom animated scenery .DATs with frame offsets draw a random sprite at the end of their animation.
- Fix: [#22628] Potential crash while rebuilding the scenario index.
- Fix: [#23289] Dodgems and Flying Saucer cars can spawn on top of each other when the ride is opened.
- Fix: [#24332] Banner font renders differently when using RCT Classic as the base game.
- Fix: [#24343] Large gently sloped turns are buildable without cheats when the vehicles do not have sprites for them.
- Fix: [#24346] Possible crash during line drawing in OpenGL mode.
- Fix: [#24353] ‘Show dirty visuals’ is off by one pixel and does not work correctly with higher framerates.
- Fix: [#24362] When upgrading from an older version on Windows, old versions of official objects are not always removed.
- Fix: [#24366] Zero G Rolls have some incorrect vehicle yaw rotations.
- Fix: [#24371] Fix divide by zero in the scenery window when there is no scenery.
- Fix: [#24378] Prevent ride and stall statistics from overflowing.
- Fix: [#24388] Shortcut keys are not localised based on the user’s language settings.
- Fix: [#24403] Park fences draw underneath and through opaque water.
- Fix: [#24406] The network status window uses an undefined string for its title.
- Fix: [#24444] In the object load error window, the guide text overlaps when the title bar is enlarged.
- Fix: [#24446] [Plugin] Fix regression breaking the track iterator on specific track pieces.
- Fix: [#24447] Shortcut list is not refreshed when changing language.
- Fix: [#24448] Shortcuts involving the Caps Lock key are wrongly localised to NumPad Dot.
- Fix: [#24464] Window and viewport visibility is not calculated correctly causing minor performance issues.
- Fix: [#24488] Objects are not always redrawn immediately when they are reloaded from the Object Selection window.
- Fix: [#24544] RCT1 Maze designs with wooden walls are not imported correctly.
- Fix: [#24567] Long flat-to-steep wooden mine support sprites don't connect to flat supports exactly.
tupaschoal added a commit that referenced this pull request Jun 7, 2025
- Feature: [#22476] “Time since last inspection” statistic is available in the rides window.
- Feature: [#24313] [Plugin] Add API for setting a ride vehicle’s sprite to a smoke plume.
- Improved: [#24345] Vehicle fallback sprites are less likely to glitch with the track.
- Improved: [#24362, #24491] The Windows installer is now translated as well.
- Improved: [#24364] Improve the fallback vehicle sprites for Zero G Rolls, and allow small ones to be built without cheats if the fallbacks are available.
- Improved: [#24368] Clicking the in-game update notication now leads to a more user-friendly download page.
- Improved: [#24400] Ride list in preservation window is now sorted alphabetically.
- Improved: [#24409] Steam installs of RCT Classic are now detected automatically.
- Improved: [#24413] Better performance when moving the viewport on Windows and Linux platforms.
- Improved: [#24417] Improve the fallback vehicle sprites for Dive Loops.
- Improved: [#24433] The ride, new ride, scenery, path, viewport, park and tool windows no longer redraw every frame if they have not changed.
- Improved: [#24467] Apply tweening only to on-screen entities when not zoomed out for better performance with uncapped FPS.
- Improved: [#24474] More efficiently search viewports when playing Audio.
- Improved: [#24479] More descriptive error messages for `set` commands in the in-game console.
- Improved: [#24563] The Linux .desktop file will now request the more powerful dedicated GPU on hybrid graphics systems.
- Change: [#24342, #24484] g2.dat is now split into g2.dat, fonts.dat and tracks.dat.
- Change: [#24362] The Windows installer now prevents installing to the same folder as RollerCoaster Tycoon 2 or Classic.
- Change: [#24418] Small & Large Zero G Rolls can now be built on the LIM Launched RC without cheats if vehicle sprites are available.
- Fix: [#5269] Font bugs when using the Russian release of RCT2 as the base game.
- Fix: [#11071, #22958] The virtual floor does not always draw correctly.
- Fix: [#18220] Some custom RCT1 scenarios are detected as competition DLC scenarios.
- Fix: [#20095] UCES Halloween - Cemetery Ridge scenario has mismatched entrance/exit on haunted house.
- Fix: [#20158] Custom animated scenery .DATs with frame offsets draw a random sprite at the end of their animation.
- Fix: [#22628] Potential crash while rebuilding the scenario index.
- Fix: [#23289] Dodgems and Flying Saucer cars can spawn on top of each other when the ride is opened.
- Fix: [#24332] Banner font renders differently when using RCT Classic as the base game.
- Fix: [#24343] Large gently sloped turns are buildable without cheats when the vehicles do not have sprites for them.
- Fix: [#24346] Possible crash during line drawing in OpenGL mode.
- Fix: [#24353] ‘Show dirty visuals’ is off by one pixel and does not work correctly with higher framerates.
- Fix: [#24362] When upgrading from an older version on Windows, old versions of official objects are not always removed.
- Fix: [#24366] Zero G Rolls have some incorrect vehicle yaw rotations.
- Fix: [#24371] Fix divide by zero in the scenery window when there is no scenery.
- Fix: [#24378] Prevent ride and stall statistics from overflowing.
- Fix: [#24388] Shortcut keys are not localised based on the user’s language settings.
- Fix: [#24403] Park fences draw underneath and through opaque water.
- Fix: [#24406] The network status window uses an undefined string for its title.
- Fix: [#24444] In the object load error window, the guide text overlaps when the title bar is enlarged.
- Fix: [#24446] [Plugin] Fix regression breaking the track iterator on specific track pieces.
- Fix: [#24447] Shortcut list is not refreshed when changing language.
- Fix: [#24448] Shortcuts involving the Caps Lock key are wrongly localised to NumPad Dot.
- Fix: [#24464] Window and viewport visibility is not calculated correctly causing minor performance issues.
- Fix: [#24488] Objects are not always redrawn immediately when they are reloaded from the Object Selection window.
- Fix: [#24544] RCT1 Maze designs with wooden walls are not imported correctly.
- Fix: [#24567] Long flat-to-steep wooden mine support sprites don't connect to flat supports exactly.
CorySanin added a commit to CorySanin/OpenRCT2 that referenced this pull request Jun 22, 2025
v0.4.23

Release v0.4.23

- Feature: [OpenRCT2#22476] “Time since last inspection” statistic is available in the rides window.
- Feature: [OpenRCT2#24313] [Plugin] Add API for setting a ride vehicle’s sprite to a smoke plume.
- Improved: [OpenRCT2#24345] Vehicle fallback sprites are less likely to glitch with the track.
- Improved: [OpenRCT2#24362, OpenRCT2#24491] The Windows installer is now translated as well.
- Improved: [OpenRCT2#24364] Improve the fallback vehicle sprites for Zero G Rolls, and allow small ones to be built without cheats if the fallbacks are available.
- Improved: [OpenRCT2#24368] Clicking the in-game update notication now leads to a more user-friendly download page.
- Improved: [OpenRCT2#24400] Ride list in preservation window is now sorted alphabetically.
- Improved: [OpenRCT2#24409] Steam installs of RCT Classic are now detected automatically.
- Improved: [OpenRCT2#24413] Better performance when moving the viewport on Windows and Linux platforms.
- Improved: [OpenRCT2#24417] Improve the fallback vehicle sprites for Dive Loops.
- Improved: [OpenRCT2#24433] The ride, new ride, scenery, path, viewport, park and tool windows no longer redraw every frame if they have not changed.
- Improved: [OpenRCT2#24467] Apply tweening only to on-screen entities when not zoomed out for better performance with uncapped FPS.
- Improved: [OpenRCT2#24474] More efficiently search viewports when playing Audio.
- Improved: [OpenRCT2#24479] More descriptive error messages for `set` commands in the in-game console.
- Improved: [OpenRCT2#24563] The Linux .desktop file will now request the more powerful dedicated GPU on hybrid graphics systems.
- Change: [OpenRCT2#24342, OpenRCT2#24484] g2.dat is now split into g2.dat, fonts.dat and tracks.dat.
- Change: [OpenRCT2#24362] The Windows installer now prevents installing to the same folder as RollerCoaster Tycoon 2 or Classic.
- Change: [OpenRCT2#24418] Small & Large Zero G Rolls can now be built on the LIM Launched RC without cheats if vehicle sprites are available.
- Fix: [OpenRCT2#5269] Font bugs when using the Russian release of RCT2 as the base game.
- Fix: [OpenRCT2#11071, OpenRCT2#22958] The virtual floor does not always draw correctly.
- Fix: [OpenRCT2#18220] Some custom RCT1 scenarios are detected as competition DLC scenarios.
- Fix: [OpenRCT2#20095] UCES Halloween - Cemetery Ridge scenario has mismatched entrance/exit on haunted house.
- Fix: [OpenRCT2#20158] Custom animated scenery .DATs with frame offsets draw a random sprite at the end of their animation.
- Fix: [OpenRCT2#22628] Potential crash while rebuilding the scenario index.
- Fix: [OpenRCT2#23289] Dodgems and Flying Saucer cars can spawn on top of each other when the ride is opened.
- Fix: [OpenRCT2#24332] Banner font renders differently when using RCT Classic as the base game.
- Fix: [OpenRCT2#24343] Large gently sloped turns are buildable without cheats when the vehicles do not have sprites for them.
- Fix: [OpenRCT2#24346] Possible crash during line drawing in OpenGL mode.
- Fix: [OpenRCT2#24353] ‘Show dirty visuals’ is off by one pixel and does not work correctly with higher framerates.
- Fix: [OpenRCT2#24362] When upgrading from an older version on Windows, old versions of official objects are not always removed.
- Fix: [OpenRCT2#24366] Zero G Rolls have some incorrect vehicle yaw rotations.
- Fix: [OpenRCT2#24371] Fix divide by zero in the scenery window when there is no scenery.
- Fix: [OpenRCT2#24378] Prevent ride and stall statistics from overflowing.
- Fix: [OpenRCT2#24388] Shortcut keys are not localised based on the user’s language settings.
- Fix: [OpenRCT2#24403] Park fences draw underneath and through opaque water.
- Fix: [OpenRCT2#24406] The network status window uses an undefined string for its title.
- Fix: [OpenRCT2#24444] In the object load error window, the guide text overlaps when the title bar is enlarged.
- Fix: [OpenRCT2#24446] [Plugin] Fix regression breaking the track iterator on specific track pieces.
- Fix: [OpenRCT2#24447] Shortcut list is not refreshed when changing language.
- Fix: [OpenRCT2#24448] Shortcuts involving the Caps Lock key are wrongly localised to NumPad Dot.
- Fix: [OpenRCT2#24464] Window and viewport visibility is not calculated correctly causing minor performance issues.
- Fix: [OpenRCT2#24488] Objects are not always redrawn immediately when they are reloaded from the Object Selection window.
- Fix: [OpenRCT2#24544] RCT1 Maze designs with wooden walls are not imported correctly.
- Fix: [OpenRCT2#24567] Long flat-to-steep wooden mine support sprites don't connect to flat supports exactly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog This issue/PR deserves a changelog entry.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants