- 4
- 1
Насколько реально через Plugin SDK реализовать подмену создаваемых игрой машин в момент спавна в трафике, грубо говоря чтобы при спавне такси 420 спавнились рандомные машины из набора 445, 466, 516?
Я пробовал через Events::vehicleSetModelEvent, но чтобы не делал - ловил краши в момент создания модели, хотя перед этим загружал её в память, но нифига не вышло
UPD: Почти удалось с использованием следующего кода:
Но есть один нюанс: если модель 400 загружена в память до появления первой рандомной машины, то всё работает и весь трафик в одних Лендсталкерах. Если же я пытаюсь хоть как-то взаимодействовать с CStreaming, при этом даже просто проверяя загружена ли модель - игра нахуй вылетает. Как это исправить? И да, я использовал в том числе и нейронку, чтобы дойти до такого результата
Я пробовал через Events::vehicleSetModelEvent, но чтобы не делал - ловил краши в момент создания модели, хотя перед этим загружал её в память, но нифига не вышло
UPD: Почти удалось с использованием следующего кода:
C++:
#include <windows.h>
#include "CCarCtrl.h"
#include "CVehicle.h"
#include "CStreaming.h"
#include "MinHook.h"
// Линкуем MinHook
#pragma comment(lib, "MinHook.x86.lib")
// Прототип оригинальной функции
typedef CVehicle* (__cdecl* GetNewVehicleDependingOnCarModel_t)(int modelId, unsigned char createdBy);
GetNewVehicleDependingOnCarModel_t pOrigGetNewVehicleDependingOnCarModel = nullptr;
// Наш хук
CVehicle* __cdecl Hooked_GetNewVehicleDependingOnCarModel(int modelId, unsigned char createdBy) {
// Проверяем, что это именно случайный городской трафик (1 = RANDOM_CAR)
// Благодаря этому миссии (2) и припаркованные авто (3) не сломаются
if (createdBy == 1) {
modelId = 400;
// Проверяем, загружена ли модель в память игры
if (!CStreaming::HasModelLoaded(modelId)) {
// Запрашиваем модель с высоким приоритетом
CStreaming::RequestModel(modelId, 2);
// Заставляем стриминг мгновенно загрузить её из gta3.img
CStreaming::LoadAllRequestedModels(false);
}
// Защита от вылета 0x004C9691: если модель почему-то не загрузилась
// (например, критический затык стриминга), спавним оригинал во избежание краша
if (!CStreaming::HasModelLoaded(modelId)) {
return pOrigGetNewVehicleDependingOnCarModel(modelId, createdBy);
}
// Разрешаем игре удалить модель если не нужна
CStreaming::SetModelIsDeletable(modelId);
}
// Передаем управление в оригинальный движок
return pOrigGetNewVehicleDependingOnCarModel(modelId, createdBy);
}
void InitHooks() {
// Инициализируем MinHook
if (MH_Initialize() != MH_OK && MH_Initialize() != MH_ERROR_ALREADY_INITIALIZED) {
return;
}
// Ставим хук на CCarCtrl::GetNewVehicleDependingOnCarModel (0x421440)
void* target = (void*)0x421440;
if (MH_CreateHook(target, reinterpret_cast<void*>(&Hooked_GetNewVehicleDependingOnCarModel), reinterpret_cast<void**>(&pOrigGetNewVehicleDependingOnCarModel)) == MH_OK) {
MH_EnableHook(target);
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
InitHooks();
}
return TRUE;
}
Последнее редактирование: