diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index 64f6859f61..2e6983a6f2 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -53,11 +53,19 @@ declare global { dispose(): void; } + /** + * A coordinate within the game's client screen in pixels. + */ + interface ScreenCoordsXY { + x: number; + y: number; + } + /** * A coordinate within the game. * Each in-game tile is a size of 32x32. */ - interface Coord2 { + interface CoordsXY { x: number; y: number; } @@ -67,10 +75,18 @@ declare global { * Each in-game tile is a size of 32x32. * The z-coordinate raises 16 per land increment. A full-height wall is 32 in height. */ - interface Coord3 extends Coord2 { + interface CoordsXYZ extends CoordsXY { z: number; } + /** + * A rectangular area specified using two coordinates. + */ + interface MapRange { + leftTop: CoordsXY; + rightBottom: CoordsXY; + } + /** * Represents information about the plugin such as type, name, author and version. * It also includes the entry point. @@ -245,7 +261,7 @@ declare global { error?: number; errorTitle?: string; errorMessage?: string; - position?: Coord3; + position?: CoordsXYZ; cost?: number; expenditureType?: ExpenditureType; } @@ -328,7 +344,7 @@ declare global { * APIs for the map. */ interface GameMap { - readonly size: Coord2; + readonly size: CoordsXY; readonly numRides: number; readonly numEntities: number; readonly rides: Ride[]; @@ -710,6 +726,8 @@ declare global { readonly height: number; readonly windows: number; readonly mainViewport: Viewport; + readonly tileSelection: TileSelection; + readonly tool: Tool; getWindow(id: number): Window; getWindow(classification: string): Window; @@ -717,9 +735,79 @@ declare global { closeWindows(classification: string, id?: number): void; closeAllWindows(): void; + /** + * Begins a new tool session. The cursor will change to the style specified by the + * given tool descriptor and cursor events will be provided. + * @param tool The properties and event handlers for the tool. + */ + activateTool(tool: ToolDesc): void; + registerMenuItem(text: string, callback: () => void): void; } + interface TileSelection { + range: MapRange; + tiles: CoordsXY[]; + } + + interface Tool { + id: string; + cursor: CursorType; + + cancel: () => void; + } + + interface ToolEventArgs { + readonly isDown: boolean; + readonly screenCoords: ScreenCoordsXY; + readonly mapCoords?: CoordsXYZ; + readonly tileElementIndex?: number; + readonly entityId?: number; + } + + /** + * Describes the properties and event handlers for a custom tool. + */ + interface ToolDesc { + id: string; + cursor?: CursorType; + + onStart: () => void; + onDown: (e: ToolEventArgs) => void; + onMove: (e: ToolEventArgs) => void; + onUp: (e: ToolEventArgs) => void; + onFinish: () => void; + } + + type CursorType = + "arrow" | + "bench_down" | + "bin_down" | + "blank" | + "cross_hair" | + "diagonal_arrows" | + "dig_down" | + "entrance_down" | + "fence_down" | + "flower_down" | + "fountain_down" | + "hand_closed" | + "hand_open" | + "hand_point" | + "house_down" | + "lamppost_down" | + "paint_down" | + "path_down" | + "picker" | + "statue_down" | + "tree_down" | + "up_arrow" | + "up_down_arrow" | + "volcano_down" | + "walk_down" | + "water_down" | + "zzz"; + /** * Represents the type of a widget, e.g. button or label. */ @@ -822,7 +910,7 @@ declare global { frameBase: number; frameCount?: number; frameDuration?: number; - offset?: Coord2; + offset?: ScreenCoordsXY; } interface WindowTabDesc { @@ -839,8 +927,8 @@ declare global { zoom: number; visibilityFlags: number; - getCentrePosition(): Coord2; - moveTo(position: Coord2 | Coord3): void; - scrollTo(position: Coord2 | Coord3): void; + getCentrePosition(): CoordsXY; + moveTo(position: CoordsXY | CoordsXYZ): void; + scrollTo(position: CoordsXY | CoordsXYZ): void; } } diff --git a/src/openrct2-ui/scripting/CustomMenu.cpp b/src/openrct2-ui/scripting/CustomMenu.cpp index a2d7ef47b4..34333ad903 100644 --- a/src/openrct2-ui/scripting/CustomMenu.cpp +++ b/src/openrct2-ui/scripting/CustomMenu.cpp @@ -11,12 +11,72 @@ # include "CustomMenu.h" +# include +# include +# include + namespace OpenRCT2::Scripting { + std::optional ActiveCustomTool; std::vector CustomMenuItems; - static void RemoveMenuItems(std::shared_ptr owner) + static constexpr std::array CursorNames = { + "arrow", "blank", "up_arrow", "up_down_arrow", "hand_point", "zzz", "diagonal_arrows", + "picker", "tree_down", "fountain_down", "statue_down", "bench_down", "cross_hair", "bin_down", + "lamppost_down", "fence_down", "flower_down", "path_down", "dig_down", "water_down", "house_down", + "volcano_down", "walk_down", "paint_down", "entrance_down", "hand_open", "hand_closed", + }; + + template<> DukValue ToDuk(duk_context* ctx, const CURSOR_ID& value) { + if (value >= 0 && static_cast(value) < std::size(CursorNames)) + { + auto str = CursorNames[value]; + duk_push_lstring(ctx, str.data(), str.size()); + DukValue::take_from_stack(ctx); + } + return {}; + } + + template<> CURSOR_ID FromDuk(const DukValue& s) + { + if (s.type() == DukValue::Type::STRING) + { + auto it = std::find(std::begin(CursorNames), std::end(CursorNames), s.as_c_string()); + if (it != std::end(CursorNames)) + { + return static_cast(std::distance(std::begin(CursorNames), it)); + } + } + return CURSOR_UNDEFINED; + } + + template<> DukValue ToDuk(duk_context* ctx, const CoordsXY& coords) + { + DukObject dukCoords(ctx); + dukCoords.Set("x", coords.x); + dukCoords.Set("y", coords.y); + return dukCoords.Take(); + } + + template<> DukValue ToDuk(duk_context* ctx, const ScreenCoordsXY& coords) + { + DukObject dukCoords(ctx); + dukCoords.Set("x", coords.x); + dukCoords.Set("y", coords.y); + return dukCoords.Take(); + } + + static void RemoveMenuItemsAndTool(std::shared_ptr owner) + { + if (ActiveCustomTool) + { + if (ActiveCustomTool->Owner == owner) + { + tool_cancel(); + } + } + auto& menuItems = CustomMenuItems; for (auto it = menuItems.begin(); it != menuItems.end();) { @@ -33,8 +93,131 @@ namespace OpenRCT2::Scripting void InitialiseCustomMenuItems(ScriptEngine& scriptEngine) { - scriptEngine.SubscribeToPluginStoppedEvent([](std::shared_ptr plugin) -> void { RemoveMenuItems(plugin); }); + scriptEngine.SubscribeToPluginStoppedEvent( + [](std::shared_ptr plugin) -> void { RemoveMenuItemsAndTool(plugin); }); } + + void CustomTool::OnUpdate(const ScreenCoordsXY& screenCoords) + { + InvokeEventHandler(onMove, screenCoords); + } + + void CustomTool::OnDown(const ScreenCoordsXY& screenCoords) + { + MouseDown = true; + InvokeEventHandler(onDown, screenCoords); + } + + void CustomTool::OnDrag(const ScreenCoordsXY& screenCoords) + { + } + + void CustomTool::Start() + { + auto& scriptEngine = GetContext()->GetScriptEngine(); + scriptEngine.ExecutePluginCall(Owner, onStart, {}, false); + } + + void CustomTool::OnUp(const ScreenCoordsXY& screenCoords) + { + MouseDown = false; + InvokeEventHandler(onUp, screenCoords); + } + + void CustomTool::OnAbort() + { + auto& scriptEngine = GetContext()->GetScriptEngine(); + scriptEngine.ExecutePluginCall(Owner, onFinish, {}, false); + } + + void CustomTool::InvokeEventHandler(const DukValue& dukHandler, const ScreenCoordsXY& screenCoords) + { + if (dukHandler.is_function()) + { + auto ctx = dukHandler.context(); + + auto flags = 0; + CoordsXY mapCoords{}; + int32_t interactionType = 0; + TileElement* tileElement{}; + get_map_coordinates_from_pos(screenCoords, flags, mapCoords, &interactionType, &tileElement, nullptr); + + DukObject obj(dukHandler.context()); + obj.Set("isDown", MouseDown); + obj.Set("screenCoords", ToDuk(ctx, screenCoords)); + obj.Set("mapCoords", ToDuk(ctx, mapCoords)); + + if (interactionType == VIEWPORT_INTERACTION_ITEM_SPRITE && tileElement != nullptr) + { + // get_map_coordinates_from_pos returns the sprite using tileElement... ugh + auto sprite = reinterpret_cast(tileElement); + obj.Set("entityId", sprite->generic.sprite_index); + } + else if (tileElement != nullptr) + { + int32_t index = 0; + auto el = map_get_first_element_at(mapCoords); + if (el != nullptr) + { + do + { + if (el == tileElement) + { + obj.Set("tileElementIndex", index); + break; + } + index++; + } while (!(el++)->IsLastForTile()); + } + } + auto eventArgs = obj.Take(); + + auto& scriptEngine = GetContext()->GetScriptEngine(); + std::vector args; + args.push_back(eventArgs); + scriptEngine.ExecutePluginCall(Owner, dukHandler, args, false); + } + } + + void InitialiseCustomTool(ScriptEngine& scriptEngine, const DukValue& dukValue) + { + try + { + if (dukValue.type() == DukValue::Type::OBJECT) + { + CustomTool customTool; + customTool.Owner = scriptEngine.GetExecInfo().GetCurrentPlugin(); + customTool.Id = dukValue["id"].as_string(); + customTool.Cursor = FromDuk(dukValue["cursor"]); + if (customTool.Cursor == CURSOR_UNDEFINED) + { + customTool.Cursor = CURSOR_ARROW; + } + customTool.onStart = dukValue["onStart"]; + customTool.onDown = dukValue["onDown"]; + customTool.onMove = dukValue["onMove"]; + customTool.onUp = dukValue["onUp"]; + customTool.onFinish = dukValue["onFinish"]; + + auto toolbarWindow = window_find_by_class(WC_TOP_TOOLBAR); + if (toolbarWindow != nullptr) + { + // Use a widget that does not exist on top toolbar but also make sure it isn't -1 as that + // prevents abort from being called. + rct_widgetindex widgetIndex = -2; + tool_cancel(); + tool_set(toolbarWindow, widgetIndex, static_cast(customTool.Cursor)); + ActiveCustomTool = std::move(customTool); + ActiveCustomTool->Start(); + } + } + } + catch (const DukException&) + { + duk_error(scriptEngine.GetContext(), DUK_ERR_ERROR, "Invalid parameters."); + } + } + } // namespace OpenRCT2::Scripting #endif diff --git a/src/openrct2-ui/scripting/CustomMenu.h b/src/openrct2-ui/scripting/CustomMenu.h index 6d41982e21..743fa111f0 100644 --- a/src/openrct2-ui/scripting/CustomMenu.h +++ b/src/openrct2-ui/scripting/CustomMenu.h @@ -13,6 +13,7 @@ # include # include +# include # include # include # include @@ -41,9 +42,39 @@ namespace OpenRCT2::Scripting } }; + struct CustomTool + { + std::shared_ptr Owner; + std::string Id; + CURSOR_ID Cursor{}; + bool MouseDown{}; + + // Event handlers + DukValue onStart; + DukValue onDown; + DukValue onMove; + DukValue onUp; + DukValue onFinish; + + void Start(); + void OnUpdate(const ScreenCoordsXY& screenCoords); + void OnDown(const ScreenCoordsXY& screenCoords); + void OnDrag(const ScreenCoordsXY& screenCoords); + void OnUp(const ScreenCoordsXY& screenCoords); + void OnAbort(); + + private: + void InvokeEventHandler(const DukValue& dukHandler, const ScreenCoordsXY& screenCoords); + }; + + extern std::optional ActiveCustomTool; extern std::vector CustomMenuItems; void InitialiseCustomMenuItems(ScriptEngine& scriptEngine); + void InitialiseCustomTool(ScriptEngine& scriptEngine, const DukValue& dukValue); + + template<> DukValue ToDuk(duk_context* ctx, const CURSOR_ID& value); + template<> CURSOR_ID FromDuk(const DukValue& s); } // namespace OpenRCT2::Scripting diff --git a/src/openrct2-ui/scripting/ScTileSelection.hpp b/src/openrct2-ui/scripting/ScTileSelection.hpp new file mode 100644 index 0000000000..850d180378 --- /dev/null +++ b/src/openrct2-ui/scripting/ScTileSelection.hpp @@ -0,0 +1,178 @@ +/***************************************************************************** + * Copyright (c) 2014-2020 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#ifdef ENABLE_SCRIPTING + +# include +# include +# include + +namespace OpenRCT2::Scripting +{ + class ScTileSelection + { + private: + duk_context* _ctx{}; + + public: + ScTileSelection(duk_context* ctx) + : _ctx(ctx) + { + } + + DukValue range_get() const + { + if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE) + { + DukObject range(_ctx); + + DukObject leftTop(_ctx); + leftTop.Set("x", gMapSelectPositionA.x); + leftTop.Set("y", gMapSelectPositionA.y); + range.Set("leftTop", leftTop.Take()); + + DukObject rightBottom(_ctx); + rightBottom.Set("x", gMapSelectPositionB.x); + rightBottom.Set("y", gMapSelectPositionB.y); + range.Set("rightBottom", rightBottom.Take()); + return range.Take(); + } + else + { + duk_push_null(_ctx); + return DukValue::take_from_stack(_ctx); + } + } + + void range_set(DukValue value) + { + map_invalidate_selection_rect(); + if (value.type() == DukValue::Type::OBJECT) + { + auto range = GetMapRange(value); + if (range) + { + gMapSelectPositionA.x = range->GetLeft(); + gMapSelectPositionA.y = range->GetTop(); + gMapSelectPositionB.x = range->GetRight(); + gMapSelectPositionB.y = range->GetBottom(); + gMapSelectType = MAP_SELECT_TYPE_FULL; + gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; + } + } + else + { + gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE; + } + map_invalidate_selection_rect(); + } + + DukValue tiles_get() const + { + duk_push_array(_ctx); + if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE_CONSTRUCT) + { + duk_uarridx_t index = 0; + for (const auto& tile : gMapSelectionTiles) + { + duk_push_object(_ctx); + duk_push_int(_ctx, tile.x); + duk_put_prop_string(_ctx, -2, "x"); + duk_push_int(_ctx, tile.y); + duk_put_prop_string(_ctx, -2, "y"); + duk_put_prop_index(_ctx, -2, index); + index++; + } + } + return DukValue::take_from_stack(_ctx); + } + + void tiles_set(DukValue value) + { + map_invalidate_map_selection_tiles(); + gMapSelectionTiles.clear(); + if (value.is_array()) + { + value.push(); + auto arrayLen = duk_get_length(_ctx, -1); + for (duk_uarridx_t i = 0; i < arrayLen; i++) + { + if (duk_get_prop_index(_ctx, -1, i)) + { + auto dukElement = DukValue::take_from_stack(_ctx); + auto coords = GetCoordsXY(dukElement); + if (coords) + { + gMapSelectionTiles.push_back(*coords); + } + } + } + duk_pop(_ctx); + } + + if (gMapSelectionTiles.empty()) + { + gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT; + gMapSelectFlags &= ~MAP_SELECT_FLAG_GREEN; + } + else + { + gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE_CONSTRUCT; + } + map_invalidate_map_selection_tiles(); + } + + static void Register(duk_context* ctx) + { + dukglue_register_property(ctx, &ScTileSelection::range_get, &ScTileSelection::range_set, "range"); + dukglue_register_property(ctx, &ScTileSelection::tiles_get, &ScTileSelection::tiles_set, "tiles"); + } + + private: + static std::optional GetCoordsXY(const DukValue& dukCoords) + { + std::optional result; + if (dukCoords.type() == DukValue::Type::OBJECT) + { + auto dukX = dukCoords["x"]; + if (dukX.type() == DukValue::Type::NUMBER) + { + auto dukY = dukCoords["y"]; + if (dukY.type() == DukValue::Type::NUMBER) + { + result = { dukX.as_int(), dukY.as_int() }; + } + } + } + return result; + } + + static std::optional GetMapRange(const DukValue& dukMapRange) + { + std::optional result; + if (dukMapRange.type() == DukValue::Type::OBJECT) + { + auto leftTop = GetCoordsXY(dukMapRange["leftTop"]); + if (leftTop.has_value()) + { + auto rightBottom = GetCoordsXY(dukMapRange["rightBottom"]); + if (rightBottom.has_value()) + { + result = MapRange(leftTop->x, leftTop->y, rightBottom->x, rightBottom->y); + } + } + } + return result; + } + }; +} // namespace OpenRCT2::Scripting + +#endif diff --git a/src/openrct2-ui/scripting/ScUi.hpp b/src/openrct2-ui/scripting/ScUi.hpp index d1b2f5094c..b4e527a738 100644 --- a/src/openrct2-ui/scripting/ScUi.hpp +++ b/src/openrct2-ui/scripting/ScUi.hpp @@ -12,11 +12,14 @@ #ifdef ENABLE_SCRIPTING # include "CustomMenu.h" +# include "ScTileSelection.hpp" # include "ScViewport.hpp" # include "ScWindow.hpp" +# include # include # include +# include # include # include # include @@ -34,6 +37,41 @@ namespace OpenRCT2::Ui::Windows namespace OpenRCT2::Scripting { + class ScTool + { + private: + duk_context* _ctx{}; + + public: + ScTool(duk_context* ctx) + : _ctx(ctx) + { + } + + static void Register(duk_context* ctx) + { + dukglue_register_property(ctx, &ScTool::id_get, nullptr, "id"); + dukglue_register_property(ctx, &ScTool::cursor_get, nullptr, "cursor"); + dukglue_register_method(ctx, &ScTool::cancel, "cancel"); + } + + private: + std::string id_get() const + { + return ActiveCustomTool ? ActiveCustomTool->Id : ""; + } + + DukValue cursor_get() const + { + return ToDuk(_ctx, static_cast(gCurrentToolId)); + } + + void cancel() + { + tool_cancel(); + } + }; + class ScUi { private: @@ -64,6 +102,20 @@ namespace OpenRCT2::Scripting return std::make_shared(WC_MAIN_WINDOW); } + std::shared_ptr tileSelection_get() const + { + return std::make_shared(_scriptEngine.GetContext()); + } + + std::shared_ptr tool_get() const + { + if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) + { + return std::make_shared(_scriptEngine.GetContext()); + } + return {}; + } + std::shared_ptr openWindow(DukValue desc) { using namespace OpenRCT2::Ui::Windows; @@ -128,6 +180,11 @@ namespace OpenRCT2::Scripting return {}; } + void activateTool(const DukValue& desc) + { + InitialiseCustomTool(_scriptEngine, desc); + } + void registerMenuItem(std::string text, DukValue callback) { auto& execInfo = _scriptEngine.GetExecInfo(); @@ -142,10 +199,13 @@ namespace OpenRCT2::Scripting dukglue_register_property(ctx, &ScUi::width_get, nullptr, "width"); dukglue_register_property(ctx, &ScUi::windows_get, nullptr, "windows"); dukglue_register_property(ctx, &ScUi::mainViewport_get, nullptr, "mainViewport"); + dukglue_register_property(ctx, &ScUi::tileSelection_get, nullptr, "tileSelection"); + dukglue_register_property(ctx, &ScUi::tool_get, nullptr, "tool"); dukglue_register_method(ctx, &ScUi::openWindow, "openWindow"); dukglue_register_method(ctx, &ScUi::closeWindows, "closeWindows"); dukglue_register_method(ctx, &ScUi::closeAllWindows, "closeAllWindows"); dukglue_register_method(ctx, &ScUi::getWindow, "getWindow"); + dukglue_register_method(ctx, &ScUi::activateTool, "activateTool"); dukglue_register_method(ctx, &ScUi::registerMenuItem, "registerMenuItem"); } diff --git a/src/openrct2-ui/scripting/UiExtensions.cpp b/src/openrct2-ui/scripting/UiExtensions.cpp index de973d5ef7..54a00df453 100644 --- a/src/openrct2-ui/scripting/UiExtensions.cpp +++ b/src/openrct2-ui/scripting/UiExtensions.cpp @@ -12,6 +12,7 @@ # include "UiExtensions.h" # include "CustomMenu.h" +# include "ScTileSelection.hpp" # include "ScUi.hpp" # include "ScWidget.hpp" # include "ScWindow.hpp" @@ -26,6 +27,8 @@ void UiScriptExtensions::Extend(ScriptEngine& scriptEngine) dukglue_register_global(ctx, std::make_shared(scriptEngine), "ui"); + ScTileSelection::Register(ctx); + ScTool::Register(ctx); ScUi::Register(ctx); ScViewport::Register(ctx); ScWidget::Register(ctx); diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index 265ac9856f..8ffa06d91d 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014-2019 OpenRCT2 developers + * Copyright (c) 2014-2020 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 @@ -2961,6 +2961,15 @@ static void window_top_toolbar_tool_update(rct_window* w, rct_widgetindex widget case WIDX_SCENERY: top_toolbar_tool_update_scenery(screenCoords); break; +#ifdef ENABLE_SCRIPTING + default: + auto& customTool = OpenRCT2::Scripting::ActiveCustomTool; + if (customTool) + { + customTool->OnUpdate(screenCoords); + } + break; +#endif } } @@ -3009,6 +3018,15 @@ static void window_top_toolbar_tool_down(rct_window* w, rct_widgetindex widgetIn case WIDX_SCENERY: window_top_toolbar_scenery_tool_down(screenCoords, w, widgetIndex); break; +#ifdef ENABLE_SCRIPTING + default: + auto& customTool = OpenRCT2::Scripting::ActiveCustomTool; + if (customTool) + { + customTool->OnDown(screenCoords); + } + break; +#endif } } @@ -3227,6 +3245,15 @@ static void window_top_toolbar_tool_drag(rct_window* w, rct_widgetindex widgetIn if (gWindowSceneryEyedropperEnabled) window_top_toolbar_scenery_tool_down(screenCoords, w, widgetIndex); break; +#ifdef ENABLE_SCRIPTING + default: + auto& customTool = OpenRCT2::Scripting::ActiveCustomTool; + if (customTool) + { + customTool->OnDrag(screenCoords); + } + break; +#endif } } @@ -3254,6 +3281,15 @@ static void window_top_toolbar_tool_up(rct_window* w, rct_widgetindex widgetInde gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE; gCurrentToolId = TOOL_CROSSHAIR; break; +#ifdef ENABLE_SCRIPTING + default: + auto& customTool = OpenRCT2::Scripting::ActiveCustomTool; + if (customTool) + { + customTool->OnUp(screenCoords); + } + break; +#endif } } @@ -3270,6 +3306,16 @@ static void window_top_toolbar_tool_abort(rct_window* w, rct_widgetindex widgetI case WIDX_CLEAR_SCENERY: hide_gridlines(); break; +#ifdef ENABLE_SCRIPTING + default: + auto& customTool = OpenRCT2::Scripting::ActiveCustomTool; + if (customTool) + { + customTool->OnAbort(); + customTool = {}; + } + break; +#endif } } diff --git a/src/openrct2/scripting/Duktape.hpp b/src/openrct2/scripting/Duktape.hpp index 71ac11ab14..fe47adf8d1 100644 --- a/src/openrct2/scripting/Duktape.hpp +++ b/src/openrct2/scripting/Duktape.hpp @@ -189,6 +189,10 @@ namespace OpenRCT2::Scripting return std::nullopt; } } + + template DukValue ToDuk(duk_context* ctx, const T& value) = delete; + template T FromDuk(const DukValue& s) = delete; + } // namespace OpenRCT2::Scripting #endif