You are not logged in.
Пока что тольок задумал способ "добавления" места в структуры фиксированного размера (будь то CPed, или CVehicle).
Пока что думаю сделать так (всё это можно сделать, изменяя игровые процедуры):
1) При создании педа (CPed::CPed) создавать новый буфер, указатель на него записать в структуру. Жертвуем полем структуры в 4 байт.
2) При удалении (CPed::~CPed) удаляем буфер.
3) Поле структуры, которым пожертвовали, теперь "перенести" в созданный буфер, т.е., заменить все ссылки к нему.
В общем, выглядит всё просто, есть ли тут какие-то неполадки, возможные сбои?
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Да, все просто, но а если игра сама захочет создать/разрушить CPed?
Offline
Метод, в общем, логичный.
Неиспользуемое поле в CPed - найти не вопрос. Как вариант - использовать поля CPlacement, которые используются только в статических объектах.
Проблема с созданием/удалением объекта решается перехватом конструктора и деструктора (~5 точек)
Offline
5 раз? Можно ли просто "пропатчить" конструктор и деструктор?
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Можно, но это тоже получится не меньше четырех точек (а делать это будет сложнее).
С одной стороны, приятно, что можно ограничиться только CPed (т.е. не нужно трогать CPlayerPed и CEmergencyPed), с дургой стороны, у CPed три конструктора и один деструктор (что и дает нам четыре точки)
Offline
А чем отличаются эти конструкторы?
И сколько их у CVehicle?
PS речь идёт о классах СА.
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Вот CLEO-версия *извращенец*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | { $CLEO } { RwMalloc = 0x72F420 RwFree = 0x72F430 refs to CPed.field_780 (turretPosMode) 0x5111E4 - mov ecx, [ebp+780h] , get 0x5E7EA8 - mov [esi+780h], edx , set } 0AC6: 0@ = label @ctor offset 0AC6: 1@ = label @ctorJmp offset 0AB1: call_scm_func @asmdef 4 asm_inj 0@ jump_from 0x5E812B then_jump 0x5E 8131 offset_jump_in_asm 1@ 0AC6: 0@ = label @dtor offset 0AC6: 1@ = label @dtorJmp offset 0AB1: call_scm_func @asmdef 4 asm_inj 0@ jump_from 0x5E 8656 then_jump 0x5E865F offset_jump_in_asm 1@ 0AC6: 0@ = label @field_780_get offset 0AC6: 1@ = label @field_780_getJmp offset 0AB1: call_scm_func @asmdef 4 asm_inj 0@ jump_from 0x5111E 4 then_jump 0x5111EA offset_jump_in_asm 1@ 0AC6: 0@ = label @field_780_set offset 0AC6: 1@ = label @field_780_setJmp offset 0AB1: call_scm_func @asmdef 4 asm_inj 0@ jump_from 0x5E7EA 8 then_jump 0x5E7EAE offset_jump_in_asm 1@ 0A93: :ctor hex 89 48 0C 89 48 10 B 8 20 F 4 72 00 // mov eax, 0x72F420 6A 64 // push 0x64 FF D 0 // call eax 89 30 // mov [eax], esi 89 86 80 07 00 00 // mov [esi+780h], eax 83 C 4 04 // add esp, 4 end :ctorJmp hex E 9 00 00 00 00 end :dtor hex 83 C 4 04 8B 86 80 07 00 00 // mov eax, [esi+780h] 85 C 0 // test eax, eax 74 0B // jz short 0xB 50 // push eax B 8 30 F 4 72 00 // mov eax, 0x72F430 FF D 0 // call eax 83 C 4 04 // add esp, 4 8A 86 77 04 00 00 A 8 01 end :dtorJmp hex E 9 00 00 00 00 end :field_780_get hex 8B 8D 80 07 00 00 // mov ecx, [ebp+780h] 8B 49 04 // mov ecx, [ecx+4] end :field_780_getJmp hex E 9 00 00 00 00 end :field_780_set hex 8B B 6 80 07 00 00 // mov esi, [esi+780h] 89 56 04 // mov [esi+4], edx end :field_780_setJmp hex E 9 00 00 00 00 end :asmdef 0A8C: write_memory 1@ size 1 value 0xE 9 virtual_protect 1 0085: 4@ = 1@ 4@ += 5 0062: 0@ -= 4@ 1@ += 1 0A8C: write_memory 1@ size 4 value 0@ virtual_protect 1 0085: 4@ = 3@ 4@ += 5 0062: 2@ -= 4@ 3@ += 1 0A8C: write_memory 3@ size 4 value 2@ virtual_protect 1 0AB2: ret 0 |
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Здравствуйте.
Решил всё это дело перенести в отдельный плугин, правда с изменениями.
Идея такая: выделяем под пул (CVehicle) массив указателей (размер массива - кол-во элементов в пуле). Этот указатель указывает на дополнительные буферы для структуры.
Информация об этих буферах хранится в списке (list).
В конструкторе (CVehicle::CVehicle) проходимся по этим буферам и инициализируем их. В деструкторе - деинициализация.
В общем, получилось такое:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | // Переменные void **vehicleAdditional; unsigned int vehiclePluginsSize; struct tStructPluginDesc { unsigned int size; unsigned int userId; void *constructor; void *destructor; }; list<tStructPluginDesc*>vehiclePlugins; // Функции void AllocateAdditionalData() { vehicleAdditional = new void *[(*(CPool< void *> **)0xB74494)->m_Size]; vehiclePluginsSize = 0; } void ReleaseVehicleAdditional() { delete [] vehicleAdditional; for (auto i = vehiclePlugins.begin(); i != vehiclePlugins.end(); ++i) delete i._Ptr->_Myval; } unsigned int plugin::StructPlugins::RegisterVehiclePlugin(unsigned int size, unsigned int userId, void *constructor, void *destructor) { tStructPluginDesc *plugin = new tStructPluginDesc; plugin->size = size; plugin->userId = userId; plugin->constructor = constructor; plugin->destructor = destructor; vehiclePlugins.push_back(plugin); unsigned int result = vehiclePluginsSize; vehiclePluginsSize += size; return result; } void *plugin::StructPlugins::GetVehiclePlugin(CVehicle *vehicle, unsigned int id) { unsigned int vehicleId = ((unsigned int )vehicle - (unsigned int )(*(CPool< void > **)0xB74494)->m_Objects) / 0xA18; return ( void *)((unsigned int )vehicleAdditional[vehicleId] + id); } void *FindVehiclePluginByUserId(CVehicle *vehicle, unsigned int userId) { unsigned int vehicleId = ((unsigned int )vehicle - (unsigned int )(*(CPool< void > **)0xB74494)->m_Objects) / 0xA18; unsigned int size = 0; for (auto i = vehiclePlugins.begin(); i != vehiclePlugins.end(); ++i) { if (i._Ptr->_Myval->userId == userId) return ( void *)((unsigned int )vehicleAdditional[vehicleId] + size); size += i._Ptr->_Myval->size; } return NULL; } void __fastcall OnVehicleConstructor(CVehicle *vehicle) { unsigned int vehicleId = ((unsigned int )vehicle - (unsigned int )(*(CPool< void > **)0xB74494)->m_Objects) / 0xA18; vehicleAdditional[vehicleId] = new __int8 [vehiclePluginsSize]; unsigned int size = 0; for (auto i = vehiclePlugins.begin(); i != vehiclePlugins.end(); ++i) { (( void (*)(CVehicle *, void *))i._Ptr->_Myval->constructor)(vehicle, ( void *)((unsigned int )vehicleAdditional[vehicleId] + size)); size += i._Ptr->_Myval->size; } }; void __fastcall OnVehicleDestructor(CVehicle *vehicle) { unsigned int vehicleId = ((unsigned int )vehicle - (unsigned int )(*(CPool< void > **)0xB74494)->m_Objects) / 0xA18; unsigned int size = 0; for (auto i = vehiclePlugins.begin(); i != vehiclePlugins.end(); ++i) { (( void (*)(CVehicle *, void *))i._Ptr->_Myval->destructor)(vehicle, ( void *)((unsigned int )vehicleAdditional[vehicleId] + size)); size += i._Ptr->_Myval->size; } delete vehicleAdditional[vehicleId]; }; |
Ну и использоваться будет примерно так (пример - структура для хранения информации о запасе бензина):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | // Регистрация буфера struct tVehicleGasolineData { float gasolineState; float fuelCapacity; unsigned int timeLastRefueled; }; unsigned int gGasolineDataId; void VehicleGasolineDataConstructor(CVehicle *vehicle, tVehicleGasolineData *gasoline) { gasoline->gasolineState = 1.0; gasoline->fuelCapacity = 1.0; gasoline->timeLastRefueled = 0; } void VehicleGasolineDataDestructor(CVehicle *vehicle, tVehicleGasolineData *gasoline) { } void RegisterGasolineStruct() { gGasolineDataId = plugin::StructPlugins::RegisterVehiclePlugin( sizeof (tVehicleGasolineData), 0xABCDEF, VehicleGasolineDataConstructor, VehicleGasolineDataDestructor); } |
1 2 3 4 5 | //Пример использование буфера float SetVehicleGasolineState(CVehicle *vehicle, float state) { ((tVehicleGasolineData *)plugin::StructPlugins::GetVehiclePlugin(vehicle, gGasolineDataId))->gasolineState = state; } |
Есть ли замечания по поводу такой реализации?)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Метод оказался полностью рабочим, я его уже задействовал в ImVehFt:
Last edited by DK22Pac (02-02-2014 15:34)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Да, всё это идёт в отдельной dll.
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
mfisto, да.
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Ты подключаешь файлы plugin.dll (хедеры) к себе в проект, и вызываешь функцию регистрации своих "ячеек".
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Пример с педами. При создании педа выбирается случайное имя, которое позже рисуется на экране.
Не могу прикрепить файл, вот, в общем pedNames.txt
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Поправил
Offline