diff --git a/src/badguy/dispenser.hpp b/src/badguy/dispenser.hpp index 261692113d3..d7f65552c95 100644 --- a/src/badguy/dispenser.hpp +++ b/src/badguy/dispenser.hpp @@ -50,6 +50,16 @@ class Dispenser final : public BadGuy, virtual ObjectSettings get_settings() override; virtual void after_editor_set() override; + virtual void expose(HSQUIRRELVM vm, SQInteger table_idx) override + { + ExposedObject::expose(vm, table_idx); + } + + virtual void unexpose(HSQUIRRELVM vm, SQInteger table_idx) override + { + ExposedObject::unexpose(vm, table_idx); + } + void notify_dead() { if (m_limit_dispensed_badguys) { m_current_badguys--; diff --git a/src/badguy/willowisp.hpp b/src/badguy/willowisp.hpp index de4d3bde109..a98756a8837 100644 --- a/src/badguy/willowisp.hpp +++ b/src/badguy/willowisp.hpp @@ -57,6 +57,16 @@ class WillOWisp final : virtual ObjectSettings get_settings() override; virtual void move_to(const Vector& pos) override; + virtual void expose(HSQUIRRELVM vm, SQInteger table_idx) override + { + ExposedObject::expose(vm, table_idx); + } + + virtual void unexpose(HSQUIRRELVM vm, SQInteger table_idx) override + { + ExposedObject::unexpose(vm, table_idx); + } + /** make WillOWisp vanish */ void vanish(); diff --git a/src/scripting/badguy.hpp b/src/scripting/badguy.hpp index 6f22c69ab29..2c67be28384 100644 --- a/src/scripting/badguy.hpp +++ b/src/scripting/badguy.hpp @@ -27,9 +27,9 @@ class BadGuy; namespace scripting { -class BadGuy final +class BadGuy #ifndef SCRIPTING_API - : public GameObject<::BadGuy> + : virtual public GameObject<::BadGuy> #endif { #ifndef SCRIPTING_API diff --git a/src/scripting/dispenser.cpp b/src/scripting/dispenser.cpp index b992371b35b..2a8d5f9ac23 100644 --- a/src/scripting/dispenser.cpp +++ b/src/scripting/dispenser.cpp @@ -21,13 +21,13 @@ namespace scripting { void Dispenser::activate() { - SCRIPT_GUARD_VOID; + SCRIPT_GUARD_VOID_T(Dispenser); object.activate(); } void Dispenser::deactivate() { - SCRIPT_GUARD_VOID; + SCRIPT_GUARD_VOID_T(Dispenser); object.deactivate(); } diff --git a/src/scripting/dispenser.hpp b/src/scripting/dispenser.hpp index c2415c1827d..5086b450f31 100644 --- a/src/scripting/dispenser.hpp +++ b/src/scripting/dispenser.hpp @@ -18,6 +18,7 @@ #define HEADER_SUPERTUX_SCRIPTING_DISPENSER_HPP #ifndef SCRIPTING_API +#include "scripting/badguy.hpp" #include "scripting/game_object.hpp" class Dispenser; @@ -25,14 +26,14 @@ class Dispenser; namespace scripting { -class Dispenser final +class Dispenser final : public scripting::BadGuy #ifndef SCRIPTING_API - : public GameObject<::Dispenser> + , virtual public GameObject<::Dispenser> #endif { #ifndef SCRIPTING_API public: - using GameObject::GameObject; + using BadGuy::BadGuy; private: Dispenser(const Dispenser&) = delete; diff --git a/src/scripting/game_object.hpp b/src/scripting/game_object.hpp index f57e443745f..898a4cb72f2 100644 --- a/src/scripting/game_object.hpp +++ b/src/scripting/game_object.hpp @@ -50,6 +50,33 @@ } \ auto& object __attribute__((unused)) = *object_ptr +#define SCRIPT_GUARD_VOID_T(OBJECT) \ + auto object_ptr = GameObject<::OBJECT>::get_object_ptr(); \ + if (object_ptr == nullptr) { \ + log_fatal << "error: script is accessing a dead object: " \ + << GameObject<::OBJECT>::m_uid << std::endl; \ + return; \ + } \ + auto& object = *object_ptr + +#define SCRIPT_GUARD_DEFAULT_T(OBJECT) \ + auto object_ptr = GameObject<::OBJECT>::get_object_ptr(); \ + if (object_ptr == nullptr) { \ + log_fatal << "error: script is accessing a dead object: " \ + << GameObject<::OBJECT>::m_uid << std::endl; \ + return {}; \ + } \ + auto& object = *object_ptr + +#define SCRIPT_GUARD_RETURN_T(OBJECT, x) \ + auto object_ptr = GameObject<::OBJECT>::get_object_ptr(); \ + if (object_ptr == nullptr) { \ + log_fatal << "error: script is accessing a dead object: " \ + << GameObject<::OBJECT>::m_uid << std::endl; \ + return x; \ + } \ + auto& object __attribute__((unused)) = *object_ptr + class GameObjectManager; namespace scripting { diff --git a/src/scripting/willowisp.cpp b/src/scripting/willowisp.cpp index f80a3578c76..85fcf5d5e61 100644 --- a/src/scripting/willowisp.cpp +++ b/src/scripting/willowisp.cpp @@ -23,28 +23,28 @@ namespace scripting { void WillOWisp::goto_node(int node_no) { - SCRIPT_GUARD_VOID; + SCRIPT_GUARD_VOID_T(WillOWisp); object.goto_node(node_no); } void WillOWisp::set_state(const std::string& state) { - SCRIPT_GUARD_VOID; + SCRIPT_GUARD_VOID_T(WillOWisp); object.set_state(state); } void WillOWisp::start_moving() { - SCRIPT_GUARD_VOID; + SCRIPT_GUARD_VOID_T(WillOWisp); object.start_moving(); } void WillOWisp::stop_moving() { - SCRIPT_GUARD_VOID; + SCRIPT_GUARD_VOID_T(WillOWisp); object.stop_moving(); } diff --git a/src/scripting/willowisp.hpp b/src/scripting/willowisp.hpp index bed78eea931..91bca0529dc 100644 --- a/src/scripting/willowisp.hpp +++ b/src/scripting/willowisp.hpp @@ -19,6 +19,7 @@ #ifndef SCRIPTING_API #include +#include "scripting/badguy.hpp" #include "scripting/game_object.hpp" class WillOWisp; @@ -26,14 +27,14 @@ class WillOWisp; namespace scripting { -class WillOWisp final +class WillOWisp final : public scripting::BadGuy #ifndef SCRIPTING_API - : public GameObject<::WillOWisp> + , virtual public GameObject<::WillOWisp> #endif { #ifndef SCRIPTING_API public: - using GameObject::GameObject; + using BadGuy::BadGuy; private: WillOWisp(const WillOWisp&) = delete; diff --git a/src/scripting/wrapper.cpp b/src/scripting/wrapper.cpp index d19766c8ea7..230d2d72aeb 100644 --- a/src/scripting/wrapper.cpp +++ b/src/scripting/wrapper.cpp @@ -8176,6 +8176,74 @@ void register_supertux_wrapper(HSQUIRRELVM v) throw SquirrelError(v, "Couldn't register class 'BadGuy'"); } + // Register class Dispenser + sq_pushstring(v, "Dispenser", -1); + sq_pushstring(v, "BadGuy", -1); + sq_get(v, -3); + if(sq_newclass(v, SQTrue) < 0) { + std::ostringstream msg; + msg << "Couldn't create new class 'Dispenser'"; + throw SquirrelError(v, msg.str()); + } + sq_pushstring(v, "activate", -1); + sq_newclosure(v, &Dispenser_activate_wrapper, 0); + sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|t"); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'activate'"); + } + + sq_pushstring(v, "deactivate", -1); + sq_newclosure(v, &Dispenser_deactivate_wrapper, 0); + sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|t"); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'deactivate'"); + } + + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register class 'Dispenser'"); + } + + // Register class WillOWisp + sq_pushstring(v, "WillOWisp", -1); + sq_pushstring(v, "BadGuy", -1); + sq_get(v, -3); + if(sq_newclass(v, SQTrue) < 0) { + std::ostringstream msg; + msg << "Couldn't create new class 'WillOWisp'"; + throw SquirrelError(v, msg.str()); + } + sq_pushstring(v, "goto_node", -1); + sq_newclosure(v, &WillOWisp_goto_node_wrapper, 0); + sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|ti"); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'goto_node'"); + } + + sq_pushstring(v, "set_state", -1); + sq_newclosure(v, &WillOWisp_set_state_wrapper, 0); + sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|ts"); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'set_state'"); + } + + sq_pushstring(v, "start_moving", -1); + sq_newclosure(v, &WillOWisp_start_moving_wrapper, 0); + sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|t"); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'start_moving'"); + } + + sq_pushstring(v, "stop_moving", -1); + sq_newclosure(v, &WillOWisp_stop_moving_wrapper, 0); + sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|t"); + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register function 'stop_moving'"); + } + + if(SQ_FAILED(sq_createslot(v, -3))) { + throw SquirrelError(v, "Couldn't register class 'WillOWisp'"); + } + // Register class Camera sq_pushstring(v, "Camera", -1); if(sq_newclass(v, SQFalse) < 0) { @@ -8286,31 +8354,6 @@ void register_supertux_wrapper(HSQUIRRELVM v) throw SquirrelError(v, "Couldn't register class 'Decal'"); } - // Register class Dispenser - sq_pushstring(v, "Dispenser", -1); - if(sq_newclass(v, SQFalse) < 0) { - std::ostringstream msg; - msg << "Couldn't create new class 'Dispenser'"; - throw SquirrelError(v, msg.str()); - } - sq_pushstring(v, "activate", -1); - sq_newclosure(v, &Dispenser_activate_wrapper, 0); - sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|t"); - if(SQ_FAILED(sq_createslot(v, -3))) { - throw SquirrelError(v, "Couldn't register function 'activate'"); - } - - sq_pushstring(v, "deactivate", -1); - sq_newclosure(v, &Dispenser_deactivate_wrapper, 0); - sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|t"); - if(SQ_FAILED(sq_createslot(v, -3))) { - throw SquirrelError(v, "Couldn't register function 'deactivate'"); - } - - if(SQ_FAILED(sq_createslot(v, -3))) { - throw SquirrelError(v, "Couldn't register class 'Dispenser'"); - } - // Register class DisplayEffect sq_pushstring(v, "DisplayEffect", -1); if(sq_newclass(v, SQFalse) < 0) { @@ -9463,45 +9506,6 @@ void register_supertux_wrapper(HSQUIRRELVM v) throw SquirrelError(v, "Couldn't register class 'Torch'"); } - // Register class WillOWisp - sq_pushstring(v, "WillOWisp", -1); - if(sq_newclass(v, SQFalse) < 0) { - std::ostringstream msg; - msg << "Couldn't create new class 'WillOWisp'"; - throw SquirrelError(v, msg.str()); - } - sq_pushstring(v, "goto_node", -1); - sq_newclosure(v, &WillOWisp_goto_node_wrapper, 0); - sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|ti"); - if(SQ_FAILED(sq_createslot(v, -3))) { - throw SquirrelError(v, "Couldn't register function 'goto_node'"); - } - - sq_pushstring(v, "set_state", -1); - sq_newclosure(v, &WillOWisp_set_state_wrapper, 0); - sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|ts"); - if(SQ_FAILED(sq_createslot(v, -3))) { - throw SquirrelError(v, "Couldn't register function 'set_state'"); - } - - sq_pushstring(v, "start_moving", -1); - sq_newclosure(v, &WillOWisp_start_moving_wrapper, 0); - sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|t"); - if(SQ_FAILED(sq_createslot(v, -3))) { - throw SquirrelError(v, "Couldn't register function 'start_moving'"); - } - - sq_pushstring(v, "stop_moving", -1); - sq_newclosure(v, &WillOWisp_stop_moving_wrapper, 0); - sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|t"); - if(SQ_FAILED(sq_createslot(v, -3))) { - throw SquirrelError(v, "Couldn't register function 'stop_moving'"); - } - - if(SQ_FAILED(sq_createslot(v, -3))) { - throw SquirrelError(v, "Couldn't register class 'WillOWisp'"); - } - // Register class Wind sq_pushstring(v, "Wind", -1); if(sq_newclass(v, SQFalse) < 0) { diff --git a/src/squirrel/exposed_object.hpp b/src/squirrel/exposed_object.hpp index 1c2274a7a8d..df66930c8a3 100644 --- a/src/squirrel/exposed_object.hpp +++ b/src/squirrel/exposed_object.hpp @@ -42,7 +42,7 @@ * @param class T: Scripting class (e.g. scripting::Gradient) */ template -class ExposedObject : public ScriptInterface +class ExposedObject : virtual public ScriptInterface { private: /**