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

Оффлайн kenking

  • Новичок
  • **
  • Сообщений: 237
  • Репутация: +16/-0
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #120 : Октября 08, 2016, 05:45:58 pm »
Это вызов метода из таблицы виртуальных методов (virtual table, "vtable").

А так можно записать?
Код: C++
  1. // Converted from float CVehicle::GetDooorAngleOpenRatio(uint door) 0x871EF4
  2. float CVehicle::GetDooorAngleOpenRatio(unsigned int door)
  3. {
  4.     return ((float (__thiscall *)(CVehicle*, unsigned int))0x871EF4)(this, door);
  5. }


Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #121 : Октября 08, 2016, 06:30:22 pm »
Можно. Но не надо. Этот метод является виртуальным.
У каждого класса из иерархии CVehicle есть (или может быть) своя реализация метода GetDooorAngleOpenRatio, и вызывать его надо именно из виртуальной таблицы.

Обычный метод
Код: C++
  1. CBike *bike = new CBike(...);
  2. CVehicle *vehicle = bike;
  3. vehicle->GetDooorAngleOpenRatio(); // вызываем CVehicle::GetDooorAngleOpenRatio. Вызывается 0x871EF4
  4. CAutomobile *automobile = new CAutomobile(...);
  5. vehicle = automobile;
  6. vehicle->GetDooorAngleOpenRatio(); // вызываем CVehicle::GetDooorAngleOpenRatio. Вызывается 0x871EF4

Виртуальный метод
Код: C++
  1. CBike *bike = new CBike(...); // при конструктировании CBike, по офсету +0 записывается указатель на таблицу виртуальных методов CBike
  2. CVehicle *vehicle = bike;
  3. vehicle->GetDooorAngleOpenRatio(); // вызываем CBike::GetDooorAngleOpenRatio. Вызывается vehicle->таблица->GetDooorAngleOpenRatio
  4. CAutomobile *automobile = new CAutomobile(...); // при конструктировании CAutomobile, по офсету +0 записывается указатель на таблицу виртуальных методов CAutomobile
  5. vehicle = automobile;
  6. vehicle->GetDooorAngleOpenRatio(); // вызываем CAutomobile::GetDooorAngleOpenRatio. Вызывается vehicle->таблица->GetDooorAngleOpenRatio

« Последнее редактирование: Октября 08, 2016, 06:55:45 pm от DK »
Plugin-SDK https://github.com/DK22Pac/plugin-sdk

Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv

Оффлайн kenking

  • Новичок
  • **
  • Сообщений: 237
  • Репутация: +16/-0
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #122 : Октября 08, 2016, 07:41:29 pm »
Если я правильно понял, то тогда для VC, например, будет так:

// CVehicle.h
Код: C++
  1. // component index in m_apModelNodes array
  2. void GetComponentWorldPosition(int componentId, CVector& posnOut);

// CVehicle.cpp
Код: C++
  1. // Converted from void CVehicle::GetComponentWorldPosition(int componentId,CVector &posnOut) 0x69CA40
  2. void CVehicle::GetComponentWorldPosition(int componentId, CVector& posnOut)
  3. {
  4.     ((void (__thiscall *)(CVehicle*, int, CVector&))(*(void ***)this)[19])(this, componentId, posnOut);
  5. }

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #123 : Октября 08, 2016, 08:01:51 pm »
Я все обьявления и определения (методов класса) генерировал автоматом.
Могу и тебе эту программу подогнать  :)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk

Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv

Оффлайн Shagg_E

  • Администратор
  • Постоялец
  • *****
  • Сообщений: 720
  • Репутация: +24/-4
  • Изобретательный Рукожопъ
    • Просмотр профиля
    • NewRockstar
Re: Написание плагина. Настройка проекта
« Ответ #124 : Октября 08, 2016, 09:18:55 pm »
DK, я просто нашел в кучи всевдокода момент, когда происходит именно то, что мне нужно(отключение/включение управления), и так повезло, что от себя ничего практически добавлять не пришлось(иначе я бы с этим не справился):
Там объявлялась переменная именно __int16, я не стал ничего додумывать и у меня это так:
Код: C++
  1. __int16 *GetPadInt;
Ниже используется функция, возвращающая(как я понял) поинтер пада, поэтому я объявил эту функцию:
Код: C++
  1. auto    _GetPad         = (__int16* (_cdecl*)(signed int pad))0x4AB060;  // Returns Player Controls Pointer
И всё! Дальше по-сути чисто копипаста псевдокода с моими комментариями:
Код: C++
  1. GetPadInt = _GetPad(0); // get Player Controls Pointer
  2. GetPadInt[120] |= 0x20u; // Disable Player Controls
и
Код: C++
  1. GetPadInt = _GetPad(0); // get Player Controls Pointer
  2. GetPadInt[120] &= 0xFFDFu; // Enable Player Controls
Если бы паста не сработала, то у меня ничего бы не вышло, т.к. сам я еще так не разбирал эти побайтовые/побитовые смещения...
Просто я не думаю, что буду особо углубляться в программирование(хочу больше ковырять моделирование и анимацию), а на данном этапе мне требовалось лишь заставить это работать, и оно(к счастью) работает ;D
Цитировать
Почему именно 5-ый бит - открывай калькулятор в режиме "Программист" и разбирайся :)
Да вот тут опять загвоздка - я не понимаю, почему 5й, а не 6й бит(если считать справа налево), ведь 6й становится нулем:
https://gyazo.com/15f6431c36f38e5ceb3451e93cf1f352
И последний вопрос: если есть адрес массива float a, то являются ли следующие варианты идентичными:
Код: C++
  1. b=*a[2];
  2. b=*a+8;
?
Извиняюсь за флуд, просто случайно заметил, как зашла речь про то, непонимание чего меня мучило...
« Последнее редактирование: Октября 08, 2016, 09:26:13 pm от Shagg_E »

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #125 : Октября 08, 2016, 10:07:49 pm »
Да, эта функция возвращает указатель на CPad.
Код: C++
  1. CPad *CPad::GetPad(int padNumber)
Цитировать
Да вот тут опять загвоздка - я не понимаю, почему 5й, а не 6й бит(если считать справа налево), ведь 6й становится нулем:
5ый - потому, что биты обычно считают от нуля. Даже в калькуляторе это видно.
Цитировать
И последний вопрос: если есть адрес массива float a, то являются ли следующие варианты идентичными:
Нет.
Обе записи неверны.
Код: C++
  1. b=*a[2];
Если a - это массив float, то ты получаешь элемент с индексом 2 и читаешь значение по адресу, который лежит в этом элементе. Компилятор должен выдать ошибку.
Код: C++
  1. b=*a+8;
Тут читается значение первого элемента и к нему прибавляется 8.

Код: C++
  1. float a[3]; // обявляем массив из 3-х float.
  2. float first = a[0]; // получили первый элемент в массиве
  3. float first = *a; // получили первый элемент в массиве
  4.  
  5. float third = a[2]; // получили третий элемент в массиве
  6. float third = *(a + 2); // получили третий элемент в массиве
  7. float third = *(float *)((unsigned char *)a + 8); // получили третий элемент в массиве
Plugin-SDK https://github.com/DK22Pac/plugin-sdk

Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv

Оффлайн Shagg_E

  • Администратор
  • Постоялец
  • *****
  • Сообщений: 720
  • Репутация: +24/-4
  • Изобретательный Рукожопъ
    • Просмотр профиля
    • NewRockstar
Re: Написание плагина. Настройка проекта
« Ответ #126 : Октября 08, 2016, 10:18:43 pm »
Аа, теперь всё ясно, спасибо.

Оффлайн kenking

  • Новичок
  • **
  • Сообщений: 237
  • Репутация: +16/-0
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #127 : Октября 09, 2016, 06:47:49 am »
Я все обьявления и определения (методов класса) генерировал автоматом.
Могу и тебе эту программу подогнать  :)
Было бы хорошо.  :)


UPD:
В CVehicleModelInfo.h некоторые функции объявлены как статические, например
Код: C++
  1. static void AddWheelUpgrade(int wheelSetNumber, int modelId);

при попытке определить такую функцию так
Код: C++
  1. // Converted from stdcall void CVehicleModelInfo::AddWheelUpgrade(int wheelSetNumber, int modelId) 0x4C8700
  2. void CVehicleModelInfo::AddWheelUpgrade(int wheelSetNumber, int modelId)
  3. {
  4.     ((void(__cdecl *)(CVehicleModelInfo*, int, int))0x4C8700)(this, wheelSetNumber, modelId);
  5. }

выходит "оператор this можно использовать только внутри не статической функции-члена"
Убрать static или как определять эту функцию?

И ещё просьба пояснить момент с определением __cdecl или __thiscall
IDA верно определяет этот момент или не всегда? Как самому в этом разобраться?
« Последнее редактирование: Октября 09, 2016, 08:59:51 am от kenking »

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #128 : Октября 09, 2016, 10:40:56 am »
В CVehicleModelInfo.h некоторые функции объявлены как статические, например

выходит "оператор this можно использовать только внутри не статической функции-члена"

Всё верно. Статическая функция - это обычно __cdecl, а не __thiscall, и там this (указатель на обьект класса) не нужен.
Статическая функция не привязана к обьекту, она является общей для всех обьектов.
http://ru.stackoverflow.com/a/373738
Убрать static или как определять эту функцию?

Нет. Надо вызывать как __cdecl, без передачи this (CVehicleModelInfo*)
И ещё просьба пояснить момент с определением __cdecl или __thiscall
IDA верно определяет этот момент или не всегда?

Почти всегда - верно.
Если у функции соглашение вызова __thiscall - это нестатический метод какого-то класса.
Если у функции соглашение вызова __cdecl - это либо не член класса, либо статический метод какого-то класса.
Код: C++
  1. void Func(){} // __cdecl
  2.  
  3. class A {
  4.     A() {} // thiscall
  5.     ~A() {} // thiscall
  6.     void SomeMethod() {} // thiscall
  7.     static void SomeStaticMethod() {} // cdecl
  8. };
Как самому в этом разобраться?

1. В первую очеред смотреть, что выдает декомпилятор.
2. Можно также глянуть в ассемблерный код. this всегда передается в регистре ecx, т.е. перед вызовом функции в ecx должен быть указатель на экземпляр класса.
Также, thiscall всегда сам за собой "чистит" стек. Если в thiscall-метод передается 1 параметр (кроме this), то при возврате функции, вместо обычного retn, будет такой опкод:
Код: C++
  1. retn 4 // Смещаем стек на 1 параметр (1 параметр = 4 байта)

_cheatWeaponSet


CPed::GiveWeapon


https://sannybuilder.com/forums/viewtopic.php?id=159

3. Обычно из названия функции можно понять - работает ли она с конкретным экземпляром класса, или является "общей".
Например,
Код: C++
  1. CPed::GiveWeapon - скорее всего, нестатический метод
  2. CPed::InitAllPeds - скорее всего, статический метод

Ко второму пункту я обращаюсь только в редких случаях.

PS Нашёл ещё одну познавательную статью от listener'а
https://sannybuilder.com/forums/viewtopic.php?id=845

UPD:
Кстати, обрати внимание, что в примерах, которые я показываю, я обьявляю функции внутри классов как статические. Это делается, потому что в "Эвенты" нельзя передавать thiscall-функции.
Код: C++
  1. class Test {
  2.     static void GameProcess() { // __cdecl
  3.         /*
  4.         Из статического метода мы не имеем доступа к нестатическим функциям/переменным
  5.         ...
  6.         */
  7.         value = 0;
  8.         value = GetRandomValue();
  9.     }
  10.  
  11.     static int value; // поэтому переменные, которые мы хочем использовать в GameProcess(), мы обьявляем тоже как статические
  12.     static int GetRandomValue() { return rand(); } // это же касается и функций.
  13.  
  14.     Test() {
  15.         Events::gameProcessEvent += GameProcess;
  16.     }
  17. } test;
  18.  
  19. int Test::value;
« Последнее редактирование: Октября 09, 2016, 11:09:01 am от DK »
Plugin-SDK https://github.com/DK22Pac/plugin-sdk

Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv

Оффлайн kenking

  • Новичок
  • **
  • Сообщений: 237
  • Репутация: +16/-0
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #129 : Октября 09, 2016, 02:37:48 pm »
Спасибо за пояснения.
Определил все функции, что были объявлены в CVehicleModelInfo.h
и добавил ещё
Код: C++
  1. int GetNumDoors();

Просьба проверить верно ли я понял вышеизложенное
Код: C++
  1. #include "CVehicleModelInfo.h"
  2.  
  3. RwTexture *CVehicleModelInfo::ms_pRemapTexture = (RwTexture *)0xB4E47C;
  4. RwTexture *CVehicleModelInfo::ms_pLightsTexture = (RwTexture *)0xB4E68C;
  5. RwTexture *CVehicleModelInfo::ms_pLightsOnTexture = (RwTexture *)0xB4E690;
  6. unsigned char *CVehicleModelInfo::ms_currentCol = (unsigned char *)0xB4E3F0;
  7. CRGBA *CVehicleModelInfo::ms_vehicleColourTable = (CRGBA *)0xB4E480;
  8.  
  9. void CVehicleModelInfo::ShutdownLightTexture()
  10. {
  11.     ((void(__cdecl *)())0x4C7470)();
  12. }
  13.  
  14. RwTexture * CVehicleModelInfo::FindTextureCB(char const * name)
  15. {
  16.     return ((RwTexture* (__cdecl *)(char const*))0x4C7510)(name);
  17. }
  18.  
  19. void CVehicleModelInfo::UseCommonVehicleTexDicationary()
  20. {
  21.     ((void(__cdecl *)())0x4C75A0)();
  22. }
  23.  
  24. void CVehicleModelInfo::StopUsingCommonVehicleTexDicationary()
  25. {
  26.     ((void(__cdecl *)())0x4C75C0)();
  27. }
  28.  
  29. RpAtomic * CVehicleModelInfo::MoveObjectsCB(RwObject * object, void * data)
  30. {
  31.     return ((RpAtomic* (__cdecl *)(RwObject*, void*))0x4C7700)(object, data);
  32. }
  33.  
  34. RpAtomic * CVehicleModelInfo::HideDamagedAtomicCB(RpAtomic * atomic, void * data)
  35. {
  36.     return ((RpAtomic* (__cdecl *)(RpAtomic*, void*))0x4C7720)(atomic, data);
  37. }
  38.  
  39. RpAtomic * CVehicleModelInfo::HideAllComponentsAtomicCB(RpAtomic * atomic, void * data)
  40. {
  41.     return ((RpAtomic* (__cdecl *)(RpAtomic*, void*))0x4C7790)(atomic, data);
  42. }
  43.  
  44. RpMaterial * CVehicleModelInfo::HasAlphaMaterialCB(RpMaterial * material, void * data)
  45. {
  46.     return ((RpMaterial* (__cdecl *)(RpMaterial*, void*))0x4C77C0)(material, data);
  47. }
  48.  
  49. RpAtomic * CVehicleModelInfo::SetAtomicRendererCB(RpAtomic * atomic, void * data)
  50. {
  51.     return ((RpAtomic* (__cdecl *)(RpAtomic*, void*))0x4C77E0)(atomic, data);
  52. }
  53.  
  54. RpAtomic * CVehicleModelInfo::SetAtomicRendererCB_RealHeli(RpAtomic * atomic, void * data)
  55. {
  56.     return ((RpAtomic* (__cdecl *)(RpAtomic*, void*))0x4C7870)(atomic, data);
  57. }
  58.  
  59. RpAtomic * CVehicleModelInfo::SetAtomicRendererCB_Plane(RpAtomic * atomic, void * data)
  60. {
  61.     return ((RpAtomic* (__cdecl *)(RpAtomic*, void*))0x4C7930)(atomic, data);
  62. }
  63.  
  64. RpAtomic * CVehicleModelInfo::SetAtomicRendererCB_Boat(RpAtomic * atomic, void * data)
  65. {
  66.     return ((RpAtomic* (__cdecl *)(RpAtomic*, void*))0x4C79A0)(atomic, data);
  67. }
  68.  
  69. RpAtomic * CVehicleModelInfo::SetAtomicRendererCB_Heli(RpAtomic * atomic, void * data)
  70. {
  71.     return ((RpAtomic* (__cdecl *)(RpAtomic*, void*))0x4C7A30)(atomic, data);
  72. }
  73.  
  74. RpAtomic * CVehicleModelInfo::SetAtomicRendererCB_Train(RpAtomic * atomic, void * data)
  75. {
  76.     return ((RpAtomic* (__cdecl *)(RpAtomic*, void*))0x4C7AA0)(atomic, data);
  77. }
  78.  
  79. void CVehicleModelInfo::SetAtomicRenderCallbacks()
  80. {
  81.     ((void(__thiscall *)(CVehicleModelInfo*))0x4C7B10)(this);
  82. }
  83.  
  84. RwObject * CVehicleModelInfo::SetAtomicFlagCB(RwObject * object, void * data)
  85. {
  86.     return ((RwObject* (__cdecl *)(RwObject*, void*))0x4C7B90)(object, data);
  87. }
  88.  
  89. // Converted from stdcall RwObject* CVehicleModelInfo::ClearAtomicFlagCB(RwObject *object, void *data) 0x4C7BB0
  90. RwObject* CVehicleModelInfo::ClearAtomicFlagCB(RwObject* object, void* data)
  91. {
  92.     return ((RwObject* (__cdecl *)(RwObject*, void*))0x4C7BB0)(object, data);
  93. }
  94.  
  95. // Converted from thiscall void CVehicleModelInfo::SetVehicleComponentFlags(RwFrame *component, unsigned int flags) 0x4C7C10
  96. void CVehicleModelInfo::SetVehicleComponentFlags(RwFrame* component, unsigned int flags)
  97. {
  98.     ((void(__thiscall *)(CVehicleModelInfo*, RwFrame*, unsigned int))0x4C7C10)(this, component, flags);
  99. }
  100.  
  101. // Converted from thiscall void CVehicleModelInfo::GetWheelPosn(int wheel, CVector &outVec, bool local) 0x4C7D20
  102. void CVehicleModelInfo::GetWheelPosn(int wheel, CVector& outVec, bool local)
  103. {
  104.     ((void(__thiscall *)(CVehicleModelInfo*, CVector&, bool))0x4C7D20)(this, outVec, local);
  105. }
  106.  
  107. // Converted from thiscall bool CVehicleModelInfo::GetOriginalCompPosition(CVector &outVec, int component) 0x4C7DD0
  108. bool CVehicleModelInfo::GetOriginalCompPosition(CVector& outVec, int component)
  109. {
  110.     return ((bool(__thiscall *)(CVehicleModelInfo*, CVector&, int))0x4C7DD0)(this, outVec, component);
  111. }
  112.  
  113. // Converted from thiscall int CVehicleModelInfo::ChooseComponent(void) 0x4C8040
  114. int CVehicleModelInfo::ChooseComponent()
  115. {
  116.     return ((int(__thiscall *)(CVehicleModelInfo*))0x4C8040)(this);
  117. }
  118.  
  119. // Converted from thiscall int CVehicleModelInfo::ChooseSecondComponent(void) 0x4C8120
  120. int CVehicleModelInfo::ChooseSecondComponent()
  121. {
  122.     return ((int(__thiscall *)(CVehicleModelInfo*))0x4C8120)(this);
  123. }
  124.  
  125. // Converted from thiscall bool CVehicleModelInfo::IsUpgradeAvailable(VehicleUpgradePosn upgrade) 0x4C8200
  126. bool CVehicleModelInfo::IsUpgradeAvailable(VehicleUpgradePosn upgrade)
  127. {
  128.     return ((bool(__thiscall *)(CVehicleModelInfo*, VehicleUpgradePosn))0x4C8200)(this, upgrade);
  129. }
  130.  
  131. RpMaterial * CVehicleModelInfo::SetEditableMaterialsCB(RpMaterial * material, void * data)
  132. {
  133.     return ((RpMaterial* (__cdecl *)(RpMaterial*, void*))0x4C8220)(material, data);
  134. }
  135.  
  136. RpAtomic * CVehicleModelInfo::SetEditableMaterialsCB(RpAtomic * atomic, void * data)
  137. {
  138.     return ((RpAtomic* (__cdecl *)(RpAtomic*, void*))0x4C83E0)(atomic, data);
  139. }
  140.  
  141. // Converted from stdcall void CVehicleModelInfo::SetEditableMaterials(RpClump *clump) 0x4C8430
  142. void CVehicleModelInfo::SetEditableMaterials(RpClump* clump)
  143. {
  144.     ((void(__cdecl *)(RpClump*))0x4C8430)(clump);
  145. }
  146.  
  147. // Converted from stdcall void CVehicleModelInfo::ResetEditableMaterials(RpClump *clump) 0x4C8460
  148. void CVehicleModelInfo::ResetEditableMaterials(RpClump* clump)
  149. {
  150.     ((void(__cdecl *)(RpClump*))0x4C8460)(clump);
  151. }
  152.  
  153. // Converted from thiscall void CVehicleModelInfo::SetVehicleColour(unsigned char prim, unsigned char sec, unsigned char tert, unsigned char quat) 0x4C84B0
  154. void CVehicleModelInfo::SetVehicleColour(unsigned char prim, unsigned char sec, unsigned char tert, unsigned char quat)
  155. {
  156.     ((void(__thiscall *)(CVehicleModelInfo*, unsigned char, unsigned char, unsigned char, unsigned char))0x4C84B0)(this, prim, sec, tert, quat);
  157. }
  158.  
  159. // Converted from thiscall void CVehicleModelInfo::ChooseVehicleColour(unsigned char &prim, unsigned char &sec, unsigned char &tert, unsigned char &quat, int variationShift) 0x4C8500
  160. void CVehicleModelInfo::ChooseVehicleColour(unsigned char& prim, unsigned char& sec, unsigned char& tert, unsigned char& quat, int variationShift)
  161. {
  162.     ((void(__thiscall *)(CVehicleModelInfo*, unsigned char&, unsigned char&, unsigned char&, unsigned char&, int))0x4C8500)(this, prim, sec, tert, quat, variationShift);
  163. }
  164.  
  165. // Converted from thiscall int CVehicleModelInfo::GetNumRemaps(void) 0x4C86B0
  166. int CVehicleModelInfo::GetNumRemaps()
  167. {
  168.     return ((int(__thiscall *)(CVehicleModelInfo*))0x4C86B0)(this);
  169. }
  170.  
  171. // Converted from thiscall void CVehicleModelInfo::AddRemap(int txd) 0x4C86D0
  172. void CVehicleModelInfo::AddRemap(int txd)
  173. {
  174.     ((void(__thiscall *)(CVehicleModelInfo*, int))0x4C86D0)(this, txd);
  175. }
  176.  
  177. // Converted from stdcall void CVehicleModelInfo::AddWheelUpgrade(int wheelSetNumber, int modelId) 0x4C8700
  178. void CVehicleModelInfo::AddWheelUpgrade(int wheelSetNumber, int modelId)
  179. {
  180.     ((void(__cdecl *)(int, int))0x4C8700)(wheelSetNumber, modelId);
  181. }
  182.  
  183. int CVehicleModelInfo::GetNumWheelUpgrades(int wheelSetNumber)
  184. {
  185.     return ((int(__cdecl *)(int))0x4C8740)(wheelSetNumber);
  186. }
  187.  
  188. void CVehicleModelInfo::GetWheelUpgrade(int wheelSetNumber, int wheelUpgradeNumber)
  189. {
  190.     ((void(__cdecl *)(int, int))0x4C8750)(wheelSetNumber, wheelUpgradeNumber);
  191. }
  192.  
  193. void CVehicleModelInfo::DeleteVehicleColourTextures()
  194. {
  195.     ((void(__cdecl *)())0x4C8770)();
  196. }
  197.  
  198. void CVehicleModelInfo::LoadEnvironmentMaps()
  199. {
  200.     ((void(__cdecl *)())0x4C8780)();
  201. }
  202.  
  203. void CVehicleModelInfo::ShutdownEnvironmentMaps()
  204. {
  205.     ((void(__cdecl *)())0x4C87D0)();
  206. }
  207.  
  208. RpMaterial* CVehicleModelInfo::GetMatFXEffectMaterialCB(RpMaterial* material, void* data)
  209. {
  210.     return ((RpMaterial* (__cdecl *)(RpMaterial*, void*))0x4C8810)(material, data);
  211. }
  212.  
  213. RpMaterial* CVehicleModelInfo::SetEnvironmentMapCB(RpMaterial* material, void* data)
  214. {
  215.     return ((RpMaterial* (__cdecl *)(RpMaterial*, void*))0x4C8840)(material, data);
  216. }
  217.  
  218. RpMaterial* CVehicleModelInfo::SetEnvMapCoeffCB(RpMaterial* material, void* data)
  219. {
  220.     return ((RpMaterial* (__cdecl *)(RpMaterial*, void*))0x4C88B0)(material, data);
  221. }
  222.  
  223. RpAtomic* CVehicleModelInfo::SetRenderPipelinesCB(RpAtomic* atomic, void* data)
  224. {
  225.     return ((RpAtomic* (__cdecl *)(RpAtomic*, void*))0x4C88F4)(atomic, data);
  226. }
  227.  
  228. void CVehicleModelInfo::SetRenderPipelines()
  229. {
  230.     ((void(__thiscall *)(CVehicleModelInfo*))0x4C8900)(this);
  231. }
  232.  
  233. char* CVehicleModelInfo::GetCustomCarPlateText()
  234. {
  235.     return ((char*(__thiscall *)(CVehicleModelInfo*))0x4C8970)(this);
  236. }
  237.  
  238. void CVehicleModelInfo::SetCustomCarPlateText(char* text)
  239. {
  240.     ((void(__thiscall *)(CVehicleModelInfo*, char*))0x4C8980)(this, text);
  241. }
  242.  
  243. int CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(int modelId)
  244. {
  245.     return ((int(__cdecl *)(int))0x4C89B0)(modelId);
  246. }
  247.  
  248. void CVehicleModelInfo::ReduceMaterialsInVehicle()
  249. {
  250.     ((void(__thiscall *)(CVehicleModelInfo*))0x4C8BD0)(this);
  251. }
  252.  
  253. void CVehicleModelInfo::SetupLightFlags(CVehicle* vehicle)
  254. {
  255.     ((void(__thiscall *)(CVehicleModelInfo*, CVehicle*))0x4C8C90)(this, vehicle);
  256. }
  257.  
  258. RwFrame* CVehicleModelInfo::CollapseFramesCB(RwFrame* frame, void* data)
  259. {
  260.     return ((RwFrame* (__cdecl *)(RwFrame*, void*))0x4C8E30)(frame, data);
  261. }
  262.  
  263. void CVehicleModelInfo::PreprocessHierarchy()
  264. {
  265.     ((void(__thiscall *)(CVehicleModelInfo*))0x4C8E60)(this);
  266. }
  267.  
  268. RpAtomic* CVehicleModelInfo::SetEnvironmentMapAtomicCB(RpAtomic* atomic, void* data)
  269. {
  270.     return ((RpAtomic* (__cdecl *)(RpAtomic*, void*))0x4C9410)(atomic, data);
  271. }
  272.  
  273. RpAtomic * CVehicleModelInfo::SetEnvMapCoeffAtomicCB(RpAtomic * atomic, void * data)
  274. {
  275.     return ((RpAtomic* (__cdecl *)(RpAtomic*, void*))0x4C9430)(atomic, data);
  276. }
  277.  
  278. void CVehicleModelInfo::SetCarCustomPlate()
  279. {
  280.     ((void(__thiscall *)(CVehicleModelInfo*))0x4C9450)(this);
  281. }
  282.  
  283. void CVehicleModelInfo::DisableEnvMap()
  284. {
  285.     ((void(__thiscall *)(CVehicleModelInfo*))0x4C97E0)(this);
  286. }
  287.  
  288. void CVehicleModelInfo::SetEnvMapCoeff(float coeff)
  289. {
  290.     ((void(__thiscall *)(CVehicleModelInfo*, float))0x4C9800)(this, coeff);
  291. }
  292.  
  293. int CVehicleModelInfo::GetNumDoors()
  294. {
  295.     return ((int(__thiscall *)(CVehicleModelInfo*))0x4C73C0)(this);
  296. }

Оффлайн kenking

  • Новичок
  • **
  • Сообщений: 237
  • Репутация: +16/-0
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #130 : Октября 14, 2016, 07:19:03 pm »
Набросал код для цепляния прицепов к тягачам в трафике.
Есть вопрос по экстрам.
Надо считать с тягача установленные экстры и потом на модель прицепа установить такие же. понял, что считать уже установленные экстры на транспорте можно так:
Код: C++
  1. vehicle->m_anExtras[0]
  2. vehicle->m_anExtras[1]

А вот как установить эти номера экстр на модель перед созданием транспорта не понял. Нашёл в CVehicleModelInfo это:
Код: C++
  1. // extras ids for next-spawned car
  2. // static char ms_compsUsed[2];
  3. static char *ms_compsUsed;

Но как применить не знаю. Просьба пояснить.

Ещё вопрос - как проверить в каком месте кода ошибка, если игра "вылетает"?

trailer.dat
Код: C++
  1. #A - Id tractor
  2. #B - Id trailer first variant
  3. #C - Id trailer second variant
  4. #D - Id trailer third variant  
  5. #E - Id trailer fourth variant
  6. #F - Colours of the trailer as at the tractor (0-no, 1-yes)
  7. #G - Extras at the trailer as at the tractor (0-no, 1-yes)
  8.  
  9. #A,   B,   C,   D,   E,  F, G
  10.  
  11. trailer
  12. 403, 435, 450, 584, 591, 0, 0
  13. 485, 606, 607, 607, 606, 0, 0
  14. 514, 584, 584, 584, 584, 0, 0
  15. 515, 435, 450, 584, 591, 0, 0
  16. 525, 400, 401, 402, 404, 0, 0
  17. end

Код: C++
  1. #include "plugin.h"
  2. #include <vector>
  3. #include <fstream>
  4. #include <string>
  5. #include "game_sa\CGeneral.h"
  6. #include "game_sa\CStreaming.h"
  7. #include "game_sa\CTrailer.h"
  8. #include "game_sa\CWorld.h"
  9. #include "game_sa\CTheScripts.h"
  10. #include "game_sa\CModelInfo.h"
  11.  
  12. using namespace plugin;
  13. using namespace std;
  14.  
  15. class MyPlugin {
  16. public:
  17.     class ModelInfo {
  18.     public:
  19.         bool enabledTrailer;
  20.         ModelInfo(CVehicle *vehicle) { enabledTrailer = true; }
  21.     };
  22.  
  23.     static VehicleExtendedData<ModelInfo> modelInfo;
  24.  
  25.     struct MyData {
  26.         unsigned int ModelId;
  27.         unsigned int TrailerIdOne;
  28.         unsigned int TrailerIdTwo;
  29.         unsigned int TrailerIdThree;
  30.         unsigned int TrailerIdFour;
  31.         unsigned int TrailerColours;
  32.         unsigned int TrailerExtras;
  33.     };
  34.  
  35.     static vector<MyData>& GetDataVector() {
  36.         static vector<MyData> vec;
  37.         return vec;
  38.     }
  39.  
  40.     static void ReadSettingsFile() {
  41.         ifstream stream("trailer.dat");
  42.         for (string line; getline(stream, line); ) {
  43.             if (line[0] != ';' && line[0] != '#') {
  44.                 if (!line.compare("trailer")) {
  45.                     while (getline(stream, line) && line.compare("end")) {
  46.                         if (line[0] != ';' && line[0] != '#') {
  47.                             MyData entry;
  48.                             if (sscanf(line.c_str(), "%d, %d, %d, %d, %d, %d, %d", &entry.ModelId, &entry.TrailerIdOne, &entry.TrailerIdTwo, &entry.TrailerIdThree, &entry.TrailerIdFour, &entry.TrailerColours, &entry.TrailerExtras) == 7)
  49.                                 GetDataVector().push_back(entry);
  50.                         }
  51.                     }
  52.                 }
  53.             }
  54.         }
  55.     }
  56.  
  57.     static MyData *GetDataInfoForModel(unsigned int BaseModelId) {
  58.         for (unsigned int i = 0; i < GetDataVector().size(); i++) {
  59.             if (GetDataVector()[i].ModelId == BaseModelId)
  60.                 return &GetDataVector()[i];
  61.         }
  62.         return nullptr;
  63.     }
  64.  
  65.     static void SetTrailer(CVehicle *vehicle, unsigned int modelTrailer, unsigned int colour, unsigned int extra) {
  66.         CStreaming::RequestModel(modelTrailer, 0);
  67.         CStreaming::LoadAllRequestedModels(false);
  68.         if (CStreaming::ms_aInfoForModel[modelTrailer].m_loadState == LOADSTATE_LOADED) {
  69.             if (extra) {
  70.                 ; // здесь надо считать установленные экстры с vehicle
  71.                   // vehicle->m_anExtras[0]
  72.                   // vehicle->m_anExtras[1]
  73.                   // и на модель прицепа modelTrailer установить такие же экстры
  74.             }
  75.             CVehicle *trailer = nullptr;
  76.             if (CModelInfo::IsVehicleModelType(modelTrailer) == 11)
  77.                 trailer = new CTrailer(modelTrailer, 1);
  78.             else                    
  79.                 trailer = new CAutomobile(modelTrailer, 1, true);
  80.             if (trailer) {
  81.                 trailer->SetPosn(0.0f, 0.0f, 0.0f);
  82.                 trailer->m_nStatus = 4;
  83.                 CWorld::Add(trailer);
  84.                 trailer->SetTowLink(vehicle, true);
  85.                 CTheScripts::ClearSpaceForMissionEntity(trailer->GetPosition(), trailer);
  86.                 if (colour) {
  87.                     trailer->m_nPrimaryColor = vehicle->m_nPrimaryColor;
  88.                     trailer->m_nSecondaryColor = vehicle->m_nSecondaryColor;
  89.                     trailer->m_nTertiaryColor = vehicle->m_nTertiaryColor;
  90.                     trailer->m_nQuaternaryColor = vehicle->m_nQuaternaryColor;
  91.                 }
  92.                 if (CModelInfo::IsVehicleModelType(modelTrailer) == 11) {
  93.                     trailer->m_nFlags.bEngineOn = 1;
  94.                     trailer->m_nFlags.bIsLocked = 1;
  95.                 }
  96.                 else {
  97.                     trailer->m_nFlags.bEngineOn = 0;
  98.                     trailer->m_dwDoorLock = CARLOCK_LOCKED;
  99.                 }
  100.                    
  101.             }
  102.         }
  103.     }
  104.    
  105.     MyPlugin() {
  106.         ReadSettingsFile();
  107.         static unsigned int TrailerId;
  108.  
  109.         Events::gameProcessEvent += [] {
  110.             for (int i = 0; i < CPools::ms_pVehiclePool->m_Size; i++) {
  111.                 CVehicle *vehicle = CPools::ms_pVehiclePool->GetAt(i);
  112.                 if (vehicle) {
  113.                     if (CModelInfo::IsVehicleModelType(vehicle->m_wModelIndex) == 11
  114.                         && vehicle->m_nFlags.bIsLocked == 1 && !vehicle->m_pTractor) {
  115.                         vehicle->m_nFlags.bIsLocked = 0;
  116.                         if (!vehicle->IsVisible())
  117.                             vehicle->CanBeDeleted();
  118.                     }
  119.                     MyData *entryModel = GetDataInfoForModel(vehicle->m_wModelIndex);
  120.                     if (entryModel) {
  121.                         switch (CGeneral::GetRandomNumberInRange(0, 4)) {
  122.                         case 0: TrailerId = entryModel->TrailerIdOne; break;
  123.                         case 1: TrailerId = entryModel->TrailerIdTwo; break;
  124.                         case 2: TrailerId = entryModel->TrailerIdThree; break;
  125.                         case 3: TrailerId = entryModel->TrailerIdFour; break;
  126.                         }
  127.                         ModelInfo &info = modelInfo.Get(vehicle);
  128.                         if (info.enabledTrailer && vehicle->m_pDriver && !vehicle->m_pTrailer
  129.                             && (CModelInfo::IsVehicleModelType(TrailerId) == 11 || CModelInfo::IsVehicleModelType(TrailerId) == 0)) {
  130.                             vehicle->m_nFlags.bMadDriver = 0;
  131.                             SetTrailer(vehicle, TrailerId, entryModel->TrailerColours, entryModel->TrailerExtras);
  132.                         }
  133.                         info.enabledTrailer = false;
  134.                     }
  135.                 }
  136.             }
  137.         };
  138.  
  139.     }
  140. } myPlugin;
  141.  
  142. VehicleExtendedData<MyPlugin::ModelInfo> MyPlugin::modelInfo;

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #131 : Октября 14, 2016, 09:22:15 pm »
По аналогии с опкодом 0506
Код: C++
  1. case COMMAND_SET_CAR_MODEL_COMPONENTS:
  2.     this->CollectParameters(3); // параметр №1 не используется
  3.     CVehicleModelInfo::ms_compsToUse[0] = ScriptParams[1].i;
  4.     CVehicleModelInfo::ms_compsToUse[1] = ScriptParams[2].i;
  5.     return OR_CONTINUE;
Когда именно вылетает (на загрузке или в процессе игры)?
Файл открывается, данные считываются?

По CVehicleModelInfo - вроде всё правильно у тебя  :P
Plugin-SDK https://github.com/DK22Pac/plugin-sdk

Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv

Оффлайн kenking

  • Новичок
  • **
  • Сообщений: 237
  • Репутация: +16/-0
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #132 : Октября 15, 2016, 09:59:26 am »
По аналогии с опкодом 0506
Код: C++
  1. case COMMAND_SET_CAR_MODEL_COMPONENTS:
  2.     this->CollectParameters(3); // параметр №1 не используется
  3.     CVehicleModelInfo::ms_compsToUse[0] = ScriptParams[1].i;
  4.     CVehicleModelInfo::ms_compsToUse[1] = ScriptParams[2].i;
  5.     return OR_CONTINUE;
Подключать надо CRunningScript? Что-то не получается у меня. Добавь пожалуйста в тот код, что я показал.

Когда именно вылетает (на загрузке или в процессе игры)?
Файл открывается, данные считываются?
Да файл открывает и данные считываются. Но я имел ввиду не этот конкретно код, а в общем.
Вылетает в процессе игры.
Для клео скриптов были SCMLog и SCRLog Plugin для помощи в поиске ошибок при вылете игры. А в случае с плагинами, как находить из-за какого плагина был вылет и в каком месте кода ошибка?

По CVehicleModelInfo - вроде всё правильно у тебя
Сделал коммит.

Как будет время напиши пожалуйста детально, как ты переносишь всё в sdk. Хорошо бы, по-возможности, ты добавил в sdk для VC все нужные файлы .h и .cpp с подключениями, а я наполнял бы эти файлы по аналогии с sdk для SA. Ну а где будут непонятки, буду спрашивать. Хоть понемногу будет работа по VC продвигаться.

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #133 : Октября 15, 2016, 04:39:26 pm »
Подключать надо CRunningScript? Что-то не получается у меня. Добавь пожалуйста в тот код, что я показал.

Нет.
Код: C++
  1. CVehicleModelInfo::ms_compsToUse[0] = vehicle->m_anExtras[0];
  2. CVehicleModelInfo::ms_compsToUse[1] = vehicle->m_anExtras[1];

А в случае с плагинами, как находить из-за какого плагина был вылет и в каком месте кода ошибка?

Если ты точно знаешь, в каком плагине проблема - собери его в Debug-режиме (важно, чтобы была включена генерация полной отладочной информации)

После вылета в диалоговом окне Windows нажми "отладка" и выбери дебаггер Visual Studio.
Если вылет происходит в "теле" плагина, ты сможешь увидеть строку, на которой происходит вылет.
Хотя, конечно, вылет может произойти и в коде игры, или даже в другом плагине/другой библиотеке.
Тогда нужно анализировать ассемблерный код (т.к. у нас нету исходников игры и/или других библиотек).

https://drive.google.com/file/d/0B3pQzS44FafdNm13bFdpVXVsNDg/view?usp=sharing
Plugin-SDK https://github.com/DK22Pac/plugin-sdk

Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv

Оффлайн kenking

  • Новичок
  • **
  • Сообщений: 237
  • Репутация: +16/-0
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #134 : Октября 16, 2016, 10:00:01 am »
Что-то я с этими экстрами запутался.  :(
В CVehicleModelInfo нет ms_compsToUse, есть
Код: C++
  1. // extras ids for next-spawned car
  2. // static char ms_compsUsed[2];
  3. static char *ms_compsUsed;

Сделал так

Код: C++
  1. static void SetTrailer(CVehicle *vehicle, unsigned int modelTrailer, unsigned int colour, unsigned int extra) {
  2.     CStreaming::RequestModel(modelTrailer, 0);
  3.     CStreaming::LoadAllRequestedModels(false);
  4.     if (CStreaming::ms_aInfoForModel[modelTrailer].m_loadState == LOADSTATE_LOADED) {
  5.         if (extra) {
  6.             CVehicleModelInfo::ms_compsUsed[0] = vehicle->m_anExtras[0];
  7.             CVehicleModelInfo::ms_compsUsed[1] = vehicle->m_anExtras[1];
  8.         }
  9.         CVehicle *trailer = nullptr;
  10.         if (CModelInfo::IsVehicleModelType(modelTrailer) == 11)
  11.             trailer = new CTrailer(modelTrailer, 1);
  12.         else
  13.             trailer = new CAutomobile(modelTrailer, 1, true);
  14.         if (trailer) {
  15.             trailer->SetPosn(0.0f, 0.0f, 0.0f);
  16.             trailer->m_nStatus = 4;
  17.             CWorld::Add(trailer);
  18.             trailer->SetTowLink(vehicle, true);
  19.             CTheScripts::ClearSpaceForMissionEntity(trailer->GetPosition(), trailer);
  20.             if (colour) {
  21.                 trailer->m_nPrimaryColor = vehicle->m_nPrimaryColor;
  22.                 trailer->m_nSecondaryColor = vehicle->m_nSecondaryColor;
  23.                 trailer->m_nTertiaryColor = vehicle->m_nTertiaryColor;
  24.                 trailer->m_nQuaternaryColor = vehicle->m_nQuaternaryColor;
  25.             }
  26.             if (CModelInfo::IsVehicleModelType(modelTrailer) == 11) {
  27.                 trailer->m_nFlags.bEngineOn = 1;
  28.                 trailer->m_nFlags.bIsLocked = 1;
  29.             }
  30.             else {
  31.                 trailer->m_nFlags.bEngineOn = 0;
  32.                 trailer->m_dwDoorLock = CARLOCK_LOCKED;
  33.             }
  34.  
  35.         }
  36.     }
  37. }


но студия ругается
Цитировать
1>------ Перестроение всех файлов начато: проект: TankerTruck, Конфигурация: Rel-XP Win32 ------
1>  Main.cpp
1>Main.obj : error LNK2001: неразрешенный внешний символ ""public: static char * CVehicleModelInfo::ms_compsUsed" (?ms_compsUsed@CVehicleModelInfo@@2PADA)"
1>D:\Games\GTA San Andreas\scripts\TankerTruck.asi : fatal error LNK1120: неразрешенных внешних элементов: 1
========== Перестроение всех проектов: успешно: 0, с ошибками: 1, пропущено: 0 ==========


В показанных ранее примерах в этих строчках
Код: C++
  1. CallMethod<NoRet, 0x506EA0, unsigned int, int, float, float>(0xB6BC90, audioEventId, volume, speed);
  2. Call<NoRet, 0x486B00, CVector const&, CEntity *>(trailer->GetPosition(), trailer);

теперь подчёркиваются красным
Call<NoRet и CallMethod<NoRet
Студия ругается, что идентификатор не определён и отсутствуют экземпляры шаблон функции...