mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-14 11:32:56 +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: [#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: [#21908] Ride mode warnings when hovering track designs.
|
||||||
- Fix: [#22961] Clicking on the construction preview places duplicate flat rides and stalls.
|
- 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: [#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: [#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: [#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.
|
* A track piece coordinate and type within the game.
|
||||||
*/
|
*/
|
||||||
interface CarTrackLocation extends CoordsXYZD {
|
interface CarTrackLocation extends Readonly<CoordsXYZD> {
|
||||||
trackType: number;
|
readonly trackType: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2930,7 +2930,7 @@ declare global {
|
|||||||
/**
|
/**
|
||||||
* The location and direction of where the car is on the track.
|
* The location and direction of where the car is on the track.
|
||||||
*/
|
*/
|
||||||
trackLocation: CarTrackLocation;
|
readonly trackLocation: CarTrackLocation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current g-forces of this car.
|
* The current g-forces of this car.
|
||||||
@@ -2970,6 +2970,12 @@ declare global {
|
|||||||
* on the direction its moving in.
|
* on the direction its moving in.
|
||||||
*/
|
*/
|
||||||
travelBy(distance: number): void;
|
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 =
|
type VehicleStatus =
|
||||||
|
|||||||
@@ -588,6 +588,24 @@ void Vehicle::MoveRelativeDistance(int32_t distance)
|
|||||||
ClearFlag(VehicleFlags::MoveSingleCar | VehicleFlags::CollisionDisabled);
|
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)
|
Vehicle* TryGetVehicle(EntityId spriteIndex)
|
||||||
{
|
{
|
||||||
return TryGetEntity<Vehicle>(spriteIndex);
|
return TryGetEntity<Vehicle>(spriteIndex);
|
||||||
|
|||||||
@@ -47,6 +47,11 @@ struct VehicleInfo
|
|||||||
uint8_t direction; // 0x06
|
uint8_t direction; // 0x06
|
||||||
uint8_t Pitch; // 0x07
|
uint8_t Pitch; // 0x07
|
||||||
uint8_t bank_rotation; // 0x08
|
uint8_t bank_rotation; // 0x08
|
||||||
|
|
||||||
|
bool IsInvalid() const
|
||||||
|
{
|
||||||
|
return x == 0 && y == 0 && z == 0 && direction == 0 && Pitch == 0 && bank_rotation == 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SoundIdVolume;
|
struct SoundIdVolume;
|
||||||
@@ -230,12 +235,14 @@ struct Vehicle : EntityBase
|
|||||||
Ride* GetRide() const;
|
Ride* GetRide() const;
|
||||||
Vehicle* TrainHead() const;
|
Vehicle* TrainHead() const;
|
||||||
Vehicle* TrainTail() const;
|
Vehicle* TrainTail() const;
|
||||||
|
uint16_t GetTrackProgress() const;
|
||||||
void UpdateAnimationAnimalFlying();
|
void UpdateAnimationAnimalFlying();
|
||||||
void EnableCollisionsForTrain();
|
void EnableCollisionsForTrain();
|
||||||
/**
|
/**
|
||||||
* Instantly moves the specific car forward or backwards along the track.
|
* Instantly moves the specific car forward or backwards along the track.
|
||||||
*/
|
*/
|
||||||
void MoveRelativeDistance(int32_t distance);
|
void MoveRelativeDistance(int32_t distance);
|
||||||
|
void UpdateTrackChange();
|
||||||
OpenRCT2::TrackElemType GetTrackType() const
|
OpenRCT2::TrackElemType GetTrackType() const
|
||||||
{
|
{
|
||||||
return static_cast<OpenRCT2::TrackElemType>(TrackTypeAndDirection >> 2);
|
return static_cast<OpenRCT2::TrackElemType>(TrackTypeAndDirection >> 2);
|
||||||
@@ -279,7 +286,6 @@ struct Vehicle : EntityBase
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const VehicleInfo* GetMoveInfo() const;
|
const VehicleInfo* GetMoveInfo() const;
|
||||||
uint16_t GetTrackProgress() const;
|
|
||||||
void CableLiftUpdate();
|
void CableLiftUpdate();
|
||||||
bool CableLiftUpdateTrackMotionForwards();
|
bool CableLiftUpdateTrackMotionForwards();
|
||||||
bool CableLiftUpdateTrackMotionBackwards();
|
bool CableLiftUpdateTrackMotionBackwards();
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ namespace OpenRCT2
|
|||||||
|
|
||||||
namespace OpenRCT2::Scripting
|
namespace OpenRCT2::Scripting
|
||||||
{
|
{
|
||||||
static constexpr int32_t kPluginApiVersion = 104;
|
static constexpr int32_t kPluginApiVersion = 105;
|
||||||
|
|
||||||
// Versions marking breaking changes.
|
// Versions marking breaking changes.
|
||||||
static constexpr int32_t kApiVersionPeepDeprecation = 33;
|
static constexpr int32_t kApiVersionPeepDeprecation = 33;
|
||||||
|
|||||||
@@ -9,10 +9,13 @@
|
|||||||
|
|
||||||
#include "ScVehicle.hpp"
|
#include "ScVehicle.hpp"
|
||||||
|
|
||||||
|
#include "../../../world/tile_element/TrackElement.h"
|
||||||
#include "../ride/ScRide.hpp"
|
#include "../ride/ScRide.hpp"
|
||||||
|
|
||||||
#ifdef ENABLE_SCRIPTING
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
|
||||||
|
using namespace OpenRCT2::Drawing;
|
||||||
|
|
||||||
namespace OpenRCT2::Scripting
|
namespace OpenRCT2::Scripting
|
||||||
{
|
{
|
||||||
static const DukEnumMap<Vehicle::Status> VehicleStatusMap({
|
static const DukEnumMap<Vehicle::Status> VehicleStatusMap({
|
||||||
@@ -75,7 +78,7 @@ namespace OpenRCT2::Scripting
|
|||||||
ctx, &ScVehicle::flag_get<VehicleFlags::CarIsReversed>, &ScVehicle::flag_set<VehicleFlags::CarIsReversed>,
|
ctx, &ScVehicle::flag_get<VehicleFlags::CarIsReversed>, &ScVehicle::flag_set<VehicleFlags::CarIsReversed>,
|
||||||
"isReversed");
|
"isReversed");
|
||||||
dukglue_register_property(ctx, &ScVehicle::colours_get, &ScVehicle::colours_set, "colours");
|
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::trackProgress_get, nullptr, "trackProgress");
|
||||||
dukglue_register_property(ctx, &ScVehicle::remainingDistance_get, nullptr, "remainingDistance");
|
dukglue_register_property(ctx, &ScVehicle::remainingDistance_get, nullptr, "remainingDistance");
|
||||||
dukglue_register_property(ctx, &ScVehicle::subposition_get, nullptr, "subposition");
|
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::guests_get, nullptr, "guests");
|
||||||
dukglue_register_property(ctx, &ScVehicle::gForces_get, nullptr, "gForces");
|
dukglue_register_property(ctx, &ScVehicle::gForces_get, nullptr, "gForces");
|
||||||
dukglue_register_method(ctx, &ScVehicle::travelBy, "travelBy");
|
dukglue_register_method(ctx, &ScVehicle::travelBy, "travelBy");
|
||||||
|
dukglue_register_method(ctx, &ScVehicle::moveToTrack, "moveToTrack");
|
||||||
}
|
}
|
||||||
|
|
||||||
Vehicle* ScVehicle::GetVehicle() const
|
Vehicle* ScVehicle::GetVehicle() const
|
||||||
@@ -397,20 +401,6 @@ namespace OpenRCT2::Scripting
|
|||||||
}
|
}
|
||||||
return ToDuk(ctx, nullptr);
|
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
|
uint16_t ScVehicle::trackProgress_get() const
|
||||||
{
|
{
|
||||||
@@ -543,8 +533,41 @@ namespace OpenRCT2::Scripting
|
|||||||
if (vehicle != nullptr)
|
if (vehicle != nullptr)
|
||||||
{
|
{
|
||||||
vehicle->MoveRelativeDistance(value);
|
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
|
} // namespace OpenRCT2::Scripting
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#ifdef ENABLE_SCRIPTING
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
|
||||||
|
#include "../../../entity/EntityTweener.h"
|
||||||
#include "../../../ride/Ride.h"
|
#include "../../../ride/Ride.h"
|
||||||
#include "ScEntity.hpp"
|
#include "ScEntity.hpp"
|
||||||
|
|
||||||
@@ -101,6 +102,8 @@ namespace OpenRCT2::Scripting
|
|||||||
DukValue gForces_get() const;
|
DukValue gForces_get() const;
|
||||||
|
|
||||||
void travelBy(int32_t value);
|
void travelBy(int32_t value);
|
||||||
|
|
||||||
|
void moveToTrack(int32_t x, int32_t y, int32_t elementIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace OpenRCT2::Scripting
|
} // namespace OpenRCT2::Scripting
|
||||||
|
|||||||
Reference in New Issue
Block a user