Add vehicle API for plugins

This commit is contained in:
Ted John 2020-05-31 01:08:25 +01:00
parent 2743629142
commit c5b2b2017a
5 changed files with 542 additions and 2 deletions

View File

@ -854,6 +854,130 @@ declare global {
remove(): void;
}
/**
* Represents a single car on a ride. A train is made up of multiple cars, but
* something like boat hire will be one car per boat.
*/
interface Car extends Entity {
/**
* The ride this car belongs to.
*/
ride: number;
/**
* The ride object for this car, e.g. the ladybird trains object.
*/
rideObject: number;
/**
* The vehicle type for the ride object used. This is a local index
* into the ride object list of vehicle types.
*/
vehicleObject: number;
spriteType: number;
/**
* How many seats the car has, i.e. the capacity.
*/
numSeats: number;
/**
* The next car on the same train. If this is the last or only car on the train,
* this will return null.
*/
nextCarOnTrain: number | null;
/**
* The previous car on the ride. This may be the on the same train or the previous
* train. This will point to the last car if this is the first car on the ride.
*/
previousCarOnRide: number;
/**
* The next car on the ride. This may be the on the same train or the next
* train. This will point to the first car if this is the last car on the ride.
*/
nextCarOnRide: number;
/**
* The current station the train is in or departing.
*/
currentStation: number;
/**
* How heavy the car is. This is the sum of the mass of the empty car and the
* mass of each guest that is riding it.
*/
mass: number;
/**
* How much the car's velocity changes per tick.
*/
acceleration: number;
/**
* How fast the car is moving.
*/
velocity: number;
/**
* The current tilt of the car in the X/Y axis.
*/
bankRotation: number;
/**
* The colour of the car.
*/
colours: VehicleColour;
speed: number;
poweredAcceleration: number;
/**
* Current status of the car or train.
*/
status: VehicleStatus;
/**
* List of peep IDs ordered by seat.
*/
peeps: (number | null)[];
}
type VehicleStatus =
"arriving" |
"crashed" |
"crashing" |
"crooked_house_operating" |
"departing" |
"doing_circus_show" |
"ferris_wheel_rotating" |
"haunted_house_operating" |
"moving_to_end_of_station" |
"operating_1a" |
"rotating" |
"showing_film" |
"simulator_operating" |
"space_rings_operating" |
"starting" |
"stopped_by_block_brake" |
"stopping_1b" |
"stopping" |
"swinging" |
"top_spin_operating" |
"travelling_boat" |
"travelling_cable_lift" |
"travelling_dodgems" |
"travelling" |
"unloading_passengers_1c" |
"unloading_passengers" |
"waiting_for_cable_lift" |
"waiting_for_passengers_17" |
"waiting_for_passengers" |
"waiting_to_depart" |
"waiting_to_start";
/**
* Represents a guest or staff member.
*/

View File

@ -219,7 +219,7 @@ namespace OpenRCT2::Scripting
auto it = _s2n.find(k);
if (it == _s2n.end())
{
return 0;
return static_cast<T>(0);
}
return it->second;
}

View File

@ -17,6 +17,7 @@
# include "../peep/Staff.h"
# include "../world/Sprite.h"
# include "Duktape.hpp"
# include "ScRide.hpp"
# include "ScriptEngine.h"
# include <algorithm>
@ -176,6 +177,418 @@ namespace OpenRCT2::Scripting
}
};
static const DukEnumMap<VEHICLE_STATUS> VehicleStatusMap({
{ "moving_to_end_of_station", VEHICLE_STATUS_MOVING_TO_END_OF_STATION },
{ "waiting_for_passengers", VEHICLE_STATUS_WAITING_FOR_PASSENGERS },
{ "waiting_to_depart", VEHICLE_STATUS_WAITING_TO_DEPART },
{ "departing", VEHICLE_STATUS_DEPARTING },
{ "travelling", VEHICLE_STATUS_TRAVELLING },
{ "arriving", VEHICLE_STATUS_ARRIVING },
{ "unloading_passengers", VEHICLE_STATUS_UNLOADING_PASSENGERS },
{ "travelling_boat", VEHICLE_STATUS_TRAVELLING_BOAT },
{ "crashing", VEHICLE_STATUS_CRASHING },
{ "crashed", VEHICLE_STATUS_CRASHED },
{ "travelling_dodgems", VEHICLE_STATUS_TRAVELLING_DODGEMS },
{ "swinging", VEHICLE_STATUS_SWINGING },
{ "rotating", VEHICLE_STATUS_ROTATING },
{ "ferris_wheel_rotating", VEHICLE_STATUS_FERRIS_WHEEL_ROTATING },
{ "simulator_operating", VEHICLE_STATUS_SIMULATOR_OPERATING },
{ "showing_film", VEHICLE_STATUS_SHOWING_FILM },
{ "space_rings_operating", VEHICLE_STATUS_SPACE_RINGS_OPERATING },
{ "top_spin_operating", VEHICLE_STATUS_TOP_SPIN_OPERATING },
{ "haunted_house_operating", VEHICLE_STATUS_HAUNTED_HOUSE_OPERATING },
{ "doing_circus_show", VEHICLE_STATUS_DOING_CIRCUS_SHOW },
{ "crooked_house_operating", VEHICLE_STATUS_CROOKED_HOUSE_OPERATING },
{ "waiting_for_cable_lift", VEHICLE_STATUS_WAITING_FOR_CABLE_LIFT },
{ "travelling_cable_lift", VEHICLE_STATUS_TRAVELLING_CABLE_LIFT },
{ "stopping", VEHICLE_STATUS_STOPPING },
{ "waiting_for_passengers_17", VEHICLE_STATUS_WAITING_FOR_PASSENGERS_17 },
{ "waiting_to_start", VEHICLE_STATUS_WAITING_TO_START },
{ "starting", VEHICLE_STATUS_STARTING },
{ "operating_1a", VEHICLE_STATUS_OPERATING_1A },
{ "stopping_1b", VEHICLE_STATUS_STOPPING_1B },
{ "unloading_passengers_1c", VEHICLE_STATUS_UNLOADING_PASSENGERS_1C },
{ "stopped_by_block_brake", VEHICLE_STATUS_STOPPED_BY_BLOCK_BRAKES },
});
class ScVehicle : public ScEntity
{
public:
ScVehicle(uint16_t id)
: ScEntity(id)
{
}
static void Register(duk_context* ctx)
{
dukglue_set_base_class<ScEntity, ScVehicle>(ctx);
dukglue_register_property(ctx, &ScVehicle::ride_get, &ScVehicle::ride_set, "ride");
dukglue_register_property(ctx, &ScVehicle::rideObject_get, &ScVehicle::rideObject_set, "rideObject");
dukglue_register_property(ctx, &ScVehicle::vehicleObject_get, &ScVehicle::vehicleObject_set, "vehicleObject");
dukglue_register_property(ctx, &ScVehicle::spriteType_get, &ScVehicle::spriteType_set, "spriteType");
dukglue_register_property(ctx, &ScVehicle::numSeats_get, &ScVehicle::numSeats_set, "numSeats");
dukglue_register_property(ctx, &ScVehicle::nextCarOnTrain_get, &ScVehicle::nextCarOnTrain_set, "nextCarOnTrain");
dukglue_register_property(
ctx, &ScVehicle::previousCarOnRide_get, &ScVehicle::previousCarOnRide_set, "previousCarOnRide");
dukglue_register_property(ctx, &ScVehicle::nextCarOnRide_get, &ScVehicle::nextCarOnRide_set, "nextCarOnRide");
dukglue_register_property(ctx, &ScVehicle::currentStation_get, &ScVehicle::currentStation_set, "currentStation");
dukglue_register_property(ctx, &ScVehicle::mass_get, &ScVehicle::mass_set, "mass");
dukglue_register_property(ctx, &ScVehicle::acceleration_get, &ScVehicle::acceleration_set, "acceleration");
dukglue_register_property(ctx, &ScVehicle::velocity_get, &ScVehicle::velocity_set, "velocity");
dukglue_register_property(ctx, &ScVehicle::bankRotation_get, &ScVehicle::bankRotation_set, "bankRotation");
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::speed_get, &ScVehicle::speed_set, "speed");
dukglue_register_property(
ctx, &ScVehicle::poweredAcceleration_get, &ScVehicle::poweredAcceleration_set, "poweredAcceleration");
dukglue_register_property(ctx, &ScVehicle::status_get, &ScVehicle::status_set, "status");
dukglue_register_property(ctx, &ScVehicle::peeps_get, nullptr, "peeps");
}
private:
Vehicle* GetVehicle() const
{
return get_sprite(_id)->generic.As<Vehicle>();
}
uint8_t rideObject_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->ride_subtype : 0;
}
void rideObject_set(uint8_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->ride_subtype = value;
}
}
uint8_t vehicleObject_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->vehicle_type : 0;
}
void vehicleObject_set(uint8_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->vehicle_type = value;
}
}
uint8_t spriteType_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->vehicle_sprite_type : 0;
}
void spriteType_set(uint8_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->vehicle_sprite_type = value;
}
}
ride_id_t ride_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->ride : 0;
}
void ride_set(ride_id_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->ride = value;
}
}
uint8_t numSeats_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->num_seats & VEHICLE_SEAT_NUM_MASK : 0;
}
void numSeats_set(uint8_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->num_seats &= ~VEHICLE_SEAT_NUM_MASK;
vehicle->num_seats |= value & VEHICLE_SEAT_NUM_MASK;
}
}
DukValue nextCarOnTrain_get() const
{
auto ctx = GetContext()->GetScriptEngine().GetContext();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
if (vehicle->next_vehicle_on_train != SPRITE_INDEX_NULL)
{
return ToDuk<int32_t>(ctx, vehicle->next_vehicle_on_train);
}
}
return ToDuk(ctx, nullptr);
}
void nextCarOnTrain_set(DukValue value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
if (value.type() == DukValue::Type::NUMBER)
{
vehicle->next_vehicle_on_train = static_cast<uint16_t>(value.as_int());
}
else
{
vehicle->next_vehicle_on_train = SPRITE_INDEX_NULL;
}
}
}
uint16_t previousCarOnRide_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->prev_vehicle_on_ride : 0;
}
void previousCarOnRide_set(uint16_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->prev_vehicle_on_ride = value;
}
}
uint16_t nextCarOnRide_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->next_vehicle_on_ride : 0;
}
void nextCarOnRide_set(uint16_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->next_vehicle_on_ride = value;
}
}
StationIndex currentStation_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->current_station : 0;
}
void currentStation_set(StationIndex value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->current_station = value;
}
}
uint16_t mass_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->mass : 0;
}
void mass_set(uint16_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->mass = value;
}
}
int32_t acceleration_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->acceleration : 0;
}
void acceleration_set(int32_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->acceleration = value;
}
}
int32_t velocity_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->velocity : 0;
}
void velocity_set(int32_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->velocity = value;
}
}
uint8_t bankRotation_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->bank_rotation : 0;
}
void bankRotation_set(uint8_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->bank_rotation = value;
}
}
DukValue colours_get() const
{
auto ctx = GetContext()->GetScriptEngine().GetContext();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
VehicleColour colours;
colours.Body = vehicle->colours.body_colour;
colours.Trim = vehicle->colours.trim_colour;
colours.Ternary = vehicle->colours_extended;
return ToDuk<VehicleColour>(ctx, colours);
}
return ToDuk(ctx, nullptr);
}
void colours_set(const DukValue& value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
auto colours = FromDuk<VehicleColour>(value);
vehicle->colours.body_colour = colours.Body;
vehicle->colours.trim_colour = colours.Trim;
vehicle->colours_extended = colours.Ternary;
}
}
DukValue trackLocation_get() const
{
auto ctx = GetContext()->GetScriptEngine().GetContext();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
auto coords = CoordsXYZD(vehicle->TrackLocation, vehicle->track_direction & 3);
return ToDuk<CoordsXYZD>(ctx, coords);
}
return ToDuk(ctx, nullptr);
}
void trackLocation_set(const DukValue& value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
auto coords = FromDuk<CoordsXYZD>(value);
vehicle->TrackLocation = CoordsXYZ(coords.x, coords.y, coords.z);
vehicle->track_direction &= ~3;
vehicle->track_direction |= coords.direction & 3;
}
}
uint8_t speed_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->speed : 0;
}
void speed_set(uint8_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->speed = value;
}
}
uint8_t poweredAcceleration_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->powered_acceleration : 0;
}
void poweredAcceleration_set(uint8_t value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->powered_acceleration = value;
}
}
std::string status_get() const
{
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
return std::string(VehicleStatusMap[vehicle->status]);
}
return {};
}
void status_set(const std::string& value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
vehicle->status = VehicleStatusMap[value];
}
}
std::vector<DukValue> peeps_get() const
{
auto ctx = GetContext()->GetScriptEngine().GetContext();
std::vector<DukValue> result;
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
size_t len = 0;
for (size_t i = 0; i < std::size(vehicle->peep); i++)
{
auto peep = vehicle->peep[i];
if (peep == SPRITE_INDEX_NULL)
{
result.push_back(ToDuk(ctx, nullptr));
}
else
{
result.push_back(ToDuk<int32_t>(ctx, peep));
len = i + 1;
}
}
result.resize(len);
}
return result;
}
};
static const DukEnumMap<uint32_t> PeepFlagMap({
{ "leavingPark", PEEP_FLAGS_LEAVING_PARK },
{ "slowWalk", PEEP_FLAGS_SLOW_WALK },

View File

@ -163,7 +163,7 @@ namespace OpenRCT2::Scripting
}
else
{
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScEntity>(carId)));
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScVehicle>(carId)));
carId = car->vehicle.next_vehicle_on_train;
}
}
@ -197,6 +197,8 @@ namespace OpenRCT2::Scripting
auto spriteId = sprite->generic.sprite_index;
switch (sprite->generic.sprite_identifier)
{
case SPRITE_IDENTIFIER_VEHICLE:
return GetObjectAsDukValue(_context, std::make_shared<ScVehicle>(spriteId));
case SPRITE_IDENTIFIER_PEEP:
if (sprite->peep.type == PEEP_TYPE_STAFF)
return GetObjectAsDukValue(_context, std::make_shared<ScStaff>(spriteId));

View File

@ -390,6 +390,7 @@ void ScriptEngine::Initialise()
ScTile::Register(ctx);
ScTileElement::Register(ctx);
ScEntity::Register(ctx);
ScVehicle::Register(ctx);
ScPeep::Register(ctx);
ScGuest::Register(ctx);
ScStaff::Register(ctx);