diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 385c30cbbd..28d8dba81b 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,6 +1,7 @@ 0.4.15 (in development) ------------------------------------------------------------------------ - Feature: [#15642] Track design placement can now use contruction modifier keys (ctrl/shift). +- Feature: [#21521] [Plugin] Add hook 'park.guest.softcap.calculate' called before calculating the soft guest cap. - Change: [#22596] Land ownership fixes described by .parkpatch files are now only considered on scenarios. - Fix: [#2614] The colour tab of the ride window does not hide invisible cars (original bug). - Fix: [#15406] Tunnels on steep Side-Friction track are drawn too low. diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index f5f0767173..1011d849a0 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -515,6 +515,7 @@ declare global { subscribe(hook: "network.chat", callback: (e: NetworkChatEventArgs) => void): IDisposable; subscribe(hook: "network.join", callback: (e: NetworkEventArgs) => void): IDisposable; subscribe(hook: "network.leave", callback: (e: NetworkEventArgs) => void): IDisposable; + subscribe(hook: "park.guest.softcap.calculate", callback: (e: ParkCalculateGuestCapArgs) => void): IDisposable; subscribe(hook: "ride.ratings.calculate", callback: (e: RideRatingsCalculateArgs) => void): IDisposable; subscribe(hook: "vehicle.crash", callback: (e: VehicleCrashArgs) => void): IDisposable; @@ -640,6 +641,7 @@ declare global { "network.chat" | "network.join" | "network.leave" | + "park.guest.softcap.calculate" | "ride.ratings.calculate" | "vehicle.crash"; @@ -1415,6 +1417,14 @@ declare global { readonly crashIntoType: VehicleCrashIntoType; } + /** + * The 'suggestedGuestMaximum' field in this interface can be used to override + * the park's suggested guest cap. + */ + interface ParkCalculateGuestCapArgs { + suggestedGuestMaximum: number; + } + /** * APIs for the in-game date. */ diff --git a/src/openrct2/scripting/HookEngine.cpp b/src/openrct2/scripting/HookEngine.cpp index a86f538730..77ead25f9b 100644 --- a/src/openrct2/scripting/HookEngine.cpp +++ b/src/openrct2/scripting/HookEngine.cpp @@ -34,6 +34,7 @@ static const EnumMap HooksLookupTable({ { "map.change", HOOK_TYPE::MAP_CHANGE }, { "map.changed", HOOK_TYPE::MAP_CHANGED }, { "map.save", HOOK_TYPE::MAP_SAVE }, + { "park.guest.softcap.calculate", HOOK_TYPE::PARK_CALCULATE_GUEST_CAP }, }); HOOK_TYPE OpenRCT2::Scripting::GetHookType(const std::string& name) diff --git a/src/openrct2/scripting/HookEngine.h b/src/openrct2/scripting/HookEngine.h index 3b78481f25..839691aedb 100644 --- a/src/openrct2/scripting/HookEngine.h +++ b/src/openrct2/scripting/HookEngine.h @@ -42,6 +42,7 @@ namespace OpenRCT2::Scripting MAP_CHANGE, MAP_CHANGED, MAP_SAVE, + PARK_CALCULATE_GUEST_CAP, COUNT, UNDEFINED = -1, }; diff --git a/src/openrct2/scripting/ScriptEngine.h b/src/openrct2/scripting/ScriptEngine.h index c5f8d41d83..12cc0d24a8 100644 --- a/src/openrct2/scripting/ScriptEngine.h +++ b/src/openrct2/scripting/ScriptEngine.h @@ -46,7 +46,7 @@ namespace OpenRCT2 namespace OpenRCT2::Scripting { - static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 98; + static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 99; // Versions marking breaking changes. static constexpr int32_t API_VERSION_33_PEEP_DEPRECATION = 33; diff --git a/src/openrct2/world/Park.cpp b/src/openrct2/world/Park.cpp index 15c48d3a35..8065b78e1c 100644 --- a/src/openrct2/world/Park.cpp +++ b/src/openrct2/world/Park.cpp @@ -33,6 +33,7 @@ #include "../ride/RideData.h" #include "../ride/ShopItem.h" #include "../scenario/Scenario.h" +#include "../scripting/ScriptEngine.h" #include "../util/Util.h" #include "../windows/Intent.h" #include "Entrance.h" @@ -43,6 +44,7 @@ #include using namespace OpenRCT2; +using namespace OpenRCT2::Scripting; namespace OpenRCT2::Park { @@ -157,6 +159,21 @@ namespace OpenRCT2::Park } suggestedMaxGuests = std::min(suggestedMaxGuests, 65535); + +#ifdef ENABLE_SCRIPTING + auto& hookEngine = GetContext()->GetScriptEngine().GetHookEngine(); + if (hookEngine.HasSubscriptions(HOOK_TYPE::PARK_CALCULATE_GUEST_CAP)) + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto obj = DukObject(ctx); + obj.Set("suggestedGuestMaximum", suggestedMaxGuests); + auto e = obj.Take(); + hookEngine.Call(HOOK_TYPE::PARK_CALCULATE_GUEST_CAP, e, true); + + suggestedMaxGuests = AsOrDefault(e["suggestedGuestMaximum"], static_cast(suggestedMaxGuests)); + suggestedMaxGuests = std::clamp(suggestedMaxGuests, 0, UINT16_MAX); + } +#endif return suggestedMaxGuests; }