diff --git a/src/game/game.cpp b/src/game/game.cpp index d057b6a..c20a3b6 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -36,6 +36,9 @@ namespace game unsigned int* levelEntityId; + int* g_script_error_level; + jmp_buf* g_script_error; + void AddRefToValue(VariableValue* value) { if (value->type == SCRIPT_OBJECT) @@ -153,6 +156,9 @@ namespace game native::scr_instanceFunctions = reinterpret_cast(SELECT_VALUE(0x184CDB0, 0x1D4F258, 0x1BF59C8)); native::scr_globalFunctions = reinterpret_cast(SELECT_VALUE(0x186C68C, 0x1D6EB34, 0x1C152A4)); + native::g_script_error_level = reinterpret_cast(SELECT_VALUE(0x1BEFCFC, 0x20B21FC, 0x1F5B058)); + native::g_script_error = reinterpret_cast(SELECT_VALUE(0x1BF1D18, 0x20B4218, 0x1F5A818)); + native::levelEntityId = reinterpret_cast(SELECT_VALUE(0x1BCBCA4, 0x208E1A4, 0x1CD873C)); } } diff --git a/src/game/game.hpp b/src/game/game.hpp index fe35409..5aa55ff 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -48,6 +48,9 @@ namespace game extern unsigned int* levelEntityId; + extern int* g_script_error_level; + extern jmp_buf* g_script_error; + void AddRefToValue(VariableValue* value); void Scr_ClearOutParams(); diff --git a/src/module/notification.cpp b/src/module/notification.cpp index bf545c0..1ca4c3d 100644 --- a/src/module/notification.cpp +++ b/src/module/notification.cpp @@ -77,7 +77,7 @@ void notification::vm_notify_stub(const unsigned int notify_id, const unsigned s } catch (std::exception& e) { - scripting::propagate_scripting_error(e); + scripting::propagate_error(e); } } diff --git a/src/module/scripting.cpp b/src/module/scripting.cpp index 2db605c..04bef8d 100644 --- a/src/module/scripting.cpp +++ b/src/module/scripting.cpp @@ -75,7 +75,7 @@ void scripting::post_start() } catch (std::exception& e) { - propagate_scripting_error(e); + propagate_error(e); } }); on_stop([this]() @@ -225,7 +225,7 @@ void scripting::on_stop(const std::function& callback) stop_callbacks_.push_back(callback); } -void scripting::propagate_scripting_error(const std::exception& e) +void scripting::propagate_error(const std::exception& e) { printf("\n******* Script execution error *******\n"); printf("%s\n", e.what()); @@ -269,7 +269,7 @@ void scripting::call(const std::string& function, const unsigned int entity_id, const int function_index = find_function_index(function); if (function_index < 0) { - throw std::runtime_error("No function found for name " + function); + throw std::runtime_error("No function found for name '" + function + "'"); } const game::native::scr_entref_t entity = function_index > 0x1C7 @@ -278,20 +278,32 @@ void scripting::call(const std::string& function, const unsigned int entity_id, const auto function_ptr = game::native::Scr_GetFunc(function_index); - /*static_assert(sizeof(jmp_buf) == 64); - ++*(DWORD*)0x20B21FC; - int res = setjmp(((jmp_buf*)0x20B4218)[*(DWORD*)0x20B21FC]); - if (res) + if(!call_safe(function_ptr, entity)) { - --*(DWORD*)0x20B21FC; - return; - }*/ - - function_ptr(entity.val); - - //--*(DWORD*)0x20B21FC; + throw std::runtime_error("Error executing function '" + function + "'"); + } } +#pragma warning(push) +#pragma warning(disable: 4611) +bool scripting::call_safe(const game::native::scr_call_t function, const game::native::scr_entref_t entref) +{ + static_assert(sizeof(jmp_buf) == 64); + + *game::native::g_script_error_level += 1; + if (setjmp(game::native::g_script_error[*game::native::g_script_error_level])) + { + *game::native::g_script_error_level -= 1; + return false; + } + + function(entref.val); + + *game::native::g_script_error_level -= 1; + return true; +} +#pragma warning(pop) + int scripting::find_function_index(const std::string& function) { auto function_entry = game::scripting::instance_function_map.find(function); diff --git a/src/module/scripting.hpp b/src/module/scripting.hpp index 15c1872..d0ae2b6 100644 --- a/src/module/scripting.hpp +++ b/src/module/scripting.hpp @@ -56,7 +56,7 @@ public: static void on_start(const std::function& callback); static void on_stop(const std::function& callback); - static void propagate_scripting_error(const std::exception& e); + static void propagate_error(const std::exception& e); private: std::unique_ptr chai_; @@ -80,5 +80,6 @@ private: static void stop_execution(); static void call(const std::string& function, unsigned int entity_id, const std::vector& arguments); + static bool call_safe(game::native::scr_call_t function, game::native::scr_entref_t entref); static int find_function_index(const std::string& function); };