1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-20 21:43:06 +01:00

[Plugin API] Feat: Expose staff statistics (#22184)

This commit is contained in:
Arnold Zhou
2024-07-25 09:10:34 +10:00
committed by GitHub
parent 725f2c9576
commit a749698566
7 changed files with 346 additions and 5 deletions

View File

@@ -3,6 +3,7 @@
- Feature: [#20831] The ride selection window now shows object authors if debugging tools are active.
- Feature: [#20832] The ride music tab now shows a track listing for the current music style.
- Feature: [#22172] [Plugin] Expose ride satisfaction ratings to the plugin API.
- Feature: [#22184] [Plugin] Expose staff statistics to the plugin API.
- Feature: [#22213] [Plugin] Allow plugins to focus on textboxes in custom windows.
- Feature: [#22301] Loading save games or scenarios now indicates loading progress.
- Feature: [OpenMusic#54] Added Progressive ride music style (feat. Approaching Nirvana).

View File

@@ -3285,7 +3285,7 @@ declare global {
/**
* Represents a staff member.
*/
interface Staff extends Peep {
interface BaseStaff extends Peep {
/**
* The type of staff member, e.g. handyman, mechanic.
*/
@@ -3344,6 +3344,68 @@ declare global {
type StaffType = "handyman" | "mechanic" | "security" | "entertainer";
type Staff = Handyman | Mechanic | Security | Entertainer;
/**
* Represents a handyman.
*/
interface Handyman extends BaseStaff {
staffType: "handyman";
/**
* The number of lawns mown by the handyman.
*/
readonly lawnsMown: number;
/**
* The number of gardens watered by the handyman.
*/
readonly gardensWatered: number;
/**
* The number of litter swept by the handyman.
*/
readonly litterSwept: number;
/**
* The number of bins emptied by the handyman.
*/
readonly binsEmptied: number;
}
/**
* Represents a mechanic.
*/
interface Mechanic extends BaseStaff {
staffType: "mechanic";
/**
* The number of rides fixed by the mechanic.
*/
readonly ridesFixed: number;
/**
* The number of inspections performed by the mechanic.
*/
readonly ridesInspected: number;
}
/**
* Represents a security guard.
*/
interface Security extends BaseStaff {
staffType: "security";
/**
* The number of vandals stopped by the security guard.
*/
readonly vandalsStopped: number;
}
interface Entertainer extends BaseStaff {
staffType: "entertainer";
}
interface PatrolArea {
/**
* Gets or sets the map coodinates for all individual tiles in the staff member's patrol area.

View File

@@ -450,6 +450,9 @@ void ScriptEngine::Initialise()
ScScenarioObjective::Register(ctx);
ScPatrolArea::Register(ctx);
ScStaff::Register(ctx);
ScHandyman::Register(ctx);
ScMechanic::Register(ctx);
ScSecurity::Register(ctx);
ScPlugin::Register(ctx);
dukglue_register_global(ctx, std::make_shared<ScCheats>(), "cheats");

View File

@@ -46,7 +46,7 @@ namespace OpenRCT2
namespace OpenRCT2::Scripting
{
static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 95;
static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 96;
// Versions marking breaking changes.
static constexpr int32_t API_VERSION_33_PEEP_DEPRECATION = 33;

View File

@@ -438,6 +438,170 @@ namespace OpenRCT2::Scripting
return static_cast<uint8_t>(animationGroup.frame_offsets.size());
}
ScHandyman::ScHandyman(EntityId Id)
: ScStaff(Id)
{
}
void ScHandyman::Register(duk_context* ctx)
{
dukglue_set_base_class<ScStaff, ScHandyman>(ctx);
dukglue_register_property(ctx, &ScHandyman::lawnsMown_get, nullptr, "lawnsMown");
dukglue_register_property(ctx, &ScHandyman::gardensWatered_get, nullptr, "gardensWatered");
dukglue_register_property(ctx, &ScHandyman::litterSwept_get, nullptr, "litterSwept");
dukglue_register_property(ctx, &ScHandyman::binsEmptied_get, nullptr, "binsEmptied");
}
Staff* ScHandyman::GetHandyman() const
{
return ::GetEntity<Staff>(_id);
}
DukValue ScHandyman::lawnsMown_get() const
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto* ctx = scriptEngine.GetContext();
auto peep = GetHandyman();
if (peep != nullptr && peep->AssignedStaffType == StaffType::Handyman)
{
duk_push_uint(ctx, peep->StaffLawnsMown);
}
else
{
duk_push_null(ctx);
}
return DukValue::take_from_stack(ctx);
}
DukValue ScHandyman::gardensWatered_get() const
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto* ctx = scriptEngine.GetContext();
auto peep = GetHandyman();
if (peep != nullptr && peep->AssignedStaffType == StaffType::Handyman)
{
duk_push_uint(ctx, peep->StaffGardensWatered);
}
else
{
duk_push_null(ctx);
}
return DukValue::take_from_stack(ctx);
}
DukValue ScHandyman::litterSwept_get() const
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto* ctx = scriptEngine.GetContext();
auto peep = GetHandyman();
if (peep != nullptr && peep->AssignedStaffType == StaffType::Handyman)
{
duk_push_uint(ctx, peep->StaffLitterSwept);
}
else
{
duk_push_null(ctx);
}
return DukValue::take_from_stack(ctx);
}
DukValue ScHandyman::binsEmptied_get() const
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto* ctx = scriptEngine.GetContext();
auto peep = GetHandyman();
if (peep != nullptr && peep->AssignedStaffType == StaffType::Handyman)
{
duk_push_uint(ctx, peep->StaffBinsEmptied);
}
else
{
duk_push_null(ctx);
}
return DukValue::take_from_stack(ctx);
}
ScMechanic::ScMechanic(EntityId Id)
: ScStaff(Id)
{
}
void ScMechanic::Register(duk_context* ctx)
{
dukglue_set_base_class<ScStaff, ScMechanic>(ctx);
dukglue_register_property(ctx, &ScMechanic::ridesFixed_get, nullptr, "ridesFixed");
dukglue_register_property(ctx, &ScMechanic::ridesInspected_get, nullptr, "ridesInspected");
}
Staff* ScMechanic::GetMechanic() const
{
return ::GetEntity<Staff>(_id);
}
DukValue ScMechanic::ridesFixed_get() const
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto* ctx = scriptEngine.GetContext();
auto peep = GetMechanic();
if (peep != nullptr && peep->AssignedStaffType == StaffType::Mechanic)
{
duk_push_uint(ctx, peep->StaffRidesFixed);
}
else
{
duk_push_null(ctx);
}
return DukValue::take_from_stack(ctx);
}
DukValue ScMechanic::ridesInspected_get() const
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto* ctx = scriptEngine.GetContext();
auto peep = GetMechanic();
if (peep != nullptr && peep->AssignedStaffType == StaffType::Mechanic)
{
duk_push_uint(ctx, peep->StaffRidesInspected);
}
else
{
duk_push_null(ctx);
}
return DukValue::take_from_stack(ctx);
}
ScSecurity::ScSecurity(EntityId Id)
: ScStaff(Id)
{
}
void ScSecurity::Register(duk_context* ctx)
{
dukglue_set_base_class<ScStaff, ScSecurity>(ctx);
dukglue_register_property(ctx, &ScSecurity::vandalsStopped_get, nullptr, "vandalsStopped");
}
Staff* ScSecurity::GetSecurity() const
{
return ::GetEntity<Staff>(_id);
}
DukValue ScSecurity::vandalsStopped_get() const
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto* ctx = scriptEngine.GetContext();
auto peep = GetSecurity();
if (peep != nullptr && peep->AssignedStaffType == StaffType::Security)
{
duk_push_uint(ctx, peep->StaffVandalsStopped);
}
else
{
duk_push_null(ctx);
}
return DukValue::take_from_stack(ctx);
}
ScPatrolArea::ScPatrolArea(EntityId id)
: _staffId(id)
{

View File

@@ -78,6 +78,53 @@ namespace OpenRCT2::Scripting
uint8_t animationLength_get() const;
};
class ScHandyman : public ScStaff
{
public:
ScHandyman(EntityId Id);
static void Register(duk_context* ctx);
private:
Staff* GetHandyman() const;
DukValue lawnsMown_get() const;
DukValue gardensWatered_get() const;
DukValue litterSwept_get() const;
DukValue binsEmptied_get() const;
};
class ScMechanic : public ScStaff
{
public:
ScMechanic(EntityId Id);
static void Register(duk_context* ctx);
private:
Staff* GetMechanic() const;
DukValue ridesFixed_get() const;
DukValue ridesInspected_get() const;
};
class ScSecurity : public ScStaff
{
public:
ScSecurity(EntityId Id);
static void Register(duk_context* ctx);
private:
Staff* GetSecurity() const;
DukValue vandalsStopped_get() const;
};
} // namespace OpenRCT2::Scripting
#endif

View File

@@ -158,7 +158,29 @@ namespace OpenRCT2::Scripting
{
for (auto sprite : EntityList<Staff>())
{
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScStaff>(sprite->Id)));
auto staff = GetEntity<Staff>(sprite->Id);
if (staff != nullptr)
{
switch (staff->AssignedStaffType)
{
case StaffType::Handyman:
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScHandyman>(sprite->Id)));
break;
case StaffType::Mechanic:
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScMechanic>(sprite->Id)));
break;
case StaffType::Security:
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScSecurity>(sprite->Id)));
break;
default:
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScStaff>(sprite->Id)));
break;
}
}
else
{
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScStaff>(sprite->Id)));
}
}
}
else if (type == "crashed_vehicle_particle")
@@ -225,7 +247,29 @@ namespace OpenRCT2::Scripting
{
for (auto sprite : EntityTileList<Staff>(pos))
{
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScStaff>(sprite->Id)));
auto staff = GetEntity<Staff>(sprite->Id);
if (staff != nullptr)
{
switch (staff->AssignedStaffType)
{
case StaffType::Handyman:
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScHandyman>(sprite->Id)));
break;
case StaffType::Mechanic:
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScMechanic>(sprite->Id)));
break;
case StaffType::Security:
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScSecurity>(sprite->Id)));
break;
default:
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScStaff>(sprite->Id)));
break;
}
}
else
{
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScStaff>(sprite->Id)));
}
}
}
else if (type == "crashed_vehicle_particle")
@@ -357,7 +401,27 @@ namespace OpenRCT2::Scripting
case EntityType::Vehicle:
return GetObjectAsDukValue(_context, std::make_shared<ScVehicle>(spriteId));
case EntityType::Staff:
return GetObjectAsDukValue(_context, std::make_shared<ScStaff>(spriteId));
{
auto staff = GetEntity<Staff>(spriteId);
if (staff != nullptr)
{
switch (staff->AssignedStaffType)
{
case StaffType::Handyman:
return GetObjectAsDukValue(_context, std::make_shared<ScHandyman>(spriteId));
case StaffType::Mechanic:
return GetObjectAsDukValue(_context, std::make_shared<ScMechanic>(spriteId));
case StaffType::Security:
return GetObjectAsDukValue(_context, std::make_shared<ScSecurity>(spriteId));
default:
return GetObjectAsDukValue(_context, std::make_shared<ScStaff>(spriteId));
}
}
else
{
return GetObjectAsDukValue(_context, std::make_shared<ScStaff>(spriteId));
}
}
case EntityType::Guest:
return GetObjectAsDukValue(_context, std::make_shared<ScGuest>(spriteId));
case EntityType::Litter: