diff --git a/src/mods/bindings/Sdk.cpp b/src/mods/bindings/Sdk.cpp index b8842c8a..1d779e5a 100644 --- a/src/mods/bindings/Sdk.cpp +++ b/src/mods/bindings/Sdk.cpp @@ -1014,13 +1014,22 @@ void set_data(void* data, ::sdk::RETypeDefinition* data_type, sol::object& value } REManagedObject** field = (REManagedObject**) data; - if (field != nullptr && *field != nullptr) { - utility::re_managed_object::release(*field); - } - if (new_data != nullptr) { - utility::re_managed_object::add_ref(new_data); + if (field != nullptr && *field != new_data) { + if (new_data != nullptr) { + utility::re_managed_object::add_ref(new_data); + } + + // Use a thread-safe atomic exchange. This is what Capcom does for all field assignments. + auto old = *field; + while (_InterlockedCompareExchangePointer((PVOID*)field, new_data, old) != old) { + old = *field; + } + + if (old != nullptr) { + utility::re_managed_object::release(old); + } } - *(REManagedObject**) data = new_data; + return; } }