-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Scripting: Add Car.moveToTrack API #23359
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
Conversation
Maybe instead of modifying trackLocation_set, I could introduce a new dedicated |
c08e648
to
3e8993d
Compare
I pushed a new version that calculates the new vehicle state on its own instead of piggy-backing |
d272e08
to
9c15671
Compare
rctdemo17.mp4le demo (now without travelBy()) I also added track_progress clipping code to be within the current piece when coming from a longer one. |
@@ -584,6 +584,20 @@ void Vehicle::MoveRelativeDistance(int32_t distance) | |||
ClearFlag(VehicleFlags::MoveSingleCar | VehicleFlags::CollisionDisabled); | |||
} | |||
|
|||
void Vehicle::UpdateTrackChange() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is all only ever useful for your one scripting bit of code it would make more sense to keep it with the rest of the scripting function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but doesn't it touch private Vehicle fields? I thought this means it has to happen in Vehicle.cpp no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_vehicleCurPosition
namely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_vehicleCurPosition
namely.
Pretty sure that is a global var
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well but it's still only accessible from Vehicle.cpp if it's defined there. But nevermind that because I just tested and it works well with just using a local variable instead. dunno why it's being done like that in the existing functions.
But... on my way trying to move it to ScVehicle
I ran into couple of Vehicle
functions that really are private.
GetTrackProgress/GetMoveInfo/GetRideTypeDescriptor
. What do you suggest?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the reason all the other users are using a global Is just because thats how it worked in assembly. I'd need to have a look see how all this is getting updated. Perhaps there is a different function we can make that can be used by a few other consumers. I'm just not a fan of having basically half a function in one file and the other half in another.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I follow what are you suggesting to do? refactor the bunch of other similar code to a single function that sorta looks like what I made?
892cfd2
to
214f33e
Compare
I would say bump scripting api version but I'm not sure it's needed at this time. |
(comment deleted) I thought I wrote That's why in my starting attempt I tried to confine all the code that relates to the redraw itself in another function, in case we want to introduce as a new method to |
Okay nevermind that^ I think we're ready for merge here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/openrct2/ride/Vehicle.cpp
Outdated
// Clip track progress to avoid being out of bounds of current piece | ||
uint16_t trackTotalProgress = GetTrackProgress(); | ||
if (track_progress >= trackTotalProgress) | ||
track_progress = trackTotalProgress - 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The track progress is capped here but the track progress of the vehicle is not updated accordingly, so the trackProgress
getter now returns an out of bounds value if read after updating the trackLocation
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm looks like I didn't even validate for invalid value from GetTrackProgress()
. Nice catch!
be4d0bb
to
0f574f9
Compare
I moved the new functionality to a new API method, |
0f574f9
to
ab63f2b
Compare
9d12cc1
to
2308cd3
Compare
@duncanspumpkin and @Basssiiie can you double check this is ready to merge? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have tested it again and both the setter and the moveToTrack
method still have some issues.
2025-01-02.13-44-13.mp4
Also wouldn't it be better to either have only moveToTrack
and then trackLocation
as a readonly getter, OR only having trackLocation
getter and setter, instead of both the method and the setter?
Click here for my updated test script.
/// <reference path="../bin/openrct2.d.ts" />
// @ts-check
registerPlugin({
name: "Test track location",
version: "1",
authors: ['Basssiiie'],
targetApiVersion: 82,
type: "local",
licence: "MIT",
main() {
ui.registerMenuItem("Test track location", function() {
ui.activateTool({
id: 'test-pick-vehicle',
cursor: 'cross_hair',
filter: ["entity"],
onDown: function(args) {
var entityId = args.entityId;
if (entityId === undefined) return;
ui.tool.cancel();
console.log("Entity "+entityId+" selected");
var entity = map.getEntity(entityId);
var window = ui.openWindow({
classification: "test-track-location",
title: "Test track location",
width: 200,
height: 150,
onUpdate: function()
{
var trackLocation = entity.trackLocation;
window.findWidget("info-label").text =
"Entity id: "+entityId
+"\nTile: "+[Math.floor(trackLocation.x / 32), Math.floor(trackLocation.y / 32)].join(", ")
+"\nTrack: "+[trackLocation.x, trackLocation.y, trackLocation.z].join(", ")
+"\nDirection: "+trackLocation.direction
+"\nType: "+trackLocation.trackType
+"\nProgress: "+entity.trackProgress+" / "+context.getTrackSegment(trackLocation.trackType).getSubpositionLength(entity.subposition, trackLocation.direction);
},
widgets: [
{
name: "info-label",
type: "label",
x: 10,
y: 25,
width: 180,
height: 15,
},
{
name: "pick-location-button",
type: "button",
x: 10,
y: 105,
width: 180,
height: 15,
text: "Set track location",
onClick: function() {
ui.activateTool({
id: "test-set-track-location",
cursor: "cross_hair",
filter: ["ride"],
onDown: function(args) {
var coords = args.mapCoords;
var index = args.tileElementIndex;
if (!coords || index === undefined) return;
ui.tool.cancel();
var element = map.getTile(Math.floor(coords.x / 32), Math.floor(coords.y / 32)).getElement(index);
var location = {
x: coords.x,
y: coords.y,
z: element.baseZ,
direction: element.direction,
trackType: element.trackType
}
console.log("Set location to", location);
entity.trackLocation = location;
}
})
}
},
{
name: "move-location-button",
type: "button",
x: 10,
y: 125,
width: 180,
height: 15,
text: "Move track location",
onClick: function() {
ui.activateTool({
id: "test-move-track-location",
cursor: "cross_hair",
filter: ["ride"],
onDown: function(args) {
var coords = args.mapCoords;
var index = args.tileElementIndex;
if (!coords || index === undefined) return;
ui.tool.cancel();
var location = {
x: coords.x,
y: coords.y
}
console.log("Move location to", location, index);
entity.moveToTrack(location, index);
}
})
}
},
]
})
}
})
})
}
});
And the park:
Six Flags flat train track.zip
distribution/openrct2.d.ts
Outdated
/** | ||
* Moves the vehicle to the track piece specified in the parameters. | ||
*/ | ||
moveToTrack(coord: CoordsXY, elemIndex: number): void; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moveToTrack(coord: CoordsXY, elemIndex: number): void; | |
moveToTrack(x: number, y: number, trackElementIndex: number): void; |
And also have x
and y
be tile coordinates instead of entity coordinates would probably be neater. 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@guysv could you still look at this one?
This pull request has been marked as stale and will be closed in 14 days if no action is taken. To keep it open, leave a comment or remove the |
This pull request has been marked as stale and will be closed in 14 days if no action is taken. To keep it open, leave a comment or remove the |
2308cd3
to
71875c3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had another test at this and it works great for the most part. All previous issues are resolved, except for one. The only thing that is still missing is calling this function in both travelBy()
and moveToTrack()
at the end, to prevent it from snapping back to the original position when "Uncap FPS" is enabled. 🙂
EntityTweener::Get().RemoveEntity(vehicle);
distribution/openrct2.d.ts
Outdated
@@ -2676,7 +2669,7 @@ declare global { | |||
/** | |||
* The location and direction of where the car is on the track. | |||
*/ | |||
trackLocation: CarTrackLocation; | |||
trackLocation: CoordsXYZD; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's best to not revert this to the prior PR. Instead it'd be better to keep the getter as is, but only remove the setter as that's the broken one. Reading the vehicle's track type could still be useful in other scenarios.
Also make sure to make the properties on CarTrackLocation
readonly as well, to avoid any confusion there. 🙂
trackLocation: CoordsXYZD; | |
readonly trackLocation: CarTrackLocation; |
distribution/changelog.txt
Outdated
@@ -109,7 +110,7 @@ | |||
- Fix: [#22742, #22793] In game console does not handle format tokens properly. | |||
- Fix: [#23135] Map generator tree placement has noticable patterns. | |||
- Fix: [#23286] Currency formatted incorrectly in the in game console. | |||
- Fix: [#23348] Console set commands don’t print output properly. | |||
- Fix: [#23348] Console set commands don't print output properly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this change is a mistake and should probably be reverted?
made a final push. I think its GTG!! @Basssiiie @tupaschoal |
749402e
to
90e9e46
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still missing two of my suggested changes unfortunately. 😥
One being that I suggested changing CarTrackLocation
to this, to avoid people attempting to assign the properties (which does nothing):
interface CarTrackLocation extends Readonly<CoordsXYZD> {
readonly trackType: number;
}
The other is an alternative signature for the moveToTrack()
method, which I now have tagged you in again here @guysv
Edit: also needs a plugin api version increment.
4bf98ea
to
8480ff5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking all good to me. I have tested it again as well and it all works great now! Thank you for your time. 😃
A new function to move cars to tracks easier. Also redraws the car.
reverts 30a555d car.moveToTrack() achieves the same thing in a saner API.
added back tracklocation.Get with track type added EntityTweener call at the end of travelBy/moveToTrack
8480ff5
to
866a69d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At a glance it looks good to me.
- Feature: [#22646] New scenario files now contain a minimap image, shown in the scenario selection window. - Feature: [#23774] Climates can now be customised using objects. - Feature: [#23876] New park save files now contain a preview image, shown in the load/save window. - Improved: [#24078] Handrails on Wooden Roller Coaster station sprites with no platforms have been removed. - Improved: [objects#379] Add additional colour schemes to Mine Train. - Change: [#23932] The land rights window now checks “Land Owned” by default. - Change: [#23936] The ‘guests prefer less/more intense rides’ settings have been turned into a dropdown. - Change: [#24059] The ‘select other ride’ button is now available in the track designs manager. - Change: [#24067] [Plugin] Registered menu items are now listed alphabetically. - Change: [#24070] Footpath selection menus now show object names on hover using a tooltip. - Change: [#24101] Frozen peeps are no longer removed when using the 'remove all guests' cheat. - Fix: [#4225] Ride Construction window offers non-existent banked sloped to level curve (original bug). - Fix: [#5281] Missing supports on miniature railways built backwards. - Fix: [#7222] Transparent pixels in sloped path tunnels (original bug). - Fix: [#10379] Banners outside the park can be renamed and modified (original bug). - Fix: [#10582] Low clearance tunnels below water are drawn incorrectly (original bug). - Fix: [#17524, #23710] Station bases are drawn on many ride types when the “No entrance, no platform station” style is selected. - Fix: [#18169] CJK, Arabic and Vietnamese display all text as ‘???’ on Android. - Fix: [#18309] Flying and Multi Dimension trains glitch when changing between inverted and uninverted track when uncap fps is on. - Fix: [#19506] Queue paths can be placed on level crossings by replacing an existing regular path. - Fix: [#21803] The park fence is drawn differently in OpenGL compared to software rendering when zoomed out. - Fix: [#21824] Some sprites are drawn incorrectly when zoomed out in OpenGL rendering. - Fix: [#21908] Ride mode warnings when hovering track designs. - Fix: [#22820] OpenGL does not draw masked sprites correctly. - Fix: [#22961] Clicking on the construction preview places duplicate flat rides and stalls. - Fix: [#23359] Scripting: Add car.moveToTrack, an easier API than setting car.trackLocation directly. - Fix: [#23443] New GOG version of RCT2 is not extracted correctly. - Fix: [#23484] Stray coloured pixels on castle-themed stations and Roman-themed entrances/exits (original bug). - Fix: [#23486] Object selection minimum requirements can be bypassed with close window hotkey. - Fix: [#23743] Parks with guest goals over 32767 do not appear in the scenario list. - Fix: [#23844] Sound effects keep playing when loading another save. - Fix: [#23881] Compiling on Raspbian/arm-linux-gnueabihf fails. - Fix: [#23891] Inverted Hairpin Coaster track can draw over things above it (original bug). - Fix: [#23892] Gentle banked Wooden Roller Coaster track glitches as trains pass (original bug). - Fix: [#23897] Reverse Freefall Coaster slope up to vertical track piece does not draw a vertical tunnel. - Fix: [#23910] Heartline Twister Coaster track can draw over things above it (original bug). - Fix: [#23939] Incorrect assertion when trying to load heightmap. - Fix: [#23941] Underflow in “Repay loan and achieve a certain park value” objective when using Japanese. - Fix: [#23949] Walls draw over sloped rear water edges and those edge sprites are misaligned (original bug). - Fix: [#23960] Corner path fences can draw over adjacent sloped land (original bug). - Fix: [#23961] Lamps and queue line tvs draw incorrectly on paths with fences. - Fix: [#23983] Ordering files by size does not work and occasionally crashes the game. - Fix: [#24009] [Plugin] The object manager API does not identify recently introduced object types. - Fix: [#24028] Giga and LSM Launched Coaster booster sprites have pixels that draw over transparent pixels. - Fix: [#24077] Track Designer crashes when clicking the park fence.
So #22272 introduced the ability to set a vehicle's track location property, which allows teleporting vehicles across any other track piece available.
Back when I wrote that addition, I noticed that merely setting trackLocation does not actually trigger vehicle redraw. The vehicle teleports to its correct position only after trying to advance the track a bit on its own.
Alternatively, you could trigger track advancement with
car.travelBy()
, which is how I made the demo. I came to realize using travelBy is kind of hack, so here I figured a way to trigger vehicle redraw after setting trackLocation.The way travelBy gets this effect is by adding some pending progress to be made for that vehicle (vehicle.remaining_distance, and calling
UpdateTrackMotion
, which eventually translates remaining_distance into calls toUpdateTrackMotionForwards
(when going forward)So the first move is to introduce a new vehicle flagVehicleFlags::UpdateSingleCar
, that bypassesUpdateTrackMotion
remaining_distance check, and makes the call toUpdateTrackMotionForwards
regardless of pending moves.Next, useVehicleFlags::UpdateSingleCar
to also preventUpdateTrackMotionForwards
from advancingvehicle.track_progress
, as we don't want to advance there when just recalculating state due to new trackLocation.Errm nvm. all that, see second comment. Anyway I found how to recalculate vehicle state according to new track location
@Basssiiie FYI