static void DeinitLevel() { static bool initedLateHook = false; if (!initedLateHook) { // late hook to prevent scenario manager from reinitializing on map load - it messes things up, a lot, and I doubt custom maps use scenarios anyway. :) hook::put<uint16_t>(hook::pattern("83 F9 04 0F 85 F9 00 00 00").count(1).get(0).get<void>(3), 0xE990); // shutdown hook::put<uint16_t>(hook::pattern("83 F9 02 0F 85 C6 01 00 00").count(1).get(0).get<void>(3), 0xE990); // init // don't load mounted ped (personality) metadata anymore (temp dbg-y?) hook::nop(hook::pattern("48 8B DA 83 E9 14 74 5B").count(1).get(0).get<void>(0x72 - 12), 5); initedLateHook = true; } // stuff g_inLevelFree = true; g_deinitLevel(); shutdownModelInfo(1); initModelInfo(1); initStreamingInterface(); // extra content manager shutdown session removes these, and we want these before init session, so we scan them right here, right now. extraContentMgr__doScanInt(*g_extraContentMgr); extraContentMgr__doScanPost(*g_extraContentMgr, false, false); //shutdownPhysics(1); //initPhysics(1); // unknown value in the bounds streaming module, doesn't get cleared on 'after map loaded' shutdown *(uint32_t*)(g_boundsStreamingModule + 5664) = 0; // bounds streaming module, 'has preloading bounds completed' value *(uint8_t*)(g_boundsStreamingModule + 255) = 0; // clear the 'loaded cache hashes' list *g_cacheArray = atArray<allocWrap<uint32_t>>(16); // free one CScene list of all the bad influences from the last session ClearInteriorProxyList(g_sceneLinkedList); // also clear the interior proxy pool out, as it might contain garbage references to static bounds, still (*g_interiorProxyPool)->Clear(); // and some global vehicle audio entity also houses... interior proxies. *g_vehicleReflEntityArray = atArray<CInteriorProxy*>(); g_inLevelFree = false; if (!g_didLevelFree) { for (auto& stack : g_stacks) { FILE* f = fopen(va("D:\\dev\\stacks\\%p.txt", ((stack.first / 256) * 256)), "a"); if (f) { fprintf(f, "--- %p ---\n", stack.first); for (auto& entry : stack.second) { fprintf(f, "%p\n", entry); } fprintf(f, "--- --- ---\n"); fclose(f); } } g_stackIdx = 0; g_stacks.clear(); g_didLevelFree = true; } }
static void DeinitLevel() { static bool initedLateHook = false; if (!initedLateHook) { // late hook to prevent scenario manager from reinitializing on map load - it messes things up, a lot, and I doubt custom maps use scenarios anyway. :) hook::put<uint16_t>(hook::pattern("83 F9 04 0F 85 F9 00 00 00").count(1).get(0).get<void>(3), 0xE990); // shutdown hook::put<uint16_t>(hook::pattern("83 F9 02 0F 85 C6 01 00 00").count(1).get(0).get<void>(3), 0xE990); // init // don't load mounted ped (personality) metadata anymore (temp dbg-y?) hook::nop(hook::pattern("48 8B DA 83 E9 14 74 5B").count(1).get(0).get<void>(0x72 - 12), 5); // recreate interior proxy pool sanely //char* poolFn = hook::get_pattern<char>("41 0F B7 C6 4D 89 73 E8 41 8B F6 66 89 44 24 28", -0x23); //poolFn += 0xD4; //hook::nop(poolFn, 44); //hook::jump(poolFn, ClearInteriorProxyPool); initedLateHook = true; } // stuff g_inLevelFree = true; g_deinitLevel(); shutdownModelInfo(1); initModelInfo(1); initStreamingInterface(); //g_loadClipSets(); // extra content manager shutdown session removes these, and we want these before init session, so we scan them right here, right now. // TEMP REMOVE extraContentMgr__doScanInt(*g_extraContentMgr); extraContentMgr__doScanPost(*g_extraContentMgr, false, false); //shutdownPhysics(1); //initPhysics(1); // unknown value in the bounds streaming module, doesn't get cleared on 'after map loaded' shutdown int colCrashOffset = *hook::get_pattern<int>("0F B7 83 ? ? 00 00 BA FF 1F 00 00 66 33 C1 66", 3); int colCrashCountMax = (colCrashOffset - 464) / 4; *(uint32_t*)(g_boundsStreamingModule + colCrashOffset) = 0; // bounds streaming module, 'has preloading bounds completed' value *(uint8_t*)(g_boundsStreamingModule + 255) = 0; // clear the 'loaded cache hashes' list //*g_cacheArray = atArray<allocWrap<uint32_t>>(16); g_cacheArray->ClearCount(); // free one CScene list of all the bad influences from the last session ClearInteriorProxyList(g_sceneLinkedList); // also clear the interior proxy pool out, as it might contain garbage references to static bounds, still (*g_interiorProxyPool)->Clear(); // and some global vehicle audio entity also houses... interior proxies. *g_vehicleReflEntityArray = atArray<CInteriorProxy*>(); // clear interior proxies from render phases for (auto& pair : g_renderPhases) { CRenderPhaseScanned* renderPhase = pair.second; if (renderPhase->portalScanner) { trace("clearing %s interior proxy (was %p)\n", pair.first.c_str(), renderPhase->portalScanner->interiorProxy); renderPhase->portalScanner->interiorProxy = nullptr; } } g_inLevelFree = false; if (!g_didLevelFree) { for (auto& stack : g_stacks) { FILE* f = fopen(va("D:\\dev\\stacks\\%p.txt", ((stack.first / 256) * 256)), "a"); if (f) { fprintf(f, "--- %p ---\n", stack.first); for (auto& entry : stack.second) { fprintf(f, "%p\n", entry); } fprintf(f, "--- --- ---\n"); fclose(f); } } g_stackIdx = 0; g_stacks.clear(); g_didLevelFree = true; } }