mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-10 09:32:29 +01:00
Scripting: Add Car.moveToTrack API (#23359)
* Scripting: Redraw vehicle when setting track location
* Scripting: introduce car.moveToTrack
A new function to move cars to tracks easier. Also redraws the car.
* Revert car.trackLocation to CoordsXYZD
reverts 30a555d3c2
car.moveToTrack() achieves the same thing in a saner API.
* Final fixes for vehicle.moveToTrack
added back tracklocation.Get with track type
added EntityTweener call at the end of travelBy/moveToTrack
* moveToTrack: final bassie review fixes.
* moveToTrack: use tile coords
* moveToTrack: api increment
---------
Co-authored-by: Guy Sviry <guy@axissecurity.com>
Co-authored-by: Tulio Leao <tupaschoal@gmail.com>
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
- Fix: [#19506] Queue paths can be placed on level crossings by replacing an existing regular path.
|
||||
- Fix: [#21908] Ride mode warnings when hovering track designs.
|
||||
- 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.
|
||||
|
||||
12
distribution/openrct2.d.ts
vendored
12
distribution/openrct2.d.ts
vendored
@@ -120,8 +120,8 @@ declare global {
|
||||
/**
|
||||
* A track piece coordinate and type within the game.
|
||||
*/
|
||||
interface CarTrackLocation extends CoordsXYZD {
|
||||
trackType: number;
|
||||
interface CarTrackLocation extends Readonly<CoordsXYZD> {
|
||||
readonly trackType: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2930,7 +2930,7 @@ declare global {
|
||||
/**
|
||||
* The location and direction of where the car is on the track.
|
||||
*/
|
||||
trackLocation: CarTrackLocation;
|
||||
readonly trackLocation: CarTrackLocation;
|
||||
|
||||
/**
|
||||
* The current g-forces of this car.
|
||||
@@ -2970,6 +2970,12 @@ declare global {
|
||||
* on the direction its moving in.
|
||||
*/
|
||||
travelBy(distance: number): void;
|
||||
|
||||
/**
|
||||
* Moves the vehicle to the track piece specified in the parameters.
|
||||
* Coordinates are tile coords.
|
||||
*/
|
||||
moveToTrack(x: number, y: number, elemIndex: number): void;
|
||||
}
|
||||
|
||||
type VehicleStatus =
|
||||
|
||||
@@ -588,6 +588,24 @@ void Vehicle::MoveRelativeDistance(int32_t distance)
|
||||
ClearFlag(VehicleFlags::MoveSingleCar | VehicleFlags::CollisionDisabled);
|
||||
}
|
||||
|
||||
void Vehicle::UpdateTrackChange()
|
||||
{
|
||||
auto curRide = GetRide();
|
||||
if (curRide == nullptr)
|
||||
return;
|
||||
|
||||
const auto moveInfo = GetMoveInfo();
|
||||
if (moveInfo == nullptr || moveInfo->IsInvalid())
|
||||
return;
|
||||
|
||||
_vehicleCurPosition = TrackLocation
|
||||
+ CoordsXYZ{ moveInfo->x, moveInfo->y, moveInfo->z + GetRideTypeDescriptor((*curRide).type).Heights.VehicleZOffset };
|
||||
Orientation = moveInfo->direction;
|
||||
bank_rotation = moveInfo->bank_rotation;
|
||||
Pitch = moveInfo->Pitch;
|
||||
MoveTo(_vehicleCurPosition);
|
||||
}
|
||||
|
||||
Vehicle* TryGetVehicle(EntityId spriteIndex)
|
||||
{
|
||||
return TryGetEntity<Vehicle>(spriteIndex);
|
||||
|
||||
@@ -47,6 +47,11 @@ struct VehicleInfo
|
||||
uint8_t direction; // 0x06
|
||||
uint8_t Pitch; // 0x07
|
||||
uint8_t bank_rotation; // 0x08
|
||||
|
||||
bool IsInvalid() const
|
||||
{
|
||||
return x == 0 && y == 0 && z == 0 && direction == 0 && Pitch == 0 && bank_rotation == 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct SoundIdVolume;
|
||||
@@ -230,12 +235,14 @@ struct Vehicle : EntityBase
|
||||
Ride* GetRide() const;
|
||||
Vehicle* TrainHead() const;
|
||||
Vehicle* TrainTail() const;
|
||||
uint16_t GetTrackProgress() const;
|
||||
void UpdateAnimationAnimalFlying();
|
||||
void EnableCollisionsForTrain();
|
||||
/**
|
||||
* Instantly moves the specific car forward or backwards along the track.
|
||||
*/
|
||||
void MoveRelativeDistance(int32_t distance);
|
||||
void UpdateTrackChange();
|
||||
OpenRCT2::TrackElemType GetTrackType() const
|
||||
{
|
||||
return static_cast<OpenRCT2::TrackElemType>(TrackTypeAndDirection >> 2);
|
||||
@@ -279,7 +286,6 @@ struct Vehicle : EntityBase
|
||||
|
||||
private:
|
||||
const VehicleInfo* GetMoveInfo() const;
|
||||
uint16_t GetTrackProgress() const;
|
||||
void CableLiftUpdate();
|
||||
bool CableLiftUpdateTrackMotionForwards();
|
||||
bool CableLiftUpdateTrackMotionBackwards();
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace OpenRCT2
|
||||
|
||||
namespace OpenRCT2::Scripting
|
||||
{
|
||||
static constexpr int32_t kPluginApiVersion = 104;
|
||||
static constexpr int32_t kPluginApiVersion = 105;
|
||||
|
||||
// Versions marking breaking changes.
|
||||
static constexpr int32_t kApiVersionPeepDeprecation = 33;
|
||||
|
||||
@@ -9,10 +9,13 @@
|
||||
|
||||
#include "ScVehicle.hpp"
|
||||
|
||||
#include "../../../world/tile_element/TrackElement.h"
|
||||
#include "../ride/ScRide.hpp"
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
|
||||
using namespace OpenRCT2::Drawing;
|
||||
|
||||
namespace OpenRCT2::Scripting
|
||||
{
|
||||
static const DukEnumMap<Vehicle::Status> VehicleStatusMap({
|
||||
@@ -75,7 +78,7 @@ namespace OpenRCT2::Scripting
|
||||
ctx, &ScVehicle::flag_get<VehicleFlags::CarIsReversed>, &ScVehicle::flag_set<VehicleFlags::CarIsReversed>,
|
||||
"isReversed");
|
||||
dukglue_register_property(ctx, &ScVehicle::colours_get, &ScVehicle::colours_set, "colours");
|
||||
dukglue_register_property(ctx, &ScVehicle::trackLocation_get, &ScVehicle::trackLocation_set, "trackLocation");
|
||||
dukglue_register_property(ctx, &ScVehicle::trackLocation_get, nullptr, "trackLocation");
|
||||
dukglue_register_property(ctx, &ScVehicle::trackProgress_get, nullptr, "trackProgress");
|
||||
dukglue_register_property(ctx, &ScVehicle::remainingDistance_get, nullptr, "remainingDistance");
|
||||
dukglue_register_property(ctx, &ScVehicle::subposition_get, nullptr, "subposition");
|
||||
@@ -88,6 +91,7 @@ namespace OpenRCT2::Scripting
|
||||
dukglue_register_property(ctx, &ScVehicle::guests_get, nullptr, "guests");
|
||||
dukglue_register_property(ctx, &ScVehicle::gForces_get, nullptr, "gForces");
|
||||
dukglue_register_method(ctx, &ScVehicle::travelBy, "travelBy");
|
||||
dukglue_register_method(ctx, &ScVehicle::moveToTrack, "moveToTrack");
|
||||
}
|
||||
|
||||
Vehicle* ScVehicle::GetVehicle() const
|
||||
@@ -397,20 +401,6 @@ namespace OpenRCT2::Scripting
|
||||
}
|
||||
return ToDuk(ctx, nullptr);
|
||||
}
|
||||
void ScVehicle::trackLocation_set(const DukValue& value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
auto vehicle = GetVehicle();
|
||||
if (vehicle != nullptr)
|
||||
{
|
||||
auto x = AsOrDefault(value["x"], 0);
|
||||
auto y = AsOrDefault(value["y"], 0);
|
||||
auto z = AsOrDefault(value["z"], 0);
|
||||
vehicle->TrackLocation = CoordsXYZ(x, y, z);
|
||||
vehicle->SetTrackDirection(AsOrDefault(value["direction"], 0));
|
||||
vehicle->SetTrackType(static_cast<TrackElemType>(AsOrDefault(value["trackType"], 0)));
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ScVehicle::trackProgress_get() const
|
||||
{
|
||||
@@ -543,8 +533,41 @@ namespace OpenRCT2::Scripting
|
||||
if (vehicle != nullptr)
|
||||
{
|
||||
vehicle->MoveRelativeDistance(value);
|
||||
EntityTweener::Get().RemoveEntity(vehicle);
|
||||
}
|
||||
}
|
||||
|
||||
void ScVehicle::moveToTrack(int32_t x, int32_t y, int32_t elementIndex)
|
||||
{
|
||||
CoordsXY coords = TileCoordsXY(x, y).ToCoordsXY();
|
||||
auto vehicle = GetVehicle();
|
||||
if (vehicle == nullptr)
|
||||
return;
|
||||
|
||||
auto el = MapGetNthElementAt(coords, elementIndex);
|
||||
if (el == nullptr)
|
||||
return;
|
||||
|
||||
auto origin = GetTrackSegmentOrigin(CoordsXYE(coords, el));
|
||||
if (!origin)
|
||||
return;
|
||||
|
||||
auto trackEl = el->AsTrack();
|
||||
|
||||
vehicle->TrackLocation.x = origin->x;
|
||||
vehicle->TrackLocation.y = origin->y;
|
||||
vehicle->TrackLocation.z = origin->z;
|
||||
vehicle->SetTrackDirection(origin->direction);
|
||||
vehicle->SetTrackType(trackEl->GetTrackType());
|
||||
|
||||
// Clip track progress to avoid being out of bounds of current piece
|
||||
uint16_t trackTotalProgress = vehicle->GetTrackProgress();
|
||||
if (trackTotalProgress && vehicle->track_progress >= trackTotalProgress)
|
||||
vehicle->track_progress = trackTotalProgress - 1;
|
||||
|
||||
vehicle->UpdateTrackChange();
|
||||
EntityTweener::Get().RemoveEntity(vehicle);
|
||||
}
|
||||
} // namespace OpenRCT2::Scripting
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
|
||||
#include "../../../entity/EntityTweener.h"
|
||||
#include "../../../ride/Ride.h"
|
||||
#include "ScEntity.hpp"
|
||||
|
||||
@@ -101,6 +102,8 @@ namespace OpenRCT2::Scripting
|
||||
DukValue gForces_get() const;
|
||||
|
||||
void travelBy(int32_t value);
|
||||
|
||||
void moveToTrack(int32_t x, int32_t y, int32_t elementIndex);
|
||||
};
|
||||
|
||||
} // namespace OpenRCT2::Scripting
|
||||
|
||||
Reference in New Issue
Block a user