Skip to content

Commit 1008f48

Browse files
authored
add an experimental workaround for mu dynamic normal map and other mods (WIP, may not work yet)
1 parent 001ecb9 commit 1008f48

1 file changed

Lines changed: 85 additions & 10 deletions

File tree

src/GameEventHandler.cpp

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ static bool print_flags = true;
2727
static bool overlay_culling_fix = true;
2828
static bool IS_LOADING_GAME = false;
2929
static bool force_decal = true;
30+
static bool mu_normal_setskin_workaround = false;
3031
RE::TESObjectREFR* GetUserDataFixed(RE::NiAVObject* obj) {
3132
auto* userData = REL::RelocateMember<RE::TESObjectREFR*>(obj, 0x0F8, 0x110);
3233
if (userData) {
@@ -39,10 +40,27 @@ RE::TESObjectREFR* GetUserDataFixed(RE::NiAVObject* obj) {
3940
}
4041
auto task_pool_ptr = (bool (*)(void)) nullptr;
4142
std::recursive_mutex morph_task_mutex;
43+
std::recursive_mutex qupdatenormalmap_lock;
4244
std::recursive_mutex loading_game_mutex;
4345
std::recursive_mutex custom_main_task_pool_lock;
4446
std::queue<std::function<void()>> custom_main_task_pool;
4547
auto original_process_task = (void (*)(void* main, void* arg2, void* arg3, void* arg4)) nullptr;
48+
auto qupdatenormalmap = (void (*)(void* arg1, RE::Actor* actor, int armor_slot_bit)) nullptr;
49+
auto original_setskin = (void (*)(RE::TESActorBase* actorbase, RE::TESObjectARMO* skin)) nullptr;
50+
static void setskin_hook (RE::TESActorBase* actorbase, RE::TESObjectARMO* skin) {
51+
if (original_setskin && qupdatenormalmap) {
52+
original_setskin(actorbase, skin);
53+
std::lock_guard l(qupdatenormalmap_lock);
54+
auto actor_forms = RE::TESDataHandler::GetSingleton()->GetFormArray<RE::Actor>();
55+
for (auto* actor:actor_forms) {
56+
if (actor && actor->GetActorBase()==actorbase) {
57+
qupdatenormalmap(nullptr, actor, 0xffffffff);
58+
}
59+
}
60+
61+
}
62+
}
63+
4664
static void ProcessMainTasks(void* main, void* arg2, void* arg3, void* arg4) {
4765
original_process_task(main, arg2, arg3, arg4);
4866
while (true) {
@@ -379,11 +397,18 @@ namespace plugin {
379397
}
380398
}
381399
}
400+
if (qupdatenormalmap) {
401+
if (auto actor = reference->As<RE::Actor>()) {
402+
std::lock_guard l(qupdatenormalmap_lock);
403+
qupdatenormalmap(nullptr, actor, 0xFFFFFFFF);
404+
}
405+
}
382406
} else {
383407
logger::error("not reversing overlays because 3D is not loaded or ref count too low");
384408
}
385409
}
386410
}
411+
387412
});
388413
}
389414

@@ -858,7 +883,7 @@ namespace plugin {
858883
}
859884
}
860885
//actor->Update3DModel();
861-
//
886+
//
862887
//actor->Update3DPosition(true);
863888
}
864889
}
@@ -877,15 +902,13 @@ namespace plugin {
877902
}
878903
static auto UpdateWorldDataTaskHook = (void (*)(uint64_t* TaskObj)) nullptr;
879904
static void UpdateWorldDataTask_fn(uint64_t* TaskObj) {
880-
881905
auto obj = (RE::NiAVObject*) (TaskObj[1]);
882906
RE::NiUpdateData data;
883907
data.time = 0;
884908
data.flags.set(RE::NiUpdateData::Flag::kDirty);
885909
data.flags.set(RE::NiUpdateData::Flag::kDisableCollision);
886910
obj->UpdateWorldData(&data);
887911
UpdateWorldDataTaskHook(TaskObj);
888-
889912
}
890913
#ifdef PARALLEL_MORPH_WORKAROUND
891914

@@ -1192,7 +1215,7 @@ namespace plugin {
11921215
static bool skip_load = false;
11931216
static bool vr_esl = true;
11941217
static bool do_samrim_name_fix = false;
1195-
1218+
11961219
auto LoadMainMenuOrig = (void (*)(uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4)) 0x0;
11971220
static void LoadMainMenuHook(uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4) {
11981221
{
@@ -1208,7 +1231,7 @@ namespace plugin {
12081231
ini["OverlayFix"]["reverse"] = "default";
12091232
ini["OverlayFix"]["skipload"] = "false";
12101233
ini["OverlayFix"]["nocull"] = "default";
1211-
ini["OverlayFix"]["forcedecal"] = "true";
1234+
ini["OverlayFix"]["forcedecal"] = "true";
12121235
ini["OverlayFix"]["hideunusedoverlays"] = "default";
12131236
ini["OverlayFix"]["savedanger"] = "default";
12141237
ini["OverlayFix"]["vresl"] = "default";
@@ -1218,14 +1241,15 @@ namespace plugin {
12181241
ini["OverlayFix"]["taskdelaycount"] = "60";
12191242
ini["OverlayFix"]["taskdelaymilliseconds"] = "4";
12201243
ini["OverlayFix"]["ragdollfix"] = "false";
1244+
ini["OverlayFix"]["mu_normal_setskin_workaround"] = "false";
12211245
spdlog::set_level(spdlog::level::info);
12221246
file.read(ini);
12231247
if (!ini["OverlayFix"].has("version")) {
12241248
ini["OverlayFix"]["version"] = "1";
12251249
ini["OverlayFix"]["reverse"] = "default";
12261250
ini["OverlayFix"]["skipload"] = "false";
12271251
ini["OverlayFix"]["nocull"] = "default";
1228-
ini["OverlayFix"]["forcedecal"] = "true";
1252+
ini["OverlayFix"]["forcedecal"] = "true";
12291253
ini["OverlayFix"]["hideunusedoverlays"] = "default";
12301254
ini["OverlayFix"]["savedanger"] = "default";
12311255
ini["OverlayFix"]["vresl"] = "default";
@@ -1235,6 +1259,7 @@ namespace plugin {
12351259
ini["OverlayFix"]["taskdelaycount"] = "60";
12361260
ini["OverlayFix"]["taskdelaymilliseconds"] = "4";
12371261
ini["OverlayFix"]["ragdollfix"] = "false";
1262+
ini["OverlayFix"]["mu_normal_setskin_workaround"] = "false";
12381263
}
12391264
if (atoi(ini["OverlayFix"]["taskdelaycount"].c_str()) > 0) {
12401265
delay_count = atoi(ini["OverlayFix"]["taskdelaycount"].c_str());
@@ -1243,8 +1268,11 @@ namespace plugin {
12431268
millisecond_delay = atoi(ini["OverlayFix"]["taskdelaymilliseconds"].c_str());
12441269
}
12451270
file.generate(ini);
1246-
if (ini["OverlayFix"]["forcedecal"]=="false") {
1247-
force_decal=false;
1271+
if (ini["OverlayFix"]["forcedecal"] == "false") {
1272+
force_decal = false;
1273+
}
1274+
if (ini["OverlayFix"]["mu_normal_setskin_workaround"] == "true") {
1275+
mu_normal_setskin_workaround = true;
12481276
}
12491277
if (ini["OverlayFix"]["hideunusedoverlays"] == "false") {
12501278
do_hide_unused_overlays = false;
@@ -1346,8 +1374,7 @@ namespace plugin {
13461374

13471375
#endif
13481376
if (do_ragdoll_fix) {
1349-
UpdateWorldDataTaskHook = (void (*)(uint64_t* TaskObj))(
1350-
(uint64_t) skee64_info.lpBaseOfDll + 0x129680);
1377+
UpdateWorldDataTaskHook = (void (*)(uint64_t* TaskObj))((uint64_t) skee64_info.lpBaseOfDll + 0x129680);
13511378
DetourTransactionBegin();
13521379
DetourUpdateThread(GetCurrentThread());
13531380
DetourAttach(&(PVOID&) UpdateWorldDataTaskHook, &UpdateWorldDataTask_fn);
@@ -2271,6 +2298,54 @@ namespace plugin {
22712298
DetourAttach(&(PVOID&) original_process_task, &ProcessMainTasks);
22722299
DetourTransactionCommit();
22732300
}
2301+
if (mu_normal_setskin_workaround) {
2302+
{
2303+
if (auto VM = RE::BSScript::Internal::VirtualMachine::GetSingleton()) {
2304+
RE::BSTSmartPointer<RE::BSScript::ObjectTypeInfo> classInfoPtr = nullptr;
2305+
VM->GetScriptObjectType1("MuDynamicNormalMap", classInfoPtr);
2306+
if (classInfoPtr) {
2307+
auto func_count = classInfoPtr->GetNumGlobalFuncs();
2308+
auto func_iter = classInfoPtr->GetGlobalFuncIter();
2309+
for (uint64_t i = 0; i < func_count; i = i + 1) {
2310+
if (auto func_ptr = (func_iter + i)) {
2311+
if (auto func = func_ptr->func) {
2312+
if (func->GetName() == RE::BSFixedString("QUpdateNormalmap") && func->GetIsNative()) {
2313+
qupdatenormalmap = (void (*)(void* arg1, RE::Actor* actor, int armor_slot_bit)) *
2314+
(uint64_t*) ((uint64_t) func.get() + 0x50);
2315+
}
2316+
}
2317+
}
2318+
}
2319+
}
2320+
}
2321+
}
2322+
{
2323+
if (auto VM = RE::BSScript::Internal::VirtualMachine::GetSingleton()) {
2324+
RE::BSTSmartPointer<RE::BSScript::ObjectTypeInfo> classInfoPtr = nullptr;
2325+
VM->GetScriptObjectType1("ActorBase", classInfoPtr);
2326+
if (classInfoPtr) {
2327+
auto func_count = classInfoPtr->GetNumMemberFuncs();
2328+
auto func_iter = classInfoPtr->GetMemberFuncIter();
2329+
for (uint64_t i = 0; i < func_count; i = i + 1) {
2330+
if (auto func_ptr = (func_iter + i)) {
2331+
if (auto func = func_ptr->func) {
2332+
if (func->GetName() == RE::BSFixedString("SetSkin") && func->GetIsNative()) {
2333+
original_setskin = (void (*)(RE::TESActorBase* actorbase, RE::TESObjectARMO* skin)) *
2334+
(uint64_t*) ((uint64_t) func.get() + 0x50);
2335+
}
2336+
}
2337+
}
2338+
}
2339+
}
2340+
if (original_setskin) {
2341+
DetourTransactionBegin();
2342+
DetourUpdateThread(GetCurrentThread());
2343+
DetourAttach(&(PVOID&) original_setskin, &setskin_hook);
2344+
DetourTransactionCommit();
2345+
}
2346+
}
2347+
}
2348+
}
22742349
logger::info("onPostPostLoad()");
22752350
}
22762351

0 commit comments

Comments
 (0)