1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-27 00:34:46 +01:00

Improve some of the map APIs

This commit is contained in:
Ted John
2020-03-01 12:44:36 +00:00
parent 4e12c9541e
commit 971c6e201d
5 changed files with 278 additions and 50 deletions

View File

@@ -151,7 +151,7 @@ declare global {
}
type TileElementType =
"surface" | "footpath" | "track" | "small_scenery" | "entrance" | "large_scenery" | "banner";
"surface" | "footpath" | "track" | "small_scenery" | "wall" | "entrance" | "large_scenery" | "banner";
interface BaseTileElement {
type: TileElementType;
@@ -276,52 +276,125 @@ declare global {
removeElement(index: number): void;
}
/**
* Represents the definition of a loaded object (.DAT or .json) such a ride type or scenery item.
*/
interface Object {
/**
* The unique name identifier of the object, e.g. "BURGB ".
* This may have trailing spaces if the name is shorter than 8 characters.
*/
readonly identifier: string;
/**
* The name in the user's current language.
*/
readonly name: string;
}
/**
* Represents the object definition of a ride or stall.
*/
interface RideObject extends Object {
/**
* The description of the ride / stall in the player's current language.
*/
readonly description: string;
/**
* A text description describing the capacity of the ride in the player's current language.
*/
readonly capacity: string;
}
/**
* Represents a ride or stall within the park.
*/
interface Ride {
/**
* The object metadata for this ride.
*/
readonly object: RideObject;
/**
* The unique ID / index of the ride.
*/
readonly id: number;
/**
* The type of the ride represented as the internal built-in ride type ID.
*/
type: number;
/**
* The generated or custom name of the ride.
*/
name: string;
/**
* The excitement metric of the ride represented as a 2 decimal point fixed integer.
* For example, `652` equates to `6.52`.
*/
excitement: number;
/**
* The intensity metric of the ride represented as a 2 decimal point fixed integer.
* For example, `652` equates to `6.52`.
*/
intensity: number;
/**
* The nausea metric of the ride represented as a 2 decimal point fixed integer.
* For example, `652` equates to `6.52`.
*/
nausea: number;
/**
* The total number of customers the ride has served since it was built.
*/
totalCustomers: number;
}
type ThingType =
"car" | "duck" | "peep";
/**
* Represents an object "thing" on the map that can typically moves and has a sub-tile coordinate.
*/
interface Thing {
/**
* The type of thing, e.g. car, duck, litter, or peep.
*/
readonly type: ThingType;
/**
* The x-coordinate of the thing in game units.
*/
x: number;
/**
* The y-coordinate of the thing in game units.
*/
y: number;
/**
* The z-coordinate of the thing in game units.
*/
z: number;
asPeep(): Thing | null;
}
/**
* Represents a guest or staff member.
*/
interface Peep extends Thing {
/**
* Colour of the peep's t-shirt.
*/
tshirt: number;
/**
* Colour of the peep's trousers.
*/
trousers: number;
}
interface GameMap {
readonly size: { x: number; y: number; };
readonly rides: number;
readonly things: number;
readonly size: Coord2;
readonly numRides: number;
readonly numThings: number;
readonly rides: Ride[];
getRide(id: number): Ride;
getTile(x: number, y: number): Tile;
getThing(id: number): Thing;
getAllThings(type: ThingType);
}
type ParkMessageType =

View File

@@ -43,16 +43,27 @@ namespace OpenRCT2::Scripting
return DukValue::take_from_stack(ctx);
}
int32_t rides_get()
int32_t numRides_get()
{
return static_cast<int32_t>(GetRideManager().size());
}
int32_t things_get()
int32_t numThings_get()
{
return MAX_SPRITES;
}
std::vector<std::shared_ptr<ScRide>> rides_get()
{
std::vector<std::shared_ptr<ScRide>> result;
auto rideManager = GetRideManager();
for (const auto& ride : rideManager)
{
result.push_back(std::make_shared<ScRide>(ride.id));
}
return result;
}
std::shared_ptr<ScRide> getRide(int32_t id)
{
auto rideManager = GetRideManager();
@@ -61,10 +72,10 @@ namespace OpenRCT2::Scripting
auto ride = rideManager[static_cast<ride_id_t>(id)];
if (ride != nullptr)
{
return std::make_shared<ScRide>(ride);
return std::make_shared<ScRide>(ride->id);
}
}
return nullptr;
return {};
}
std::shared_ptr<ScTile> getTile(int32_t x, int32_t y)
@@ -77,23 +88,75 @@ namespace OpenRCT2::Scripting
{
if (id >= 0 && id < MAX_SPRITES)
{
auto sprite = get_sprite(id);
auto spriteId = static_cast<uint16_t>(id);
auto sprite = get_sprite(spriteId);
if (sprite != nullptr && sprite->generic.sprite_identifier != SPRITE_IDENTIFIER_NULL)
{
return std::make_shared<ScThing>(sprite);
return std::make_shared<ScThing>(spriteId);
}
}
return nullptr;
}
std::vector<std::shared_ptr<ScThing>> getAllThings(const std::string& type)
{
SPRITE_LIST targetList{};
uint8_t targetType{};
if (type == "balloon")
{
targetList = SPRITE_LIST_MISC;
targetType = SPRITE_MISC_BALLOON;
}
if (type == "car")
{
targetList = SPRITE_LIST_VEHICLE;
}
else if (type == "litter")
{
targetList = SPRITE_LIST_LITTER;
}
else if (type == "duck")
{
targetList = SPRITE_LIST_MISC;
targetType = SPRITE_MISC_DUCK;
}
else if (type == "peep")
{
targetList = SPRITE_LIST_PEEP;
}
else
{
duk_error(_context, DUK_ERR_ERROR, "Invalid thing type.");
}
std::vector<std::shared_ptr<ScThing>> result;
auto spriteId = gSpriteListHead[targetList];
while (spriteId != SPRITE_INDEX_NULL)
{
auto sprite = get_sprite(spriteId);
if (sprite != nullptr)
{
// Only the misc list checks the type property
if (targetList != SPRITE_LIST_MISC || sprite->generic.type == targetType)
{
result.push_back(std::make_shared<ScThing>(spriteId));
}
spriteId = sprite->generic.next;
}
}
return result;
}
static void Register(duk_context* ctx)
{
dukglue_register_property(ctx, &ScMap::size_get, nullptr, "size");
dukglue_register_property(ctx, &ScMap::numRides_get, nullptr, "numRides");
dukglue_register_property(ctx, &ScMap::numThings_get, nullptr, "numThings");
dukglue_register_property(ctx, &ScMap::rides_get, nullptr, "rides");
dukglue_register_property(ctx, &ScMap::things_get, nullptr, "things");
dukglue_register_method(ctx, &ScMap::getRide, "getRide");
dukglue_register_method(ctx, &ScMap::getTile, "getTile");
dukglue_register_method(ctx, &ScMap::getThing, "getThing");
dukglue_register_method(ctx, &ScMap::getAllThings, "getAllThings");
}
};
} // namespace OpenRCT2::Scripting

View File

@@ -93,8 +93,9 @@ namespace OpenRCT2::Scripting
}
news_item_add_to_queue_raw(type, text.c_str(), static_cast<uint32_t>(-1));
}
catch (const std::exception&)
catch (const DukException&)
{
duk_error(message.context(), DUK_ERR_ERROR, "Invalid message argument.");
}
}

View File

@@ -22,12 +22,12 @@ namespace OpenRCT2::Scripting
class ScRideObject
{
private:
rct_ride_entry* _entry;
rct_ride_entry* _entry{};
public:
ScRideObject(rct_ride_entry* entry)
: _entry(entry)
{
_entry = entry;
}
static void Register(duk_context* ctx)
@@ -83,84 +83,121 @@ namespace OpenRCT2::Scripting
class ScRide
{
private:
Ride* _ride;
ride_id_t _rideId = RIDE_ID_NULL;
public:
ScRide(Ride* ride)
: _ride(ride)
ScRide(ride_id_t rideId)
: _rideId(rideId)
{
}
private:
int32_t id_get()
{
return _ride->id;
return _rideId;
}
std::shared_ptr<ScRideObject> object_get()
{
auto rideEntry = _ride->GetRideEntry();
if (rideEntry != nullptr)
auto ride = GetRide();
if (ride != nullptr)
{
return std::make_shared<ScRideObject>(rideEntry);
auto rideEntry = ride->GetRideEntry();
if (rideEntry != nullptr)
{
return std::make_shared<ScRideObject>(rideEntry);
}
}
return nullptr;
}
int32_t type_get()
{
return _ride->type;
auto ride = GetRide();
return ride != nullptr ? ride->type : 0;
}
std::string name_get()
{
return _ride->GetName();
auto ride = GetRide();
return ride != nullptr ? ride->GetName() : std::string();
}
void name_set(std::string value)
{
ThrowIfGameStateNotMutable();
_ride->custom_name = value;
auto ride = GetRide();
if (ride != nullptr)
{
ride->custom_name = value;
}
}
int32_t excitement_get()
{
return _ride->excitement;
auto ride = GetRide();
return ride != nullptr ? ride->excitement : 0;
}
void excitement_set(int32_t value)
{
ThrowIfGameStateNotMutable();
_ride->excitement = value;
auto ride = GetRide();
if (ride != nullptr)
{
ride->excitement = value;
}
}
int32_t intensity_get()
{
return _ride->intensity;
auto ride = GetRide();
return ride != nullptr ? ride->intensity : 0;
}
void intensity_set(int32_t value)
{
ThrowIfGameStateNotMutable();
_ride->intensity = value;
auto ride = GetRide();
if (ride != nullptr)
{
ride->intensity = value;
}
}
int32_t nausea_get()
{
return _ride->nausea;
auto ride = GetRide();
return ride != nullptr ? ride->nausea : 0;
}
void nausea_set(int32_t value)
{
ThrowIfGameStateNotMutable();
_ride->nausea = value;
auto ride = GetRide();
if (ride != nullptr)
{
ride->nausea = value;
}
}
int32_t totalCustomers_get()
{
return _ride->total_customers;
auto ride = GetRide();
return ride != nullptr ? ride->total_customers : 0;
}
void totalCustomers_set(int32_t value)
{
ThrowIfGameStateNotMutable();
_ride->total_customers = value;
auto ride = GetRide();
if (ride != nullptr)
{
ride->total_customers = value;
}
}
Ride* GetRide()
{
return get_ride(_rideId);
}
public:
static void Register(duk_context* ctx)
{
dukglue_register_property(ctx, &ScRide::id_get, nullptr, "id");

View File

@@ -21,19 +21,38 @@ namespace OpenRCT2::Scripting
class ScThing
{
private:
rct_sprite* _sprite;
uint16_t _id = SPRITE_INDEX_NULL;
public:
ScThing(rct_sprite* sprite)
: _sprite(sprite)
ScThing(uint16_t id)
: _id(id)
{
}
private:
std::string type_get()
{
if (_sprite->generic.sprite_identifier == SPRITE_IDENTIFIER_PEEP)
auto thing = GetThing();
if (thing != nullptr)
{
return "peep";
switch (thing->sprite_identifier)
{
case SPRITE_IDENTIFIER_VEHICLE:
return "car";
case SPRITE_IDENTIFIER_PEEP:
return "peep";
case SPRITE_IDENTIFIER_MISC:
switch (thing->type)
{
case SPRITE_MISC_BALLOON:
return "balloon";
case SPRITE_MISC_DUCK:
return "duck";
}
break;
case SPRITE_IDENTIFIER_LITTER:
return "litter";
}
}
return "unknown";
}
@@ -41,58 +60,93 @@ namespace OpenRCT2::Scripting
// x getter and setter
int32_t x_get()
{
return _sprite->generic.x;
auto thing = GetThing();
return thing != nullptr ? thing->x : 0;
}
void x_set(int32_t value)
{
ThrowIfGameStateNotMutable();
sprite_move(value, _sprite->generic.y, _sprite->generic.z, &_sprite->generic);
auto thing = GetThing();
if (thing != nullptr)
{
sprite_move(value, thing->y, thing->z, thing);
}
}
// y getter and setter
int32_t y_get()
{
return _sprite->generic.y;
auto thing = GetThing();
return thing != nullptr ? thing->y : 0;
}
void y_set(int32_t value)
{
ThrowIfGameStateNotMutable();
sprite_move(_sprite->generic.x, value, _sprite->generic.z, &_sprite->generic);
auto thing = GetThing();
if (thing != nullptr)
{
sprite_move(thing->x, value, thing->z, thing);
}
}
// z getter and setter
int16_t z_get()
{
return _sprite->generic.z;
auto thing = GetThing();
return thing != nullptr ? thing->z : 0;
}
void z_set(int16_t value)
{
ThrowIfGameStateNotMutable();
sprite_move(_sprite->generic.x, _sprite->generic.y, value, &_sprite->generic);
auto thing = GetThing();
if (thing != nullptr)
{
sprite_move(thing->x, thing->y, value, thing);
}
}
uint8_t tshirtColour_get()
{
return _sprite->peep.tshirt_colour;
auto peep = GetPeep();
return peep != nullptr ? peep->tshirt_colour : 0;
}
void tshirtColour_set(uint8_t value)
{
ThrowIfGameStateNotMutable();
_sprite->peep.tshirt_colour = value;
auto peep = GetPeep();
if (peep != nullptr)
{
peep->tshirt_colour = value;
}
}
uint8_t trousersColour_get()
{
return _sprite->peep.trousers_colour;
auto peep = GetPeep();
return peep != nullptr ? peep->trousers_colour : 0;
}
void trousersColour_set(uint8_t value)
{
ThrowIfGameStateNotMutable();
_sprite->peep.trousers_colour = value;
auto peep = GetPeep();
if (peep != nullptr)
{
peep->trousers_colour = value;
}
}
SpriteBase* GetThing()
{
return &get_sprite(_id)->generic;
}
Peep* GetPeep()
{
return get_sprite(_id)->AsPeep();
}
public:
static void Register(duk_context* ctx)
{
dukglue_register_constructor<ScThing, rct_sprite*>(ctx, "Thing");
dukglue_register_property(ctx, &ScThing::type_get, nullptr, "type");
dukglue_register_property(ctx, &ScThing::x_get, &ScThing::x_set, "x");
dukglue_register_property(ctx, &ScThing::y_get, &ScThing::y_set, "y");