@@ -42,7 +42,7 @@ std::recursive_mutex morph_task_mutex;
4242std::recursive_mutex qupdatenormalmap_lock;
4343std::recursive_mutex loading_game_mutex;
4444std::recursive_mutex custom_main_task_pool_lock;
45- static void * nitransforminterface= nullptr ;
45+ static void * nitransforminterface = nullptr ;
4646std::uint64_t qupdatenormalmap_recursion = 0 ;
4747std::queue<std::function<void ()>> custom_main_task_pool;
4848auto original_process_task = (void (*)(void * main, void * arg2, void * arg3, void * arg4)) nullptr ;
@@ -856,44 +856,57 @@ namespace plugin {
856856 }
857857 }
858858 }
859-
859+ static std:: atomic_int32_t setnodetransformhook_norecursion= 0 ;
860860 static void SetNodeTransformsHook_fn (void * arg1, uint32_t formID, uint64_t immediate, bool reset) {
861861 if (PARALLEL_TRANSFORM_FIX) {
862+ auto original_recursion = setnodetransformhook_norecursion.fetch_add (1 );
863+ if (original_recursion != 0 ) {
864+ setnodetransformhook_norecursion.fetch_sub (1 );
865+ return ;
866+ } else {
867+ setnodetransformhook_norecursion.fetch_sub (1 );
868+ }
862869 if (auto task_int = SKSE::GetTaskInterface ()) {
863870 immediate = true ;
864871 if (!is_main_thread ()) {
865- AddMainTask (
866- [arg1 = arg1, arg2 = formID, arg3 = immediate, arg4 = reset] {
867- if (auto arg2_form = RE::TESForm::LookupByID (arg2 )) {
868- if (auto actor = arg2_form-> As <RE::Actor> ()) {
869- if (!actor-> Is3DLoaded ()) {
870- logger::warn ( " Loading 3D for node transform " );
871- actor->Load3D (true );
872- }
872+ AddMainTask ([arg1 = arg1, arg2 = formID, arg3 = immediate, arg4 = reset] {
873+ if ( auto arg2_form = RE::TESForm::LookupByID (arg2)) {
874+ if (auto actor = arg2_form-> As < RE::Actor>( )) {
875+ if (! actor-> Is3DLoaded ()) {
876+ logger::warn ( " Loading 3D for node transform " );
877+ setnodetransformhook_norecursion. fetch_add ( 1 );
878+ actor->Load3D (true );
879+ setnodetransformhook_norecursion. fetch_sub ( 1 );
873880 }
874881 }
875- SetNodeTransformsHook (arg1, arg2, arg3, arg4);
876-
877- });
882+ }
883+ setnodetransformhook_norecursion.fetch_add (1 );
884+ SetNodeTransformsHook (arg1, arg2, arg3, arg4);
885+ setnodetransformhook_norecursion.fetch_sub (1 );
886+ });
878887 } else {
879888 AddMainTask ([arg1 = arg1, arg2 = formID, arg3 = immediate, arg4 = reset] {
880889 if (auto arg2_form = RE::TESForm::LookupByID (arg2)) {
881890 if (auto actor = arg2_form->As <RE::Actor>()) {
882891 if (!actor->Is3DLoaded ()) {
883892 logger::warn (" Loading 3D for node transform" );
893+ setnodetransformhook_norecursion.fetch_add (1 );
884894 actor->Load3D (true );
895+ setnodetransformhook_norecursion.fetch_sub (1 );
885896 }
886897 }
887898 }
899+ setnodetransformhook_norecursion.fetch_add (1 );
888900 SetNodeTransformsHook (arg1, arg2, arg3, arg4);
901+ setnodetransformhook_norecursion.fetch_sub (1 );
889902 });
890903 }
891904 }
892905 } else {
893906 SetNodeTransformsHook (arg1, formID, immediate, reset);
894907 }
895908 }
896-
909+
897910 static void UpdateNodeTransformsHook_fn (void * arg1, RE::TESObjectREFR* ref, bool firstperson, bool gender,
898911 const SKEEString* node_string) {
899912 if (PARALLEL_TRANSFORM_FIX && !is_main_thread ()) {
@@ -1420,21 +1433,21 @@ namespace plugin {
14201433 DetourTransactionCommit ();
14211434 if (PARALLEL_TRANSFORM_FIX) {
14221435 logger::info (" SKEE64 1170 parallel node transform workaround applying" );
1423- nitransforminterface =(void *) (((uint64_t ) skee64_info.lpBaseOfDll ) + 0x230810 );
1436+ nitransforminterface = (void *) (((uint64_t ) skee64_info.lpBaseOfDll ) + 0x230810 );
14241437 UpdateNodeTransformsHook = (void (*)(void *, RE::TESObjectREFR*, bool , bool , const SKEEString* node_name))(
14251438 (uint64_t ) skee64_info.lpBaseOfDll + 0xc68d0 );
14261439 DetourTransactionBegin ();
14271440 DetourUpdateThread (GetCurrentThread ());
14281441 DetourAttach (&(PVOID&) UpdateNodeTransformsHook, &UpdateNodeTransformsHook_fn);
14291442 DetourTransactionCommit ();
1430-
1443+
14311444 SetNodeTransformsHook = (void (*)(void * arg1, uint32_t formID, uint64_t immediate, bool reset))(
14321445 (uint64_t ) skee64_info.lpBaseOfDll + 0xc72c0 );
14331446 DetourTransactionBegin ();
14341447 DetourUpdateThread (GetCurrentThread ());
14351448 DetourAttach (&(PVOID&) SetNodeTransformsHook, &SetNodeTransformsHook_fn);
14361449 DetourTransactionCommit ();
1437-
1450+
14381451 SkeletonOnAttachHook = (void (*)(void * arg1, void * arg2, void * arg3, void * arg4, void * arg5, bool arg6, void * arg7,
14391452 void * arg8))((uint64_t ) skee64_info.lpBaseOfDll + 0x133330 );
14401453 DetourTransactionBegin ();
@@ -1567,14 +1580,14 @@ namespace plugin {
15671580 DetourUpdateThread (GetCurrentThread ());
15681581 DetourAttach (&(PVOID&) UpdateNodeTransformsHook, &UpdateNodeTransformsHook_fn);
15691582 DetourTransactionCommit ();
1570-
1583+
15711584 SetNodeTransformsHook = (void (*)(void * arg1, uint32_t formID, uint64_t immediate, bool reset))(
15721585 (uint64_t ) skee64_info.lpBaseOfDll + 0xcad50 );
15731586 DetourTransactionBegin ();
15741587 DetourUpdateThread (GetCurrentThread ());
15751588 DetourAttach (&(PVOID&) SetNodeTransformsHook, &SetNodeTransformsHook_fn);
15761589 DetourTransactionCommit ();
1577-
1590+
15781591 SkeletonOnAttachHook = (void (*)(void * arg1, void * arg2, void * arg3, void * arg4, void * arg5, bool arg6, void * arg7,
15791592 void * arg8))((uint64_t ) skee64_info.lpBaseOfDll + 0x1382a0 );
15801593 DetourTransactionBegin ();
@@ -1954,14 +1967,14 @@ namespace plugin {
19541967 DetourUpdateThread (GetCurrentThread ());
19551968 DetourAttach (&(PVOID&) UpdateNodeTransformsHook, &UpdateNodeTransformsHook_fn);
19561969 DetourTransactionCommit ();
1957-
1970+
19581971 SetNodeTransformsHook = (void (*)(void * arg1, uint32_t formID, uint64_t immediate, bool reset))(
19591972 (uint64_t ) skee64_info.lpBaseOfDll + 0x97290 );
19601973 DetourTransactionBegin ();
19611974 DetourUpdateThread (GetCurrentThread ());
19621975 DetourAttach (&(PVOID&) SetNodeTransformsHook, &SetNodeTransformsHook_fn);
19631976 DetourTransactionCommit ();
1964-
1977+
19651978 SkeletonOnAttachHook = (void (*)(void * arg1, void * arg2, void * arg3, void * arg4, void * arg5, bool arg6, void * arg7,
19661979 void * arg8))((uint64_t ) skee64_info.lpBaseOfDll + 0xfcb40 );
19671980 DetourTransactionBegin ();
@@ -2159,7 +2172,6 @@ namespace plugin {
21592172 DetourAttach (&(PVOID&) UpdateNodeTransformsHook, &UpdateNodeTransformsHook_fn);
21602173 DetourTransactionCommit ();
21612174
2162-
21632175 SetNodeTransformsHook = (void (*)(void * arg1, uint32_t formID, uint64_t immediate, bool reset))(
21642176 (uint64_t ) skee64_info.lpBaseOfDll + 0x7d7f0 );
21652177 DetourTransactionBegin ();
@@ -2377,15 +2389,13 @@ namespace plugin {
23772389 a_event->cell ->ForEachReference ([](RE::TESObjectREFR* ref) {
23782390 if (auto actor = ref->As <RE::Actor>()) {
23792391 if (!actor->Is3DLoaded ()) {
2380- logger::warn (" Loading 3D for node transform" );
2381- actor->Load3D (false );
2392+ // logger::warn("Loading 3D for node transform");
2393+ // actor->Load3D(false);
23822394 }
23832395 if (RE::PlayerCharacter::GetSingleton ()) {
23842396 RE::FormID fid = actor->formID ;
23852397 if (nitransforminterface) {
2386- AddMainTask ([fid]() {
2387- SetNodeTransformsHook_fn (nitransforminterface, (uint32_t ) fid, true , false );
2388- });
2398+ AddMainTask ([fid]() { SetNodeTransformsHook_fn (nitransforminterface, (uint32_t ) fid, true , false ); });
23892399 }
23902400 }
23912401 }
0 commit comments