Merge pull request #16731 from IntelOrca/plugin/patrol-areas

Implement #13620: [Plugin] Add support for patrol areas to Staff
This commit is contained in:
Ted John 2022-03-13 19:52:05 +00:00 committed by GitHub
commit 9ef7a4c13b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 204 additions and 1 deletions

View File

@ -15,6 +15,7 @@
- Feature: [#16097] The Looping Roller Coaster can now draw all elements from the LIM Launched Roller Coaster.
- Feature: [#16132, #16389] The Corkscrew, Twister and Vertical Drop Roller Coasters can now draw inline twists.
- Feature: [#16144] [Plugin] Add ImageManager to API.
- Feature: [#16731] [Plugin] New API for fetching and manipulating a staff member's patrol area.
- Improved: [#3517] Cheats are now saved with the park.
- Improved: [#10150] Ride stations are now properly checked if theyre sheltered.
- Improved: [#10664, #16072] Visibility status can be modified directly in the Tile Inspector's list.

View File

@ -1511,10 +1511,47 @@ declare global {
* The enabled jobs the staff can do, e.g. sweep litter, water plants, inspect rides etc.
*/
orders: number;
/**
* Gets the patrol area for the staff member.
*/
readonly patrolArea: PatrolArea;
}
type StaffType = "handyman" | "mechanic" | "security" | "entertainer";
interface PatrolArea {
/**
* Gets or sets the map coodinates for all individual tiles in the staff member's patrol area.
*
* Note: fetching all the staff member's patrol area tiles can degrade performance.
*/
tiles: CoordsXY[];
/**
* Clears all tiles from the staff member's patrol area.
*/
clear(): void;
/**
* Adds the given array of coordinates or a map range to the staff member's patrol area.
* @param coords An array of map coordinates, or a map range.
*/
add(coords: CoordsXY[] | MapRange): void;
/**
* Removes the given array of coordinates or a map range from the staff member's patrol area.
* @param coords An array of map coordinates, or a map range.
*/
remove(coords: CoordsXY[] | MapRange): void;
/**
* Checks whether a single coordinate is within the staff member's patrol area.
* @param coords An map coordinate.
*/
contains(coord: CoordsXY): boolean;
}
/**
* Represents litter entity.
*/

View File

@ -65,7 +65,6 @@ public:
void SetPatrolArea(const CoordsXY& coords, bool value);
void SetPatrolArea(const MapRange& range, bool value);
bool HasPatrolArea() const;
std::vector<TileCoordsXY> GetPatrolArea();
void SetPatrolArea(const std::vector<TileCoordsXY>& area);
private:

View File

@ -334,6 +334,14 @@ namespace OpenRCT2::Scripting
return result;
}
template<> MapRange inline FromDuk(const DukValue& d)
{
MapRange range;
range.Point1 = FromDuk<CoordsXY>(d["leftTop"]);
range.Point2 = FromDuk<CoordsXY>(d["rightBottom"]);
return range.Normalise();
}
template<> DukValue inline ToDuk(duk_context* ctx, const CoordsXY& coords)
{
DukObject dukCoords(ctx);

View File

@ -421,6 +421,7 @@ void ScriptEngine::Initialise()
# endif
ScScenario::Register(ctx);
ScScenarioObjective::Register(ctx);
ScPatrolArea::Register(ctx);
ScStaff::Register(ctx);
dukglue_register_global(ctx, std::make_shared<ScCheats>(), "cheats");

View File

@ -11,6 +11,7 @@
# include "ScStaff.hpp"
# include "../../../entity/PatrolArea.h"
# include "../../../entity/Staff.h"
namespace OpenRCT2::Scripting
@ -26,6 +27,7 @@ namespace OpenRCT2::Scripting
dukglue_register_property(ctx, &ScStaff::staffType_get, &ScStaff::staffType_set, "staffType");
dukglue_register_property(ctx, &ScStaff::colour_get, &ScStaff::colour_set, "colour");
dukglue_register_property(ctx, &ScStaff::costume_get, &ScStaff::costume_set, "costume");
dukglue_register_property(ctx, &ScStaff::patrolArea_get, nullptr, "patrolArea");
dukglue_register_property(ctx, &ScStaff::orders_get, &ScStaff::orders_set, "orders");
}
@ -122,6 +124,11 @@ namespace OpenRCT2::Scripting
}
}
std::shared_ptr<ScPatrolArea> ScStaff::patrolArea_get() const
{
return std::make_shared<ScPatrolArea>(_id);
}
uint8_t ScStaff::orders_get() const
{
auto peep = GetStaff();
@ -138,6 +145,131 @@ namespace OpenRCT2::Scripting
}
}
ScPatrolArea::ScPatrolArea(EntityId id)
: _staffId(id)
{
}
void ScPatrolArea::Register(duk_context* ctx)
{
dukglue_register_property(ctx, &ScPatrolArea::tiles_get, &ScPatrolArea::tiles_set, "tiles");
dukglue_register_method(ctx, &ScPatrolArea::clear, "clear");
dukglue_register_method(ctx, &ScPatrolArea::add, "add");
dukglue_register_method(ctx, &ScPatrolArea::remove, "remove");
dukglue_register_method(ctx, &ScPatrolArea::contains, "contains");
}
Staff* ScPatrolArea::GetStaff() const
{
return GetEntity<Staff>(_staffId);
}
void ScPatrolArea::ModifyArea(const DukValue& coordsOrRange, bool value) const
{
auto staff = GetStaff();
if (staff != nullptr)
{
if (coordsOrRange.is_array())
{
auto dukCoords = coordsOrRange.as_array();
for (const auto& dukCoord : dukCoords)
{
auto coord = FromDuk<CoordsXY>(dukCoord);
staff->SetPatrolArea(coord, value);
map_invalidate_tile_full(coord);
}
}
else
{
auto mapRange = FromDuk<MapRange>(coordsOrRange);
for (int32_t y = mapRange.GetTop(); y <= mapRange.GetBottom(); y += COORDS_XY_STEP)
{
for (int32_t x = mapRange.GetLeft(); x <= mapRange.GetRight(); x += COORDS_XY_STEP)
{
CoordsXY coord(x, y);
staff->SetPatrolArea(coord, value);
map_invalidate_tile_full(coord);
}
}
}
UpdateConsolidatedPatrolAreas();
}
}
DukValue ScPatrolArea::tiles_get() const
{
auto ctx = GetContext()->GetScriptEngine().GetContext();
duk_push_array(ctx);
auto staff = GetStaff();
if (staff != nullptr && staff->PatrolInfo != nullptr)
{
auto tiles = staff->PatrolInfo->ToVector();
duk_uarridx_t index = 0;
for (const auto& tile : tiles)
{
auto dukCoord = ToDuk(ctx, tile.ToCoordsXY());
dukCoord.push();
duk_put_prop_index(ctx, -2, index);
index++;
}
}
return DukValue::take_from_stack(ctx, -1);
}
void ScPatrolArea::tiles_set(const DukValue& value)
{
ThrowIfGameStateNotMutable();
auto staff = GetStaff();
if (staff != nullptr)
{
staff->ClearPatrolArea();
if (value.is_array())
{
ModifyArea(value, true);
}
}
}
void ScPatrolArea::clear()
{
ThrowIfGameStateNotMutable();
auto staff = GetStaff();
if (staff != nullptr)
{
staff->ClearPatrolArea();
UpdateConsolidatedPatrolAreas();
}
}
void ScPatrolArea::add(const DukValue& coordsOrRange)
{
ThrowIfGameStateNotMutable();
ModifyArea(coordsOrRange, true);
}
void ScPatrolArea::remove(const DukValue& coordsOrRange)
{
ThrowIfGameStateNotMutable();
ModifyArea(coordsOrRange, false);
}
bool ScPatrolArea::contains(const DukValue& coord) const
{
auto staff = GetStaff();
if (staff != nullptr)
{
auto pos = FromDuk<CoordsXY>(coord);
return staff->IsLocationInPatrol(pos);
}
return false;
}
} // namespace OpenRCT2::Scripting
#endif

View File

@ -15,6 +15,29 @@
namespace OpenRCT2::Scripting
{
class ScPatrolArea
{
private:
EntityId _staffId;
public:
ScPatrolArea(EntityId id);
static void Register(duk_context* ctx);
private:
Staff* GetStaff() const;
void ModifyArea(const DukValue& coordsOrRange, bool value) const;
DukValue tiles_get() const;
void tiles_set(const DukValue& value);
void clear();
void add(const DukValue& coordsOrRange);
void remove(const DukValue& coordsOrRange);
bool contains(const DukValue& coord) const;
};
class ScStaff : public ScPeep
{
public:
@ -34,6 +57,8 @@ namespace OpenRCT2::Scripting
uint8_t costume_get() const;
void costume_set(uint8_t value);
std::shared_ptr<ScPatrolArea> patrolArea_get() const;
uint8_t orders_get() const;
void orders_set(uint8_t value);
};