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

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #75 : Сентябрь 03, 2016, 01:06:38 pm »
В первом примере надо определить переменную entries.
Код: C++
  1. vector<SettingsTest::MyData> SettingsTest::entries;
По второму - смотри этот пост.
http://modsforgta.ucoz.ru/forum/9-22-3523-16-1333570000
Код: C++
  1. CVector center = vehicle->TransformFromObjectSpace(CVector(0.0f, -3.0f, 0.0f));
  2. CVector up = vehicle->TransformFromObjectSpace(CVector(0.0f, -2.0f, 0.0f)) - center;
  3. CVector right = vehicle->TransformFromObjectSpace(CVector(2.0f, -3.0f, 0.0f)) - center;
  4. CShadows::StoreShadowToBeRendered(2, pExpTex, &center, up.x, up.y, right.x, right.y, 255, r, g, b, 2.0f, false, 1.0f, 0, true);
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: Написание плагина. Настройка проекта
« Ответ #76 : Сентябрь 03, 2016, 07:00:36 pm »
Разобрался, спасибо! Есть только один момент:
Код: C++
  1. RwTexture *&pExpTex = *(RwTexture **)0xC403F4;
Такие записи (*& и **) ранее не встречались. Просьба разъяснить. Где про это почитать?

Немного изменил и дополнил код:
1) Ограничил для транспорта трафика по m_nClass (оставил для poorfamily, richfamily и executive).
2) Ограничил для транспорта игрока по m_dwVehicleSubClass.
3) Изменил случайный выбор для транспорта в трафике.
4) Взял другую (прямоугольную) текстуру.
5) Размер проекции "привязал" на габариты модели.
6) Так как текстура с ровными краями, сделал мигание проекции, чтобы это сильно "не бросалось в глаза".

Код: C++
  1. #include "plugin.h"
  2. #include "game_sa\CClock.h"
  3. #include "game_sa\CShadows.h"
  4. #include "game_sa\common.h"
  5. #include "KeyCheck.h"
  6. #include "game_sa\CModelInfo.h"
  7. #include "game_sa\CTimer.h"
  8.  
  9. #define TURN_ON_OFF_DELAY 500
  10.  
  11. using namespace plugin;
  12. using namespace std;
  13.  
  14. RwTexture *&pWhiteTex = *(RwTexture **)0xB4E3EC;
  15.  
  16. class NeonLights {
  17. public:
  18.     enum eNeonColor {
  19.         NEON_YELLOW, NEON_GREEN, NEON_RED, NEON_BLUE, NEON_PURPLE
  20.     };
  21.  
  22.     class Neon {
  23.     public:
  24.         unsigned char color;
  25.         bool activated;
  26.         bool processed;
  27.  
  28.         Neon(CVehicle *) {
  29.             activated = processed = false;
  30.         }
  31.  
  32.         void Enable(eNeonColor Color) {
  33.             color = Color;
  34.             activated = true;
  35.         }
  36.  
  37.         void Disable() {
  38.             activated = false;
  39.         }
  40.     };
  41.  
  42.     static VehicleExtendedData<Neon> VehNeon;
  43.  
  44.     static bool CanEnableNeonOnThisVehicle(CVehicle *vehicle) {
  45.         CVehicleModelInfo *vehModel = reinterpret_cast<CVehicleModelInfo *>(CModelInfo::ms_modelInfoPtrs[vehicle->m_wModelIndex]);
  46.         return CClock::GetIsTimeInRange(22, 5) && vehicle->m_pDriver && (vehModel->m_nClass == 1 || vehModel->m_nClass == 2 || vehModel->m_nClass == 3) && (vehicle->m_dwVehicleSubClass == VEHICLE_AUTOMOBILE ||
  47.                         vehicle->m_dwVehicleSubClass == VEHICLE_MTRUCK || vehicle->m_dwVehicleSubClass == VEHICLE_QUAD);
  48.     }
  49.  
  50.     static void ProcessNpcVehicle(CVehicle *vehicle) {
  51.         if (CanEnableNeonOnThisVehicle(vehicle) && !VehNeon.Get(vehicle).processed) {
  52.             VehNeon.Get(vehicle).processed = true;
  53.             if (rand() % 3 == 1) {
  54.                 VehNeon.Get(vehicle).activated = true;
  55.                 VehNeon.Get(vehicle).color = rand() % 5;
  56.             }
  57.         }
  58.     }
  59.  
  60.     static void ProcessVehicles() {
  61.         KeyCheck::Update();
  62.         CVehicle *playaVeh = FindPlayerVehicle(0, false);
  63.         if (playaVeh && (playaVeh->m_dwVehicleSubClass == VEHICLE_AUTOMOBILE ||
  64.                         playaVeh->m_dwVehicleSubClass == VEHICLE_MTRUCK || playaVeh->m_dwVehicleSubClass == VEHICLE_QUAD)) {
  65.             if (KeyCheck::Check(VK_SHIFT)) {
  66.                 if (KeyCheck::CheckJustDown('1'))
  67.                     VehNeon.Get(playaVeh).Enable(NEON_YELLOW);
  68.                 else if (KeyCheck::CheckJustDown('2'))
  69.                     VehNeon.Get(playaVeh).Enable(NEON_GREEN);
  70.                 else if (KeyCheck::CheckJustDown('3'))
  71.                     VehNeon.Get(playaVeh).Enable(NEON_RED);
  72.                 else if (KeyCheck::CheckJustDown('4'))
  73.                     VehNeon.Get(playaVeh).Enable(NEON_BLUE);
  74.                 else if (KeyCheck::CheckJustDown('5'))
  75.                     VehNeon.Get(playaVeh).Enable(NEON_PURPLE);
  76.                 else if (KeyCheck::CheckJustDown('0'))
  77.                     VehNeon.Get(playaVeh).Disable();
  78.             }
  79.         }
  80.         for (int i = 0; i < CPools::ms_pVehiclePool->m_Size; i++) {
  81.             CVehicle *vehicle = CPools::ms_pVehiclePool->GetAt(i);
  82.             if (vehicle && vehicle != playaVeh)
  83.                 ProcessNpcVehicle(vehicle);
  84.         }
  85.     }
  86.  
  87.     static void RenderNeonForVehicle(CVehicle *vehicle) {
  88.         if (VehNeon.Get(vehicle).activated) {
  89.             unsigned char r, g, b;
  90.             switch (VehNeon.Get(vehicle).color) {
  91.             case NEON_YELLOW:
  92.                 r = 255; g = 200; b = 0;
  93.                 break;
  94.             case NEON_GREEN:
  95.                 r = 0; g = 255; b = 0;
  96.                 break;
  97.             case NEON_RED:
  98.                 r = 255; g = 0; b = 0;
  99.                 break;
  100.             case NEON_BLUE:
  101.                 r = 0; g = 0; b = 255;
  102.                 break;
  103.             case NEON_PURPLE:
  104.                 r = 255; g = 0; b = 255;
  105.                 break;
  106.             }
  107.             if (CTimer::m_snTimeInMilliseconds % (TURN_ON_OFF_DELAY + 250) < TURN_ON_OFF_DELAY) {
  108.                 CVector Pos = CModelInfo::ms_modelInfoPtrs[vehicle->m_wModelIndex]->m_pColModel->m_boundBox.m_vSup;
  109.                 CVector center = vehicle->TransformFromObjectSpace(CVector(0.0f, 0.0f, 0.0f));
  110.                 CVector up = vehicle->TransformFromObjectSpace(CVector(0.0f, -Pos.y - 0.5f, 0.0f)) - center;
  111.                 CVector right = vehicle->TransformFromObjectSpace(CVector(Pos.x + 0.2f, 0.0f, 0.0f)) - center;
  112.                 CShadows::StoreShadowToBeRendered(2, pWhiteTex, &center, up.x, up.y, right.x, right.y, 255, r, g, b, 2.0f, false, 1.0f, 0, true);
  113.             }
  114.         }
  115.     }
  116.  
  117.     NeonLights() {
  118.         Events::gameProcessEvent += ProcessVehicles;
  119.         Events::vehicleRenderEvent += RenderNeonForVehicle;
  120.     }
  121. } neon;
  122.  
  123. VehicleExtendedData<NeonLights::Neon> NeonLights::VehNeon;

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #77 : Сентябрь 03, 2016, 10:07:05 pm »
Такая конструкция используется для определения игровых переменных.
Читать про ссылки, указатели, разыменование.

Допустим, мы знаем, что по адресу 0x863984 находится значение гравитации (float, дефолтное значение - 0.008).
Как работать с этим адресом (записать, прочитать)? (функции класса patch не трогаем)
Например, вот так
Код: C++
  1. // Чтение
  2. float gravity = *(float *)0x863984; // C-шный стиль; представляем 0x863984 как указатель на float и разыменовываем его
  3. float gravity = *reinterpret_cast<float *>0x863984; // C++ -шный type casting
  4. // Запись
  5. *(float *)0x863984 = 1.0f;
  6. *reinterpret_cast<float *>0x863984 = 1.0f;
Отлично. Но выглядит не очень. Что делать?
Можно сделать так
Код: C++
  1. #define GRAVITY *(float *)0x863984
  2.  
  3. /* ... */
  4.  
  5. GRAVITY = 1.0f;
А ещё лучше - создать переменную-указатель, и читать/записывать значение через неё:
Код: C++
  1. float *pGravity = (float *)0x863984;
  2.  
  3. /* ... */
  4.  
  5. *pGravity = 1.0f; // предварительно разыменовываем
  6. float gravity = *pGravity; // предварительно разыменовываем
Всё вроде хорошо... Но можно сделать ещё лучше, если вспомнить о ссылках.
Код: C++
  1. float &gGravity = *(float *)0x863984; // создаём ссылку на значение по адресу 0x863984
  2.  
  3. /* ... */
  4.  
  5. gGravity = 1.0f;
Ситуация с RwTexture* - аналогична.
По адресу 0xB4E3EC находится указатель на обьект текстуры графического движка игры (RwTexture).
Код: C++
  1. RwTexture *&pWhiteTex = *(RwTexture **)0xB4E3EC; // создаём ссылку на RwTexture* (указатель на обьект текстуры) по адресу 0xB4E3EC
  2.  
  3. /* ... */
  4.  
  5. plugin::Error("Texture \"%s\" size: %dx%d", pWhiteTex->name, pWhiteTex->raster->width, pWhiteTex->raster->height);
« Последнее редактирование: Сентябрь 03, 2016, 10:22:30 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: Написание плагина. Настройка проекта
« Ответ #78 : Сентябрь 04, 2016, 12:53:26 pm »
Спасибо за разъяснения.

По sdk для VC пока никакого продвижения нет? А по SA много ещё осталось не разобранного?

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #79 : Сентябрь 04, 2016, 03:18:26 pm »
По VC нету.
По SA - да, много.
В последнем коммите я обновил класс CShadows, добавил все функции класса и перечисления.
Ну и переменные тоже.

Добавил все функции класса CGeneral, теперь там есть такое:
Код: C++
  1. static unsigned int GetRandomNumberInRange(int min, int max); // returns random int in range [min;max)
  2. static float GetRandomNumberInRange(float min, float max); // returns random float in range [min;max)
Эти функции используются в опкодах 0208 и 0209.
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: Написание плагина. Настройка проекта
« Ответ #80 : Сентябрь 04, 2016, 04:34:14 pm »
Добавил все функции класса CGeneral, теперь там есть такое:
Эти функции используются в опкодах 0208 и 0209.
Это хорошо. В скриптах я частенько пользовался этими опкодами.


И ещё сразу по прицепам есть вопрос - можно ли в трафике в процессе создания транспорта проверить, если модель определённого ID (тягач), то цеплять к нему прицеп. Цеплять не на весь транспорт с таким ID, а выборочно, ну скажем через определённое время? Цеплять разные прицепы?
Можно, надо разбирать CCarCtrl::GenerateOneRandomCar.
Как будет свободное время разбери пожалуйста это дело. Вопрос с прицепами интересен многим пользователям. Было написано несколько скриптов на эту тему (в том числе и у меня есть такой скрипт), но это всё не то.

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #81 : Сентябрь 10, 2016, 09:19:14 am »
Тем временем в plugin-sdk появились все классы из иерархии CVehicle (CAutomobile, CMonsterTruck, CQuadBike, CTrain, CHeli, CPlane, CBike, CBmx, CTrailer, CBoat).
Обновился пример CreateCar, теперь вместо CCheat::VehicleCheat там используется своя функция спавна.
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: Написание плагина. Настройка проекта
« Ответ #82 : Сентябрь 10, 2016, 10:43:02 am »
Обновился пример CreateCar, теперь вместо CCheat::VehicleCheat там используется своя функция спавна.
Просьба пояснить эти строчки:
Код: C++
  1. reinterpret_cast<CBike *>(vehicle)->m_nDamageFlags |= 0x10;
  2. reinterpret_cast<CBmx *>(vehicle)->m_nDamageFlags |= 0x10;

и эти:
Код: C++
  1. reinterpret_cast<CBike *>(vehicle)->PlaceOnRoadProperly();
  2. reinterpret_cast<CAutomobile *>(vehicle)->PlaceOnRoadProperly();

Пробую работу с выводом текстур на экран. Почитал твой урок http://ru-script.3dn.ru/publ/programirovanie/sozdanie_dll_bibliotek/sa_124_c_plugin_sdk_risuem_chast_1/18-1-0-206

Перенёс пример на sdk:
Код: C++
  1. #include <plugin.h>
  2. #include "game_sa\CSprite2d.h"
  3. #include "game_sa\CTxdStore.h"
  4.  
  5. using namespace plugin;
  6.  
  7. class MyPlugin {
  8. public:
  9.     static CSprite2d mySprite;
  10.  
  11.     MyPlugin() {
  12.         Events::initRwEvent += [] {
  13.             // Добавляем новый слот для нашего txd
  14.             int txd = CTxdStore::AddTxdSlot("mytxd");
  15.             // Загружаем наш txd в выделенный слот
  16.             CTxdStore::LoadTxd(txd, "MODELS\\MYTXD.TXD");
  17.             // Увеличиваем счётчик использований для созданного txd
  18.             CTxdStore::AddRef(txd);
  19.             // Сохраняем текущий txd
  20.             CTxdStore::PushCurrentTxd();
  21.             // Устанавливаем наш txd как текущий
  22.             CTxdStore::SetCurrentTxd(txd);
  23.             // Назначаем текстру нашему спрайту (имя текстуры, имя альфа-маски для текстуры)
  24.             mySprite.SetTexture("skipicon", "skipicona");
  25.             // Восстанавливаем сохранённый txd
  26.             CTxdStore::PopCurrentTxd();
  27.         };
  28.  
  29.         Events::drawingEvent += [] {
  30.             // Рисуем наш спрайт (указываем параметры - позиция, ширина, высота, цвет)
  31.             mySprite.Draw(20.0, 20.0, 150.0, 150.0, CRGBA(255, 255, 255, 255));
  32.         };
  33.     }
  34.  
  35.     ~MyPlugin() {
  36.         Events::shutdownRwEvent += [] {
  37.             // Удаляем наш спрайт
  38.             mySprite.Delete();
  39.             // Удаляем наш txd
  40.             CTxdStore::RemoveTxdSlot(CTxdStore::FindTxdSlot("mytxd"));
  41.         };
  42.     }
  43. } myPlugin;
  44.  
  45. CSprite2d MyPlugin::mySprite;

Верно ли?

Дальше задумался над кодом для спидометра, но не нашёл функции для вращения текстуры стрелки.

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #83 : Сентябрь 10, 2016, 01:46:27 pm »
Просьба пояснить эти строчки:
Код: C++
  1. reinterpret_cast<CBike *>(vehicle)->m_nDamageFlags |= 0x10;
  2. reinterpret_cast<CBmx *>(vehicle)->m_nDamageFlags |= 0x10;

Для мотоциклов и велосипедов надо установить этот флаг после создания. Что это за флаг - не знаю (0x10 = 5ый бит).
и эти:
Код: C++
  1. reinterpret_cast<CBike *>(vehicle)->PlaceOnRoadProperly();
  2. reinterpret_cast<CAutomobile *>(vehicle)->PlaceOnRoadProperly();

Название функции PlaceOnRoadProperly говорит само за себя - "ставит" транспорт на землю.
Верно ли?

Нет. Добавлять функции в эвенты надо в конструкторе. Конструктор (глобального обьекта) выполняется, когда ASI прицепляется к процессу игры.
Деструктор (глобального обьекта) выполняется, когда ASI открепляется от процесса игры.
Дальше задумался над кодом для спидометра, но не нашёл функции для вращения текстуры стрелки.

Действительно, в оригинальных классах нету такой функции (для отрисовки текстуры с наклоном). Надо самому писать.
Код: C++
  1. #include <plugin.h>
  2. #include "game_sa\CSprite2d.h"
  3.  
  4. using namespace plugin;
  5.  
  6. class MyPlugin {
  7. public:
  8.     static RwTexture *pMyTexture;
  9.     static float angle;
  10.  
  11.     // Повернуть Num вершин в массиве Verts на угол Angle вокруг (CX;CY)
  12.     static void RotateVertices(RwIm2DVertex *Verts, unsigned int Num, float CX, float CY, float Angle) {
  13.         float radAngle = fmod(Angle, 360.0f);
  14.         if (radAngle < 0.0f)
  15.             radAngle += 360.0;
  16.         radAngle = (360.0f - radAngle) / 57.2957795f;
  17.         float fCos = cosf(radAngle);
  18.         float fSin = sinf(radAngle);
  19.         for (unsigned int i = 0; i < Num; i++) {
  20.             float xold = Verts[i].x;
  21.             float yold = Verts[i].y;
  22.             Verts[i].x = CX + (xold - CX) * fCos + (yold - CY) * fSin;
  23.             Verts[i].y = CY - (xold - CX) * fSin + (yold - CY) * fCos;
  24.         }
  25.     }
  26.  
  27.     static void DrawRotatedSprite(RwTexture *texture, float x, float y, float w, float h, float angle) {
  28.         CSprite2d::SetVertices(CRect(x - w / 2.0f, y - h / 2.0f, x + w / 2.0f, y + h / 2.0f),
  29.             CRGBA(255, 255, 255, 255), CRGBA(255, 255, 255, 255), CRGBA(255, 255, 255, 255), CRGBA(255, 255, 255, 255));
  30.         RotateVertices(CSprite2d::maVertices, 4, x, y, angle);
  31.         RwEngineInstance->dOpenDevice.fpRenderStateSet(rwRENDERSTATETEXTURERASTER, texture->raster);
  32.         RwEngineInstance->dOpenDevice.fpIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
  33.     }
  34.  
  35.     MyPlugin() {
  36.         Events::initRwEvent += [] {
  37.             pMyTexture = RwD3D9DDSTextureRead("models\\image", 0); // загружает image.dds из папки models
  38.         };
  39.  
  40.         Events::drawingEvent += [] {
  41.             angle += 1.0f;
  42.             if(angle > 360.0f)
  43.                 angle = 0.0f;
  44.             DrawRotatedSprite(pMyTexture, 200.0f, 200.0f, 200.0f, 300.0f, angle);
  45.         };
  46.  
  47.         Events::shutdownRwEvent += [] {
  48.             RwTextureDestroy(pMyTexture);
  49.         };
  50.  
  51.         angle = 0.0f;
  52.     }
  53. } myPlugin;
  54.  
  55. RwTexture *MyPlugin::pMyTexture;
  56. float MyPlugin::angle;

Отрисовать стрелку можно ещё и как фигуру - треугольник.
Код: C++
  1. #include <plugin.h>
  2. #include "game_sa\CSprite2d.h"
  3.  
  4. using namespace plugin;
  5.  
  6. class MyPlugin {
  7. public:
  8.     static float angle;
  9.  
  10.     // Повернуть Num вершин в массиве Verts на угол Angle вокруг (CX;CY)
  11.     static void RotateVertices(RwIm2DVertex *Verts, unsigned int Num, float CX, float CY, float Angle) {
  12.         float radAngle = fmod(Angle, 360.0f);
  13.         if (radAngle < 0.0f)
  14.             radAngle += 360.0;
  15.         radAngle = (360.0f - radAngle) / 57.2957795f;
  16.         float fCos = cosf(radAngle);
  17.         float fSin = sinf(radAngle);
  18.         for (unsigned int i = 0; i < Num; i++) {
  19.             float xold = Verts[i].x;
  20.             float yold = Verts[i].y;
  21.             Verts[i].x = CX + (xold - CX) * fCos + (yold - CY) * fSin;
  22.             Verts[i].y = CY - (xold - CX) * fSin + (yold - CY) * fCos;
  23.         }
  24.     }
  25.  
  26.     // cx, cy - центр вращения треугольника, x1,y1...x3,y3 - точки треугольника
  27.     static void DrawRotatedTriangle(float cx, float cy, float x1, float y1, float x2, float y2, float x3, float y3, CRGBA &color, float angle) {
  28.         for (unsigned int i = 0; i < 3; i++) {
  29.             CSprite2d::maVertices[i].rhw = 1.0f;
  30.             CSprite2d::maVertices[i].u = CSprite2d::maVertices[i].v = 0.0f;
  31.             CSprite2d::maVertices[i].z = 0.0f;
  32.             CSprite2d::maVertices[i].emissiveColor = RWRGBALONG(color.red, color.green, color.blue, color.alpha);
  33.         }
  34.         CSprite2d::maVertices[0].x = x1;
  35.         CSprite2d::maVertices[0].y = y1;
  36.         CSprite2d::maVertices[1].x = x2;
  37.         CSprite2d::maVertices[1].y = y2;
  38.         CSprite2d::maVertices[2].x = x3;
  39.         CSprite2d::maVertices[2].y = y3;
  40.         RotateVertices(CSprite2d::maVertices, 3, cx, cy, angle);
  41.         RwEngineInstance->dOpenDevice.fpRenderStateSet(rwRENDERSTATETEXTURERASTER, 0);
  42.         RwEngineInstance->dOpenDevice.fpIm2DRenderPrimitive(rwPRIMTYPETRILIST, CSprite2d::maVertices, 3);
  43.     }
  44.  
  45.     MyPlugin() {
  46.         Events::drawingEvent += [] {
  47.             angle += 1.0f;
  48.             if(angle > 360.0f)
  49.                 angle = 0.0f;
  50.             DrawRotatedTriangle(300.0f, 300.0f, // центр
  51.                                 300.0f - 10.0f, 300.0f + 10.0f, // точка A
  52.                                 300.0f, 300.0f - 250.0f, // точка B
  53.                                 300.0f + 10.0f, 300.0f + 10.0f, // точка С
  54.                                 CRGBA(255, 0, 0, 255), angle);
  55.             CSprite2d::DrawRect(CRect(300.0f - 2.0f, 300.0f - 2.0f, 300.0f + 2.0f, 300.0f + 2.0f), CRGBA(0, 0, 0, 255));
  56.         };
  57.  
  58.         angle = 0.0f;
  59.     }
  60. } myPlugin;
  61.  
  62. float MyPlugin::angle;

Рисование в RenderWare сводится к следующему:
1) Заполнить данные о вершинах (структуры RwIm2DVertex (или RwD3D9Vertex))
Код: C++
  1. struct RwD3D9Vertex
  2. {
  3.     RwReal      x;              /**< Screen X */
  4.     RwReal      y;              /**< Screen Y */
  5.     RwReal      z;              /**< Screen Z */
  6.     RwReal      rhw;            /**< Reciprocal of homogeneous W */
  7.  
  8.     RwUInt32    emissiveColor;  /**< Vertex color */
  9.  
  10.     RwReal      u;              /**< Texture coordinate U */
  11.     RwReal      v;              /**< Texture coordinate V */
  12. };
2) Настроить параметры рендеринга
Например, текстура устанавливается так:
Код: C++
  1. RwEngineInstance->dOpenDevice.fpRenderStateSet(rwRENDERSTATETEXTURERASTER, texture->raster);
Если же нужно отрендерить фигуру без текстуры, устанавливаем этот параметр в 0:
Код: C++
  1. RwEngineInstance->dOpenDevice.fpRenderStateSet(rwRENDERSTATETEXTURERASTER, 0);
Также можно настроить и другие параметры, например блендинг ("смешивание"), фильтрацию, адресацию, затенение.
3) Отрендерить фигуру (примитив)
Код: C++
  1. RwEngineInstance->dOpenDevice.fpIm2DRenderPrimitive(rwPRIMTYPETRILIST, CSprite2d::maVertices, 3);
где rwPRIMTYPETRILIST - тип примитива (список треугольников - у нас это 1 треугольник)
CSprite2d::maVertices - наш буфер вершин
3 - кол-во вершин в буфере

CSprite2d::maVertices - это стандартный буфер вершин. Вмещает максимум 8 вершин.
Функции CSprite2d::SetVertices предоставляют возможность быстро заполнить этот буфер, правда, предназначены они, в основном, для заполнения данных о прямоугольниках. Поэтому для треугольника нам нужно вручную заполнять этот буфер.
« Последнее редактирование: Сентябрь 10, 2016, 02:20:54 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: Написание плагина. Настройка проекта
« Ответ #84 : Сентябрь 10, 2016, 05:31:12 pm »
Код: C++
  1. pMyTexture = RwD3D9DDSTextureRead("models\\image", 0); // загружает image.dds из папки models
Как я понял, загружаются текстуры только формата .dds?
А если надо взять какую-либо текстуру из определённого .txd файла, какой код для отрисовки текстуры с наклоном будет в этом случае?

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #85 : Сентябрь 10, 2016, 07:11:50 pm »
Всё так же.
Из спрайта ты можешь получить доступ к текстуре.
Код: C++
  1. mySprite.m_pTexture
Plugin-SDK https://github.com/DK22Pac/plugin-sdk

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

Оффлайн Shagg_E

  • Администратор
  • Постоялец
  • *****
  • Сообщений: 705
  • Репутация: +24/-4
  • Изобретательный Рукожопъ
    • Просмотр профиля
    • NewRockstar
Re: Написание плагина. Настройка проекта
« Ответ #86 : Сентябрь 10, 2016, 08:23:00 pm »
Цитировать
Действительно, в оригинальных классах нету такой функции (для отрисовки текстуры с наклоном). Надо самому писать.
Стоп, а как в опкоде это реализовали? Там и скейл, и поворот текстуры на экране. Помню, что работает(когда-то давнооо скриптил для SA)..
074B: draw_sprite_with_rotation 20 coords 428@ 429@ scale 430@ 431@ angle $TEMPVAR_ANGLE rgba 220 220 220 404@
Или вы про Вайс говорите?

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #87 : Сентябрь 10, 2016, 08:56:43 pm »
Цитировать
Действительно, в оригинальных классах нету такой функции (для отрисовки текстуры с наклоном). Надо самому писать.
Стоп, а как в опкоде это реализовали? Там и скейл, и поворот текстуры на экране. Помню, что работает(когда-то давнооо скриптил для SA)..
074B: draw_sprite_with_rotation 20 coords 428@ 429@ scale 430@ 431@ angle $TEMPVAR_ANGLE rgba 220 220 220 404@
Или вы про Вайс говорите?
Понятно, что отрисовать текстуру с поворотом в игре можно, что в Вайсе, что в СА.
Я имел ввиду, что отдельной функции для этого нету.
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: Написание плагина. Настройка проекта
« Ответ #88 : Сентябрь 11, 2016, 11:31:45 am »
Всё так же.
Из спрайта ты можешь получить доступ к текстуре.
Код: C++
  1. mySprite.m_pTexture
Спасибо. А в этом случае удалять эту текстуру надо? Т.е. если у меня в Events::initRwEvent
Код: C++
  1. Events::initRwEvent += [] {
  2.     int txd = CTxdStore::AddTxdSlot("mytxd");
  3.     CTxdStore::LoadTxd(txd, "MODELS\\SPEED.txd");
  4.     CTxdStore::AddRef(txd);
  5.     CTxdStore::PushCurrentTxd();
  6.     CTxdStore::SetCurrentTxd(txd);
  7.     mySpriteRing.SetTexture("tablon", "tablona");
  8.     mySpriteArrow.SetTexture("arrow", "arrowa");
  9.     CTxdStore::PopCurrentTxd();
  10.     pMyTextureArrow = mySpriteArrow.m_pTexture;
  11.     pMyTextureRing = mySpriteRing.m_pTexture;
  12. };
то в Events::shutdownRwEvent
Код: C++
  1. Events::shutdownRwEvent += [] {
  2.     RwTextureDestroy(pMyTextureRing);
  3.     RwTextureDestroy(pMyTextureArrow);
  4.     mySpriteRing.Delete();
  5.     mySpriteArrow.Delete();
  6.     CTxdStore::RemoveTxdSlot(CTxdStore::FindTxdSlot("mytxd"));
  7. };
или строчки
Код: C++
  1. RwTextureDestroy(pMyTextureRing);
  2. RwTextureDestroy(pMyTextureArrow);
лишние?

И ещё вопрос: как сделать, чтобы текстуры рисовались в нужных координатах независимо от разрешения экрана? Тот же вопрос и касательно вывода текста.

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Написание плагина. Настройка проекта
« Ответ #89 : Сентябрь 11, 2016, 09:02:23 pm »
Нет, текстуру удалять не надо.
Она удаляется вызовом CSprite2d::Delete.
Код: C++
  1. void CSprite2d::Delete() { // @0x727240
  2.     if (m_pTexture) {
  3.         RwTextureDestroy(m_pTexture);
  4.         m_pTexture = 0;
  5.     }
  6. }

Надо умножать координаты на коэффициент соотношения высоты экрана (если высота меньше ширины) и "принятого" (стандартного) значения высоты.

Например, за стандарт взято разрешение 1920х1080.
Ты хочешь отрисовать текстуру, которая на экране 1920х1080 располагалась бы справа, по координатам
Код: C++
  1. 150, 200
Допустим, разрешение пользователя - 1280х1024.
Используем формулу
Код: C++
  1. x = static_cast<int>( 150.0f * (1024.0f/1080.0f) ); // = 142
  2. y = static_cast<int>( 200.0f * (1024.0f/1080.0f) ); // = 190

Код: C++
  1. float screen(float a) {
  2.     return static_cast<int>(a * (static_cast<float>(RsGlobal.maximumHeight) / 1080.0f));
  3. }
« Последнее редактирование: Сентябрь 11, 2016, 09:24:33 pm от DK »
Plugin-SDK https://github.com/DK22Pac/plugin-sdk

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