Автор Тема: Написание плагина. Настройка проекта  (Прочитано 8693 раз)

Оффлайн kenking

  • Прохожий
  • *
  • Сообщений: 104
  • Репутация: +3/-0
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #150 : Апрель 15, 2017, 12:25:31 pm »
Проблема решилась сменой стиля
Код: C++
  1. CFont::SetFontStyle(0);
или
Код: C++
  1. CFont::SetFontStyle(2);

Оффлайн kenking

  • Прохожий
  • *
  • Сообщений: 104
  • Репутация: +3/-0
    • Просмотр профиля
Дмитрий, ранее в этой теме ты показывал пример, как заменить небольшую функцию на свою. Если функция большая, то такое сделать проблематично. Можно ли заменить подобным образом локальную функцию, т.е. часть большой функции? Интересует, например (GTA III) вот это дело - добавление моделей с возможностью выполнять миссию такси
.text:00446A93   loc_446A93:                             ; CODE XREF: CRunningScript::ProcessCommands700To799(int)+22j
.text:00446A93                                           ; DATA XREF: .data:off_5EF4D0o
.text:00446A93 0                 lea     eax, [edi+10h]  ; jumptable 004458C2 case 34
.text:00446A96 0                 mov     ecx, edi
.text:00446A98 0                 push    1
.text:00446A9A 0                 push    eax
.text:00446A9B 0                 call    _ZN14CRunningScript17CollectParametersEPjs ; CRunningScript::CollectParameters(uint *,short)
.text:00446AA0 0                 mov     ecx, ds:ScriptParams
.text:00446AA6 0                 xor     al, al
.text:00446AA8 0                 imul    ecx, 4Fh
.text:00446AAB 0                 mov     esi, ds:_ZN6CWorld7PlayersE[ecx*4] ; CWorld::Players
.text:00446AB2 0                 cmp     byte ptr [esi+314h], 0
.text:00446AB9 0                 jz      short loc_446ADC
.text:00446ABB 0                 mov     edx, [esi+310h]
.text:00446AC1 0                 movsx   ebx, word ptr [edx+5Ch]
.text:00446AC5 0                 cmp     ebx, 6Eh
.text:00446AC8 0                 jz      short loc_446ADA
.text:00446ACA 0                 cmp     ebx, 80h
.text:00446AD0 0                 jz      short loc_446ADA
.text:00446AD2 0                 cmp     ebx, 94h
.text:00446AD8 0                 jnz     short loc_446ADC


Код: C++
  1. case 0x2DEu:
  2.       CRunningScript::CollectParameters(a1, (CRunningScript *)(a1 + 16), (unsigned int *)1, v215);
  3.       flag = 0;
  4.       player = (CPlayerPed *)*(&CWorld::Players + 79 * ScriptParams);
  5.       if ( player->ped.m_bInVehicle )
  6.       {
  7.         modelIndex = *(_WORD *)(player->ped.m_pVehicle + offsetof(CEntity, m_nModelIndex));
  8.         if ( modelIndex == MODEL_TAXI || modelIndex == MODEL_CABBIE || modelIndex == MODEL_BORGNINE )
  9.           flag = 1;
  10.       }
  11.       CRunningScript::UpdateCompareFlag((CRunningScript *)v5, flag);
  12.       break;

Или тут проще "заменить" конкретные адреса
.text:00446AC5                  cmp     ebx, 6Eh
.text:00446ACA                  cmp     ebx, 80h
.text:00446AD2                  cmp     ebx, 94h

Просьба показать как это реализовать в sdk.

Оффлайн DK

  • Новичек
  • **
  • Сообщений: 175
  • Репутация: +250/-0
    • dk22pac
    • Просмотр профиля
Конкретно этот случай - это опкод, и тут есть свои особенности.

Есть много вариантов, опишу основные.

1. Используя CLEO SDK, написать замену опкоду 02DE.
+ самый рациональный способ. Тебе надо заменить стандартный опкод - в CLEO SDK это продумано - ты используешь CLEO SDK.
+ чистый и понятный код.
обязательно наличие библиотеки CLEO 2.0 (или выше).
надо писать весь код опкода.

2. Заменить весь (или почти весь) код опкода.
Сделать вызов своей функции, с 0x446A93. Функция при этом должна быть обьявлена как fastcall (чтобы в ecx получить структуру скрипта (CRunningScript).
В этой функции пишем весь код опкода, от получения параметров (CollectParameters) до записи результата (UpdateCompareFlag).
Кусок с 0x446A98 по 0x446AE4 заполняем no-op'ами.
Код: C++
  1. void __fastcall OpcodePlayerDrivingTaxiVehicle(CRunningScript *script) {
  2.     script->CollectParameters(&script->m_nIp, 1);
  3.     bool isTaxiModel = false;
  4.     // ...
  5.     script->UpdateCompareFlag(isTaxiModel);
  6. }
  7.  
  8. ...
  9.  
  10. patch::RedirectCall(0x446A93, OpcodePlayerDrivingTaxiVehicle);
  11. patch::Nop(0x446A98, 0x4C); // или сделать jump на 0x446AE4
+ более-менее чистый и понятный код.
надо писать весь код опкода.

3. Внедрять свой код по конкретному адресу, и заменить кое-какой кусок опкода (тот, где идет проверка id).
Тут тоже много вариантов.

3.1. Путём патчинга видоизменяем код в exe.
Проверка id начинается тут: 0x446AC5. id у нас записан в регистре ebx. начиная с адреса 0x446AC5, мы можем видоизменить код, чтобы он выглядел так:
Код: C++
  1. push ebx
  2. call CheckIfTaxiModel
  3. jmp 0x446ADC
Но тут также важно проследить, чтобы после вызова функции CheckIfTaxiModel не изменился регистр edi (в этом регистре хранится структура CRunningScript). Если будут проблемы - можно также перед вызовом функции добавить pushad, а после - popad.
Функция CheckIfTaxiModel должна принимать один параметр и возвращать true/false. Соглашение вызова - stdcall (можно сделать cdecl, и добавить 'add esp, 4' после вызова).
Код: C++
  1. bool __stdcall CheckIfTaxiModel(int id) {
  2.     bool isTaxiModel = false;
  3.     // ...
  4.     return isTaxiModel;
  5. }
  6.  
  7. ...
  8.  
  9. patch::SetUChar(0x446AC5, 0x53); // команда 'push ebx'
  10. patch::RedirectCall(0x446AC6, CheckIfTaxiModel); // call
  11. patch::RedirectJump(0x446ACB, 0x446ADC); // jump
+ не надо переписывать код опкода полностью - напишем только функцию, которая сверяет id и возвращает результат.
часть кода будет не совсем "прозрачной", а его написание может вызвать трудности (по сути, надо будет продумывать запись ассемблерных инструкций).
надо следить за регистрами.

3.2. Пишем функцию - ассемблерный код.
Код: C++
  1. void __declspec(naked) MyHook_446AC5() { // инжект по адресу 0x446AC5, в ebx записан id модели
  2. __asm {
  3.     cmp ebx, 110
  4.     jz SET_TRUE
  5.     cmp ebx, 128
  6.     jz SET_TRUE
  7.     cmp ebx, 148
  8.     jz SET_TRUE
  9.     cmp ebx, <какой-то id>
  10.     jz SET_TRUE
  11.     jmp END_CHECK
  12. SET_TRUE:
  13.     mov al, 1
  14. END_CHECK:
  15.     mov ecx, 0x446ADC
  16.     jmp ecx
  17. }
  18. }
  19.  
  20. ...
  21.  
  22. patch::RedirectJump(0x446AC5, MyHook_446AC5);

+ не надо переписывать код опкода полностью - пишем только код, который сверяет id.
надо писать ассемблерный код.
в коде будет присутствовать ассемблерный код.

3.3. Новый вид инжекта в plugin-sdk
Код: C++
  1. void MyCheckIfTaxiModel(int modelId, bool &result) {
  2.     result = false;
  3.     // ...    
  4. }
  5.  
  6. ...
  7.  
  8. InstallHook<0x446AC5, 0x17, reg<ebx>, reg<eax&>>(MyCheckIfTaxiModel);
  9. //          точка внедрения
  10. //                    размер кода, который мы пропускаем
  11. //                          получаемые параметры
  12. //                          регистр ebx - id модели
  13. //                                    регистр eax - для записи (&)
пока что только в разработке.

PS То, что показано в пункте 3.3 - это, так скажем, "обертка" над тем, что показано в пункте 3.1.

PPS Вариант 3.1.
Код: C++
  1. #include "plugin_III.h"
  2. #include "extensions\ScriptCommands.h"
  3.  
  4. using namespace plugin;
  5. using namespace plugin::test;
  6.  
  7. class OpcodeTaxi {
  8. public:
  9.     static bool __stdcall CheckIfTaxiModel(int id) {
  10.         switch (id) {
  11.         case 110:
  12.         case 128:
  13.         case 148:
  14.         case 146:
  15.             return true;
  16.         }
  17.         return false;
  18.     }
  19.  
  20.     OpcodeTaxi() {
  21.         patch::SetUChar(0x446AC5, 0x53); // команда 'push ebx'
  22.         patch::RedirectCall(0x446AC6, CheckIfTaxiModel); // call
  23.         patch::RedirectJump(0x446ACB, reinterpret_cast<void *>(0x446ADC)); // jump
  24.  
  25.         Events::processScriptsEvent += [] {
  26.             if (ScriptCommand<IS_PLAYER_IN_TAXI>(0))
  27.                 ScriptCommand<PRINT_NOW>("FEC_INC", 150, 1);
  28.         };
  29.     }
  30. } myPlugin;
« Последнее редактирование: Июнь 10, 2017, 02:47:48 am от DK »
Plugin-SDK
gta_sa.idb
Skype-конференция по моддингу https://join.skype.com/jqGbs97avigh

Оффлайн kenking

  • Прохожий
  • *
  • Сообщений: 104
  • Репутация: +3/-0
    • Просмотр профиля
Спасибо!
С учётом того, чтобы можно было добавить каждому свои модели изменил код так. Верно?
Код: C++
  1. #include "plugin_III.h"
  2. #include "extensions\ScriptCommands.h"
  3. #include <vector>
  4. #include <string>
  5. #include <sstream>
  6. #include <fstream>
  7. #include "game_III\common.h"
  8.  
  9. using namespace plugin;
  10. using namespace plugin::test;
  11. using namespace std;
  12.  
  13. vector<unsigned int> taxiIDs;
  14.  
  15. class OpcodeTaxi {
  16. public:
  17.    
  18.     static void ReadSettingsFile() {
  19.         ifstream stream("taxi.dat");
  20.         for (string line; getline(stream, line); ) {
  21.             if (line[0] != ';' && line[0] != '#') {
  22.                 if (!line.compare("taxi")) {
  23.                     while (line.compare("end") && getline(stream, line)) {
  24.                         if (line[0] != ';' && line[0] != '#') {
  25.                             stringstream ss(line);
  26.                             int i;
  27.                             while (ss >> i) {
  28.                                 taxiIDs.push_back(i);
  29.                                 if (ss.peek() == ',')
  30.                                     ss.ignore();
  31.                             }
  32.                         }
  33.                     }
  34.                 }
  35.             }
  36.         }
  37.     }
  38.  
  39.     static bool __stdcall CheckIfTaxiModel(unsigned int modelId) {
  40.         for (unsigned int i : taxiIDs) {
  41.             if (i == modelId)
  42.                 return true;
  43.         }
  44.         return false;
  45.     }
  46.  
  47.     OpcodeTaxi() {
  48.         ReadSettingsFile();
  49.         patch::SetUChar(0x446AC5, 0x53); // команда 'push ebx'
  50.         patch::RedirectCall(0x446AC6, CheckIfTaxiModel); // call
  51.         patch::RedirectJump(0x446ACB, reinterpret_cast<void *>(0x446ADC)); // jump
  52.  
  53.         Events::processScriptsEvent += [] {
  54.             CVehicle *vehicle = FindPlayerVehicle();
  55.             if (vehicle && vehicle->m_nVehicleSubType == VEHICLE_AUTOMOBILE) {
  56.                 CAutomobile *automobile = reinterpret_cast<CAutomobile *>(vehicle);
  57.                 CheckIfTaxiModel(automobile->m_nModelIndex);
  58.             };
  59.            
  60.             // или так
  61.             /*for (int i = 0; i < CPools::ms_pVehiclePool->m_Size; i++) {
  62.                 CVehicle *vehicle = CPools::ms_pVehiclePool->GetAt(i);
  63.                 if (vehicle && vehicle->m_nVehicleSubType == VEHICLE_AUTOMOBILE) {
  64.                     CAutomobile *automobile = reinterpret_cast<CAutomobile *>(vehicle);
  65.                     CheckIfTaxiModel(automobile->m_nModelIndex);
  66.                 };
  67.             };*/
  68.         };
  69.     }
  70. } myPlugin;

Работает исправно, но огонёк такси не работает на добавленных моделях. Команда
Код: C++
  1. ScriptCommand<SET_TAXI_LIGHTS>(1);
не срабатывает даже на стандартных такси, хотя соответствующий опкод в клео скрипте на стандартных такси срабатывает, а на дополнительных меняется значение флага m_nTaxiLightFlag (CAutomobile+0x4D9), но огонька такси при этом нет.

Функции
Код: C++
  1. CAutomobile::SetTaxiLight
и
Код: C++
  1. CAutomobile::SetAllTaxiLights
тоже не срабатывают.

Там ещё после CAutomobile::SetAllTaxiLights есть такое дело
Код: C++
  1. case 0x220:
  2.       CRunningScript::CollectParameters(this, (CRunningScript *)(this + 16), (unsigned int *)1, (__int16)v206);
  3.       CPool_CVehicle_CAutomobile_GetAt(ScriptParams);
  4.       flag = 0;
  5.       if ( *(_BYTE *)(v101 + offsetof(CAutomobile, m_nTaxiLightFlag)) & 7 )
  6.         flag = 1;
  7.       CRunningScript::UpdateCompareFlag((CRunningScript *)v3, flag);
  8.       result = 0;
  9.       break;

Может это? Больше не знаю где искать.  :(

Как это исправить (чтобы огнёк такси работал на дополнительных такси)?

Оффлайн DK

  • Новичек
  • **
  • Сообщений: 175
  • Репутация: +250/-0
    • dk22pac
    • Просмотр профиля
Что-то я тебе не совсем понимаю.
CheckIfTaxiModel - это проверка. Зачем её вызывать таким образом?
Код: C++
  1.             CVehicle *vehicle = FindPlayerVehicle();
  2.             if (vehicle && vehicle->m_nVehicleSubType == VEHICLE_AUTOMOBILE) {
  3.                 CAutomobile *automobile = reinterpret_cast<CAutomobile *>(vehicle);
  4.                 CheckIfTaxiModel(automobile->m_nModelIndex);
  5.             };
Код: C++
  1.                 CVehicle *vehicle = CPools::ms_pVehiclePool->GetAt(i);
  2.                 if (vehicle && vehicle->m_nVehicleSubType == VEHICLE_AUTOMOBILE) {
  3.                     CAutomobile *automobile = reinterpret_cast<CAutomobile *>(vehicle);
  4.                     CheckIfTaxiModel(automobile->m_nModelIndex);
  5.                 };

0220 - это опкод 0220:   car $car_handle has_car_bomb
В опкоде SET_TAXI_LIGHTS не один параметр, а два.
Plugin-SDK
gta_sa.idb
Skype-конференция по моддингу https://join.skype.com/jqGbs97avigh

Оффлайн kenking

  • Прохожий
  • *
  • Сообщений: 104
  • Репутация: +3/-0
    • Просмотр профиля
Что-то я тебе не совсем понимаю.
CheckIfTaxiModel - это проверка. Зачем её вызывать таким образом?
А так?
Код: C++
  1. #include "plugin_III.h"
  2. #include "extensions\ScriptCommands.h"
  3. #include <vector>
  4. #include <string>
  5. #include <sstream>
  6. #include <fstream>
  7.  
  8. using namespace plugin;
  9. using namespace plugin::test;
  10. using namespace std;
  11.  
  12. vector<unsigned int> taxiIDs;
  13.  
  14. class OpcodeTaxi {
  15. public:
  16.    
  17.     static void ReadSettingsFile() {
  18.         ifstream stream("taxi.dat");
  19.         for (string line; getline(stream, line); ) {
  20.             if (line[0] != ';' && line[0] != '#') {
  21.                 if (!line.compare("taxi")) {
  22.                     while (line.compare("end") && getline(stream, line)) {
  23.                         if (line[0] != ';' && line[0] != '#') {
  24.                             stringstream ss(line);
  25.                             int i;
  26.                             while (ss >> i) {
  27.                                 taxiIDs.push_back(i);
  28.                                 if (ss.peek() == ',')
  29.                                     ss.ignore();
  30.                             }
  31.                         }
  32.                     }
  33.                 }
  34.             }
  35.         }
  36.     }
  37.  
  38.     static bool __stdcall CheckIfTaxiModel(unsigned int id) {
  39.         for (unsigned int i = 0; i < taxiIDs.size(); i++) {
  40.             id = taxiIDs[i];
  41.             return true;
  42.         }
  43.         return false;
  44.     }
  45.  
  46.     OpcodeTaxi() {
  47.         ReadSettingsFile();
  48.         patch::SetUChar(0x446AC5, 0x53); // команда 'push ebx'
  49.         patch::RedirectCall(0x446AC6, CheckIfTaxiModel); // call
  50.         patch::RedirectJump(0x446ACB, reinterpret_cast<void *>(0x446ADC)); // jump
  51.  
  52.     }
  53. } myPlugin;

В опкоде SET_TAXI_LIGHTS не один параметр, а два.
Код: C++
  1. ScriptCommand<SET_TAXI_LIGHTS>(automobile, 1);
Ошибка при компиляции. Если ставить vehicle - то же самое. Что я делаю не так? Подскажи пожалуйста.

И вопрос по рабочим огонькам дополнительных такси в силе. Где искать? Как реализовать?

Оффлайн DK

  • Новичек
  • **
  • Сообщений: 175
  • Репутация: +250/-0
    • dk22pac
    • Просмотр профиля
Ты понимаешь, как работает опкод IS_PLAYER_IN_TAXI ?
Plugin-SDK
gta_sa.idb
Skype-конференция по моддингу https://join.skype.com/jqGbs97avigh

Оффлайн kenking

  • Прохожий
  • *
  • Сообщений: 104
  • Репутация: +3/-0
    • Просмотр профиля
Ты понимаешь, как работает опкод IS_PLAYER_IN_TAXI ?
Устанавливается флаг в ноль.
Проверяется игрок в авто или нет. Если в авто, то проверяется модель авто.
Если модель является MODEL_TAXI, MODEL_CABBIE или MODEL_BORGNINE, то флаг ставится в 1. Т.е. игрок в такси, иначе флаг остаётся 0, т.е. игрок не в такси.
Обновляется флаг.

Оффлайн kenking

  • Прохожий
  • *
  • Сообщений: 104
  • Репутация: +3/-0
    • Просмотр профиля
Путаница произошла из-за невнимательности. Я почему-то пропустил это
Цитировать
Проверка id начинается тут: 0x446AC5. id у нас записан в регистре ebx. начиная с адреса 0x446AC5, мы можем видоизменить код
Прошу прощения за проявленные тормоза.  ;D

Получается значит так
Код: C++
  1. #include "plugin_III.h"
  2. #include "extensions\ScriptCommands.h"
  3. #include <vector>
  4. #include <string>
  5. #include <sstream>
  6. #include <fstream>
  7.  
  8. using namespace plugin;
  9. using namespace plugin::test;
  10. using namespace std;
  11.  
  12. vector<unsigned int> taxiIDs;
  13.  
  14. class OpcodeTaxi {
  15. public:
  16.    
  17.     static void ReadSettingsFile() {
  18.         ifstream stream("taxi.dat");
  19.         for (string line; getline(stream, line); ) {
  20.             if (line[0] != ';' && line[0] != '#') {
  21.                 if (!line.compare("taxi")) {
  22.                     while (line.compare("end") && getline(stream, line)) {
  23.                         if (line[0] != ';' && line[0] != '#') {
  24.                             stringstream ss(line);
  25.                             int i;
  26.                             while (ss >> i) {
  27.                                 taxiIDs.push_back(i);
  28.                                 if (ss.peek() == ',')
  29.                                     ss.ignore();
  30.                             }
  31.                         }
  32.                     }
  33.                 }
  34.             }
  35.         }
  36.     }
  37.  
  38.     static bool __stdcall CheckIfTaxiModel(unsigned int id) {
  39.         for (unsigned int i : taxiIDs) {
  40.             if (i == id)
  41.                 return true;
  42.         }
  43.         return false;
  44.     }
  45.  
  46.     OpcodeTaxi() {
  47.         ReadSettingsFile();
  48.         patch::SetUChar(0x446AC5, 0x53); // команда 'push ebx'
  49.         patch::RedirectCall(0x446AC6, CheckIfTaxiModel); // call
  50.         patch::RedirectJump(0x446ACB, reinterpret_cast<void *>(0x446ADC)); // jump
  51.     }
  52. } myPlugin;


По команде SET_TAXI_LIGHTS и нерабочим огонькам на добавленных такси вопрос остаётся.

Оффлайн DK

  • Новичек
  • **
  • Сообщений: 175
  • Репутация: +250/-0
    • dk22pac
    • Просмотр профиля
В опкод надо передавать хендл, а не указатель.
По "огонькам" - думаю, надо посмотреть в месте, где создается корона.
Plugin-SDK
gta_sa.idb
Skype-конференция по моддингу https://join.skype.com/jqGbs97avigh

Оффлайн kenking

  • Прохожий
  • *
  • Сообщений: 104
  • Репутация: +3/-0
    • Просмотр профиля
В опкод надо передавать хендл, а не указатель.
Просьба показать пример, а то я сейчас опять наворочу чего попало, потом стыдно будет.  :(

По "огонькам" - думаю, надо посмотреть в месте, где создается корона.
В коронах я не нашёл. Но есть ещё опкод IS_TAXI. Может он на это влияет. Хотел сделать подобно показанному тобой примеру, но там id в eax, а номера для команды 'push eax' не знаю.
.text:00444CA5                 cmp     eax, 6Eh
.text:00444CA8                 jz      short loc_444CB8
.text:00444CAA                 cmp     eax, 80h
.text:00444CAF                 jz      short loc_444CB8
.text:00444CB1                 cmp     eax, 94h
.text:00444CB6                 jnz     short loc_444CBA
.text:00444CB8
.text:00444CB8 loc_444CB8:                             ; CODE XREF: CRunningScript::ProcessCommands600To699(int)+188j
.text:00444CB8                                         ; CRunningScript::ProcessCommands600To699(int)+18Fj
.text:00444CB8                 mov     dl, 1
.text:00444CBA
.text:00444CBA loc_444CBA:                             ; CODE XREF: CRunningScript::ProcessCommands600To699(int)+196j
.text:00444CBA                 mov     ecx, ebp        ; this

automobile->SetTaxiLight срабатывает для стандартных такси (для дополнительных только меняет флаг, а огонька нет), почему до этого не работало - загадка, хотя делал так же.  ???

Оффлайн DK

  • Новичек
  • **
  • Сообщений: 175
  • Репутация: +250/-0
    • dk22pac
    • Просмотр профиля
Код: C++
  1. ScriptCommand<SET_TAXI_LIGHTS>(CPools::GetVehicleRef(automobile), 1);

Цитировать
Хотел сделать подобно показанному тобой примеру, но там id в eax, а номера для команды 'push eax' не знаю.

Options > General... > Disassembly > Display disassembly line parts > Number of opcode bytes (non-graph) - поставить 8.

Не знаю, где ты искал. Вот, что у меня:

« Последнее редактирование: Июнь 16, 2017, 03:12:29 pm от DK »
Plugin-SDK
gta_sa.idb
Skype-конференция по моддингу https://join.skype.com/jqGbs97avigh

Оффлайн kenking

  • Прохожий
  • *
  • Сообщений: 104
  • Репутация: +3/-0
    • Просмотр профиля
Спасибо.
Получается это 0x537D1F
А каким образом добавить дополнительным такси огоньки?

Оффлайн DK

  • Новичек
  • **
  • Сообщений: 175
  • Репутация: +250/-0
    • dk22pac
    • Просмотр профиля
Можно сделать так: заменяем эти инструкции на свой код:
Код: C++
  1. 0x5373D7       movsx eax, word ptr [ebp+5Ch] // 4 байта
  2. 0x5373DB       lea edx, [eax-61h] // 3 байта

Код: C++
  1. void __declspec(naked) Patch_5373D7() {
  2.     __asm {
  3.         movsx eax, word ptr [ebp+5Ch]
  4.         pushad
  5.         push eax
  6.         call GetTranslatedTaxiModel // записываем в eax новый id модели - если сравниваемая модель - такси, то получим MODEL_TAXI
  7.         add esp, 4
  8.         popad
  9.         lea edx, [eax-61h]
  10.         mov edi, 0x5373DE
  11.         jmp edi
  12.     }
  13. }

Код: C++
  1. int GetTranslatedTaxiModel(int model) {
  2.     if (IsTaxiModel(model)) // какая-то функция, которая возвращает true/false
  3.         return MODEL_TAXI;
  4.     return model;
  5. }

Т.е., перед выполнением switch-а, подставляем в сравниваемый id MODEL_TAXI, если модель - такси.
« Последнее редактирование: Июнь 16, 2017, 07:10:00 pm от DK »
Plugin-SDK
gta_sa.idb
Skype-конференция по моддингу https://join.skype.com/jqGbs97avigh

Оффлайн kenking

  • Прохожий
  • *
  • Сообщений: 104
  • Репутация: +3/-0
    • Просмотр профиля
Спасибо за очередные пояснения.
« Последнее редактирование: Июль 20, 2017, 06:36:40 am от kenking »