33#include < detours/detours.h>
44#include " include/mutil/mutil.h"
55namespace plugin {
6- void NiNodeUpdateHook (RE::NiAVObject* obj, RE::NiUpdateData& update);
7- void * OriginalUpdatePtr = nullptr ;
6+ void UpdateClavicle (RE::Actor* obj, float delta);
7+ void * OriginalActorUpdatePtr = nullptr ;
8+ void * OriginalPlayerUpdatePtr = nullptr ;
9+ void * OriginalPlayerUpdate3PPtr = nullptr ;
810 RE::NiAVObject* FindNiObjectName (RE::NiNode* obj, std::string FindName) {
911 if (!obj) {
1012 return nullptr ;
@@ -33,10 +35,28 @@ namespace plugin {
3335 }
3436 }
3537 }
36- void NiNodeUpdateHook (RE::NiAVObject* obj, RE::NiUpdateData& update)
38+ void ActorUpdateHook (RE::Actor* obj, float delta) {
39+ auto OriginalUpdate = (void (*)(RE::Actor* obj, float delta)) OriginalActorUpdatePtr;
40+ OriginalUpdate (obj, delta);
41+ UpdateClavicle (obj, delta);
42+ }
43+ void PlayerUpdateHook (RE::Actor* obj, float delta) {
44+ auto OriginalUpdate = (void (*)(RE::Actor* obj, float delta)) OriginalPlayerUpdatePtr;
45+ OriginalUpdate (obj, delta);
46+ UpdateClavicle (obj, delta);
47+ }
48+ void PlayerUpdate3PHook (RE::Actor* obj) {
49+ auto OriginalUpdate = (void (*)(RE::Actor* obj)) OriginalPlayerUpdate3PPtr;
50+ UpdateClavicle (obj, 0 .0f );
51+ OriginalUpdate (obj);
52+
53+ }
54+ void UpdateClavicle (RE::Actor* obj, float delta)
3755 {
38- auto OriginalUpdate = (void (*)(RE::NiAVObject*, RE::NiUpdateData&)) OriginalUpdatePtr;
39- OriginalUpdate (obj, update);
56+
57+ if (!obj->Is3DLoaded () || !obj->GetCurrent3D () || !obj->GetCurrent3D ()->AsNode ()) {
58+ return ;
59+ }
4060 std::vector<std::string> nodes;
4161
4262 nodes.push_back (" NPC Clavicle2.L" );
@@ -60,9 +80,11 @@ namespace plugin {
6080 original_C2R_quat.y = 0.590508 ;
6181 original_C2R_quat.z = -0.326944 ;
6282 for (int r = 0 ; r < 2 ; r++) {
63- if (std::string (obj->name ) == nodes[0 + r * 3 ]) {
64- auto clavicle2 = obj;
65-
83+
84+ auto clavicle2 = FindNiObjectName (obj->GetCurrent3D ()->AsNode (), nodes[0 + r * 3 ].c_str ());
85+ if (!clavicle2) {
86+ continue ;
87+ }
6688 auto clavicle2node = clavicle2->AsNode ();
6789 auto clavicle = FindNiObjectName (clavicle2->parent ->AsNode (), nodes[1 + r * 3 ].c_str ());
6890 auto upperarm = FindNiObjectName (clavicle2->parent ->AsNode (), nodes[2 + r * 3 ].c_str ());
@@ -77,7 +99,7 @@ namespace plugin {
7799 original_C2_quat = original_C2R_quat;
78100 }
79101 RE::NiPoint3 original_C2_vector = upperarm->parent ->world * UA_pos - clavicle2->parent ->world * C2_pos;
80- RE::NiPoint3 new_C2_vector = upperarm->world .translate - clavicle2->world .translate ;
102+ RE::NiPoint3 new_C2_vector = ( upperarm->world .translate - clavicle2->world .translate ) ;
81103 original_C2_vector.Unitize ();
82104 new_C2_vector.Unitize ();
83105 auto axis = original_C2_vector.Cross (new_C2_vector);
@@ -103,19 +125,27 @@ namespace plugin {
103125 auto x_vecn = vec2vec_rot3.columns [0 ];
104126 auto y_vecn = vec2vec_rot3.columns [1 ];
105127 auto z_vecn = vec2vec_rot3.columns [2 ];
106- RE::NiMatrix3 vec2vec_matrix3 (RE::NiPoint3 (x_vecn.x , y_vecn.x , z_vecn.x ), RE::NiPoint3 (x_vecn.y , y_vecn.y , z_vecn.y ),
107- RE::NiPoint3 (x_vecn.z , y_vecn.z , z_vecn.z ));
128+ RE::NiMatrix3 vec2vec_matrix3;
129+ for (int x = 0 ; x < 3 ; x++) {
130+ vec2vec_matrix3.entry [0 ][x] = vec2vec_rot3.columns [x][0 ];
131+ vec2vec_matrix3.entry [1 ][x] = vec2vec_rot3.columns [x][1 ];
132+ vec2vec_matrix3.entry [2 ][x] = vec2vec_rot3.columns [x][2 ];
133+ }
108134
109135 logger::error (" before\n {} {} {}\n {} {} {}\n {} {} {}" , b[0 ][0 ], b[0 ][1 ], b[0 ][2 ], b[1 ][0 ], b[1 ][1 ], b[1 ][2 ], b[2 ][0 ],
110136 b[2 ][1 ], b[2 ][2 ]);
111137
112- clavicle2->world .rotate = original_C2_world_matrix * vec2vec_matrix3;
113- clavicle2->local .rotate = clavicle2->parent ->world .rotate .Transpose () * clavicle2->world .rotate ;
138+ clavicle2->world .rotate = vec2vec_matrix3*original_C2_world_matrix;
139+ clavicle2->local .rotate = clavicle2->parent ->world .rotate .Transpose () * (vec2vec_matrix3*original_C2_world_matrix);
140+
114141 auto a = clavicle2->world .rotate .entry ;
115142 logger::error (" after\n {} {} {}\n {} {} {}\n {} {} {}" , a[0 ][0 ], a[0 ][1 ], a[0 ][2 ], a[1 ][0 ], a[1 ][1 ], a[1 ][2 ], a[2 ][0 ], a[2 ][1 ],
116143 a[2 ][2 ]);
117- }
144+ RE::NiUpdateData data{0 .0f , RE::NiUpdateData::Flag::kDirty };
145+ obj->GetCurrent3D ()->Update (data);
146+
118147 }
148+
119149 }
120150
121151
@@ -129,15 +159,35 @@ namespace plugin {
129159 }
130160
131161 void GameEventHandler::onPostPostLoad () {
132- if (OriginalUpdatePtr == nullptr ) {
133- DetourTransactionBegin ();
134- DetourUpdateThread (GetCurrentThread ());
135- uintptr_t * ninode_vtable=(uintptr_t *)RE::VTABLE_NiNode[0 ].address ();
136- OriginalUpdatePtr = (void *) ninode_vtable[0x160 / 8 ];
137-
138- DetourAttach (&OriginalUpdatePtr, NiNodeUpdateHook);
139- DetourTransactionCommit ();
140-
162+ if (OriginalActorUpdatePtr == nullptr ) {
163+ {
164+ DetourTransactionBegin ();
165+ DetourUpdateThread (GetCurrentThread ());
166+ uintptr_t * actor_vtable = (uintptr_t *) RE::VTABLE_Actor[0 ].address ();
167+ OriginalActorUpdatePtr = (void *) actor_vtable[0xad ];
168+
169+ DetourAttach (&OriginalActorUpdatePtr, ActorUpdateHook);
170+ DetourTransactionCommit ();
171+ }
172+ {
173+ DetourTransactionBegin ();
174+ DetourUpdateThread (GetCurrentThread ());
175+ uintptr_t * player_vtable = (uintptr_t *) RE::VTABLE_PlayerCharacter[0 ].address ();
176+ OriginalPlayerUpdatePtr = (void *) player_vtable[0xad ];
177+
178+ DetourAttach (&OriginalPlayerUpdatePtr, PlayerUpdateHook);
179+ DetourTransactionCommit ();
180+ }
181+ {
182+ DetourTransactionBegin ();
183+ DetourUpdateThread (GetCurrentThread ());
184+
185+ OriginalPlayerUpdate3PPtr = (void *) REL::RelocationID (39446 , 40522 ).address ();
186+
187+ DetourAttach (&OriginalPlayerUpdate3PPtr, PlayerUpdate3PHook);
188+ DetourTransactionCommit ();
189+ }
190+
141191
142192 }
143193 logger::info (" onPostPostLoad()" );
0 commit comments