[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 3 из 3
  • «
  • 1
  • 2
  • 3
Форум » Проекты » Ваши проекты » Plugin SDK » Вопросы по Plugin SDK (В этой теме задаются вопросы по плагину от DK22Pac)
Вопросы по Plugin SDK
wmysterio
Администраторы
Скриптер
17.02.18 22:09
Offline
Решил сделать отдельную тему для тех, кто пытается разрабатывать моды, используя Plugin SDK. В общем, сами вопросы задавать здесь. Тема с основной информацией будет здесь.

DK22Pac
Модераторы
TOP Скриптер
17.02.18 22:16
Offline
Смотри вики
https://github.com/DK22Pac/plugin-sdk/wiki
И тему на ещё одном форуме.
http://forum.gtabuilder.ru/index.php?topic=337.0

Обновлены все статьи по plugin-sdk.
http://ru-script.3dn.ru/publ/programirovanie/sozdaniye_asi_plaginov/18

Проводим эксперименты по сборке plugin-sdk в компиляторе mingw-64.
Отредактировал DK22Pac - Понедельник, 26.02.18, 11:43

wmysterio
Администраторы
Скриптер
17.02.18 22:16
Offline
Установил, но при компиляции, как всегда, находит ошибку. На этот раз: "не удается открыть входной файл "paths.lib" FirstScript D:\GitHubClonePath\plugin-sdk\examples\FirstScript\FirstScript\LINK". Код банальный:
#include "plugin.h"
//#include "CMessages.h"

using namespace plugin;

class FirstScript {
public:
FirstScript() {

// Добавьте здесь код инициализации плагина
Events::gameProcessEvent.Add([] {
//CMessages::AddMessageJumpQ("My first text", 1, 0, false);
});

}
} firstScript;
При создании проекта, создаётся совсем не такая структура файлов и папок, как в примерах.

DK22Pac
Модераторы
TOP Скриптер
17.02.18 22:16
Offline
wmysterio, этот пункт сделал?

wmysterio
Администраторы
Скриптер
17.02.18 22:16
Offline
DK22Pac, да, делал.
------
СКОМПИЛИРОВАЛО!!!! Блин, ну ничего же не менял в коде...

DK22Pac
Модераторы
TOP Скриптер
17.02.18 22:16
Offline
Эта ошибка означает, что библиотека paths.lib не найдена.
Библиотека paths.lib - это часть plugin-sdk, и создаётся она при сборке самого plugin-sdk.

Библиотеки plugin-sdk находятся в папке plugin-sdk\output\lib (Visual Studio 2015-2017) или plugin-sdk\output\mingw\lib (Visual Studio 2010-2013, Code::Blocks).
Отредактировал DK22Pac - Среда, 06.12.17, 21:41

wmysterio
Администраторы
Скриптер
17.02.18 22:17
Offline
Цитата DK22Pac ()
Эта ошибка означает, что библиотека paths.lib не найдена.
Да, поисковик мне так и сообщил. Возможно в момент компиляции не все файлы успели подгрузится. Иначе не могу объяснить почему при втором запуске проекта всё отработало на ура ) Сейчас думаю что бы это такое написать ) Возможностей столько, что не хватит фантазии. Наверное, склею "пенальти v2". Может удастся физику полёта мяча легче реализовать.

wmysterio
Администраторы
Скриптер
17.02.18 22:17
Offline
Есть ли способ получить информацию о размере модели транспорта ( как в опкоде 07E4 )?

DK22Pac
Модераторы
TOP Скриптер
17.02.18 22:17
Offline
CBoundingBox bb = CModelInfo::GetModelInfo(modelId)->m_pColModel->m_boundBox;

Или
#include "extensions\ScriptCommands.h"
/* ... */
using namespace plugin;
/* ... */
CBoundingBox bb;
Command<0x07E4>(modelId, &bb.m_vecSup.x, &bb.m_vecSup.y, &bb.m_vecSup.z, &bb.m_vecInf.x, &bb.m_vecInf.y, &bb.m_vecInf.z);
Отредактировал DK22Pac - Пятница, 08.12.17, 01:49

wmysterio
Администраторы
Скриптер
17.02.18 22:17
Offline
Благодарю. Очень много методов. Некоторые их них имеют такие названия, что после СБ сложно там найти знакомые названия ) Как, например, проверить уничтожена ( wrecked ) ли машина? Я там все методы и поля перерыл, но нашел только "m_fHealth", с помощью которого можно проверить на жизнеспособность авто.

DK22Pac
Модераторы
TOP Скриптер
17.02.18 22:17
Offline
Опкод 0119 (IS_CAR_DEAD) ещё дополнительно сверяет, что авто утонуло в воде.
if (vehicle->m_nStatus == STATUS_WRECKED || vehicle->m_nFlags.bIsDrowning) {

}

Или
if (Command< Commands::IS_CAR_DEAD >(vehicle)) {

}


Добавлено (08.12.17, 01:11)
---------------------------------------------
Обновлен модуль ScriptCommands и добавлен пример с его использованием.
https://github.com/DK22Pac....ommands
Отредактировал DK22Pac - Пятница, 08.12.17, 01:31

wmysterio
Администраторы
Скриптер
17.02.18 22:17
Offline
DK22Pac, спасибо. Работает! Очень крутая штука, этот плагин. Главное, разобраться что где искать.

Хочу сделать зеркало заднего вида, как в NFS-ках. Не знаю как лучше подойти к этому вопросу - прикрепить к транспорту зеркало, читать с него изображение и выводить на дисплей; создать вторую камеру и прикрепить её к транспорту, брать с неё изображение и выводить на дисплей. Или есть способы попроще?

Синтаксис "ScriptCommands" немного неудобный. Было бы круто сделать типа такого:
Commands::IS_CAR_DEAD( vehicle ) // IS_CAR_DEAD является методом
Но обращаться по имени команды намного проще, чем вбивать опкод.

DK22Pac
Модераторы
TOP Скриптер
17.02.18 22:18
Offline
Да, как-то так. Надо создать дополнительную камеру, в каждом кадре настраивать позицию и делать рендер.
Но в SA куча проблем с зеркалами (рендером в дополнительные камеры) - проблема с антиалиасингом, например.

Цитата wmysterio ()
Синтаксис "ScriptCommands" немного неудобный. Было бы круто сделать типа такого:

Для этого надо будет обьявлять каждый такой метод отдельно. Конечно, можно это как-то автоматизировать, но и на автоматизацю надо будет потратить немало времени и усилий.

wmysterio
Администраторы
Скриптер
17.02.18 22:18
Offline
Цитата DK22Pac ()
Конечно, можно это как-то автоматизировать, но и на автоматизацю надо будет потратить немало времени и усилий
Верно. В принципе, когда у нас есть доступ к методам движка, то к опкодам дела будут заходить не так часто, имхо.
Цитата DK22Pac ()
Да, как-то так. Надо создать дополнительную камеру, в каждом кадре настраивать позицию и делать рендер.
Так и сделаю, наверное. Правда в Unity две+ камеры жрут очень много ресурсов. В СА дела наверное будут такими же без дополнительных настроек рендеринга.
Цитата DK22Pac ()
Но в SA куча проблем с зеркалами (рендером в дополнительные камеры) - проблема с антиалиасингом, например.
Да, даже в магазинах зеркала выглядят криво. Хотя изображение и так будет сжиматься в размерах при выводе на дисплей, возможно антиалиасинг будет не нужен.

wmysterio
Администраторы
Скриптер
21.02.18 22:14
Offline
А как создать вторую камеру или несколько? Или там лимит на одну-единую и точка?

И ещё: как проверить осуществляется ли сейчас Fade? Пытаюсь проверить через камеру
m_nFadeInOutFlag != ?
Но не знаю где найти флаг, который отвечает за то, что экран в обычном режиме, а не затемняется, осветляется или залит каким-то цветом.

DK22Pac
Модераторы
TOP Скриптер
24.02.18 19:05
Offline
Камеру создать - это не проблема.
В игре нету явных лимитов на камеры.
Пример, где создается много камер - тени педов.
Для каждого педа создается своя камера, и устанавливется "над педом". Туда рендерится пед, и получается изображение педа, которое далее затемняется, размывается, инвертируется, и далее используется как текстура для рендера тени.
Интересно, что для игровых зеркал дополнительные камеры не создаются - там происходит рендер в основную камеру, но перед рендером камеру "переворачивают", и изменяют буфер цвета/глубины, в которые происходит рендер (таким образом, получают текстуру, которую затем используют при рендере полигонов зеркала).
Сложнее правильно настроить созданную камеру (задать позицию, разворот, параметры соотношения ширины/высоты).
Ещё сложнее - правильно что-либо отрендерить в камеру (даже у меня с этим постоянно проблемы).

В игре есть вспомогательные функции для создания и удаления камеры. Но функция создания создаёт, скажем так, "основную камеру", в которую происходит "основной" рендер. По сути, там всё меняет только один параметр (для "основной" камеры надо создавать буфер цвета с типом текстуры rwRASTERTYPECAMERA, а для "кастомной" - rwRASTERTYPECAMERATEXTURE (такую текстуру можно использовать как "обычную" текстуру - например, "наложить" её на полигон)), внутри функции. Но не хочется патчить функцию, вызывать её и отменять патч.
Поэтому придется самому написать эти функции.

Также надо учесть то, что в игре есть баг с зеркалами - если включено сглаживание (MSAA), то обьекты в зеркале неправильно рендерятся (можно заметить, что дальние обьекты перекрывают ближние). Происходит это из-за того, что буфер цвета и буфер глубины имеют разные настройки сглаживания. Буфер глубины в RenderWare всегда создается с "глобальным" параметром сглаживания. А буфер цвета с типом rwRASTERTYPECAMERATEXTURE всегда создается без сглаживания (к текстуре такого типа вообще невозможно применить аппаратное сглаживание).
Исправить этот баг можно, отключив "глобальное" сглаживание на момент создания буфера глубины. Таким образом, и буфер цвета, и буфер глубины не будут иметь сглаживания.

// Создание камеры. Возвращает обьект камеры (RwCamera*)
static RwCamera *CreateCustomCamera() {
    MSAAFix fix; // фикс для дополнительных камер в SA (отключаем MSAA перед созданием растров, иначе будет каша при рендере)
    RwCamera *camera = RwCameraCreate(); // создаём обьект RwCamera
    RwFrame *parent = RwFrameCreate(); // создаём для этого обьекта обьект "перемещения"
    rwObjectHasFrameSetFrame(&camera->object.object, parent); // крепим камеру к этому обьекту "перемещения"
    camera->frameBuffer = RwRasterCreate(512, 512, 0, rwRASTERTYPECAMERATEXTURE); // создаём буфер цвета
    camera->zBuffer = RwRasterCreate(512, 512, 0, rwRASTERTYPEZBUFFER); // создаём буфер глубины
    RwCameraSetProjection(camera, rwPERSPECTIVE); // устанавливаем тип проеции (перспективная или параллельная)
    RwCameraSetNearClipPlane(camera, 0.1f); // ближняя граница отсечения
    RwCameraSetFarClipPlane(camera, 2000.0f); // дальняя граница отсечения
    RwV2d viewWindow = { 0.5f, 0.5f };
    RwCameraSetViewWindow(camera, &viewWindow); // устанавливаем соотношение высоты/ширины камеры (также влияет на FOV)
    // Камера по умолчанию смотрит "снизу вверх" (т.е. по оси Z). Опустим её на 4 единицы вниз
    RwV3d position = {0.0f, 0.0f, -4.0f};
    RwFrameTranslate(parent, &position, rwCOMBINEREPLACE); // меняем позицию
    return camera; // возвращаем результат - камеру
}


// Универсальная функция для удаления растра. Параметр - buf - растр
static void DestroyCameraBuffer(RwRaster *buf) {
    if (buf) { // если не нулевой указатель
        auto parent = buf->parent; // у растра может быть "родитель"
        RwRasterDestroy(buf); // удаляем сам растр
        if (parent && parent != buf) // и если есть "родитель" -
            RwRasterDestroy(parent); // удаляем его
    }
}

// Удаление камеры. Параметр - camera - камера
static void DestroyCamera(RwCamera *camera) {
    if (camera) { // если не нулевой указатель
        auto frame = GetObjectParent(&m_pCustomCamera->object.object); // получить обьект "перемещения"
        if (frame) { // если не нулевой указатель
            rwObjectHasFrameSetFrame(&m_pCustomCamera->object.object, 0); // отсоединяем камеру от обьекта "перемещения"
            RwFrameDestroy(frame); // удаляем обьект "перемещения"
        }
        DestroyCameraBuffer(m_pCustomCamera->frameBuffer); // удаляем буфер цвета
        DestroyCameraBuffer(m_pCustomCamera->zBuffer); // удаляем буфер глубины
        RwCameraDestroy(m_pCustomCamera); // удаляем обект камеры
    }
}


RwFrame - это обьект, отвечающий за перемещение (у него есть матрица) и иерархию (он может быть родителем/ребенком для других RwFrame). Пример из игры - компоненты автомобиля (двери, колеса).
RwRaster - это обьект, который хранит массив пикселей (другими словами, изображение). Это могут быть данные (пикселей) как обычной текстуры (которая загружается из txd), так и "текстуры" камеры.
На самом деле, есть ещё обьект RwTexture, но пока что это не важно.

Так вот, буфер цвета и глубины - это растры, - по сути, массивы пикселей в определённом формате. Результат рендера в камеру - это и есть эти растры (буфер глубины используется в процессе рендеринга, а вот буфер цвета - это уже "финальное" изображение).

Теперь надо отрендерить что-то в камеру и вывести полученное изображение.

// Обновляем камеру и рендерим в неё
static void UpdateCamera() {
    RwRGBA backgroundClr = { 80, 80, 80, 255 }; // цвет "заливки"
    RwCameraClear(m_pCustomCamera, &backgroundClr, rwCAMERACLEARIMAGE | rwCAMERACLEARZ); // очищаем буфер цвета и глубины
    if (RwCameraBeginUpdate(m_pCustomCamera)) { // начинаем рендер в камеру - "включаем" камеру
        // Рендерим куб
        RwMatrix transform; // матрица трансформации куба
        static float angle = 0.0f; // угол вращения матрицы
        RwV3d xAxis = { 1.0f, 0.0f, 0.0f };
        RwV3d yAxis = { 0.0f, 1.0f, 0.0f };
        angle += 1.0f; // увеличиваем угол вращения
        if (angle > 360.0f)
            angle = 0.0f;
        RwMatrixRotate(&transform, &xAxis, angle, rwCOMBINEREPLACE); // поворот по оси X
        RwMatrixRotate(&transform, &yAxis, angle, rwCOMBINEPOSTCONCAT); // поворот по оси Y
        SetRenderState(rwRENDERSTATEZTESTENABLE, true); // включаем тест глубины
        SetRenderState(rwRENDERSTATEZWRITEENABLE, true); // включаем запись в буфер глубины
        SetRenderRaster(nullptr); // сбрасываем текстуру
        if (RwIm3DTransform(CubeVerts, 36, &transform, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXRGBA)) { // начинаем рендер - трансформируем вершины
            RwIm3DRenderPrimitive(rwPRIMTYPETRILIST); // рендерим треугольники
            RwIm3DEnd(); // заканчиваем рендер
        }
        RwCameraEndUpdate(m_pCustomCamera); // заканчиваем рендер в камеру
    }
}


Вот так вот и выглядит рендер в камеру. Залили всё цветом, включили рендер, повернули обьект и отрендерили его.
Отдельная история - это установка состояний рендеринга (в sdk это функция SetRenderState). Очень часто бывает, что в месте инжекта уже установлены какие-то состояния, и их надо будет дополнительно выключать/включать. Например, в этом примере я выключаю текстуру (если это не сделать, то в моменты, когда на экране есть какой-то текст (например, название улицы или авто внизу), то обьект будет рендерится с текстурой шрифта). Вот такие вот бывают сюрпризы)

Осталось вывести полученное изображение:
// Отрисовка изображения камеры
static void DrawCameraImage() {
    SetRenderRaster(m_pCustomCamera->frameBuffer); // устанавливем текстуру (растр) для спрайта - буфер цвета камеры
    CSprite2d::DrawTxRect(CRect(SCREEN_COORD(50.0f), SCREEN_COORD(50.0f), SCREEN_COORD(500.0f), SCREEN_COORD(500.0f)),
        CRGBA(255, 255, 255, 255)); // рисуем прямоугольник
}


Ну и вот как всё это инициализируется:
Events::initRwEvent += [] { m_pCustomCamera = CreateCustomCamera(); }; // создаём камеру
Events::shutdownRwEvent += [] { DestroyCamera(m_pCustomCamera); }; // удаляем камеру
Events::gameProcessEvent += UpdateCamera; // обновляем камеру
Events::drawingEvent += DrawCameraImage; // рисуем результат рендера
// Пересоздание камеры при потере девайса
Events::d3dResetEvent += [] { DestroyCamera(m_pCustomCamera); m_pCustomCamera = CreateCustomCamera(); }; // удаляем и создаём камеру


При потере девайса игра будет пересоздавать все динамические растры (тот же буфер глубины), и чтобы опять не было проблемы со сглаживанием, мы просто удаляем то, что игра пересоздала, и заново создаём (с нашим "фиксом").

Если у тебя нет каких-либо знаний о том, как происходит рендер в 3д-играх (DirectX) - возможно, всё это будет очень сложно понять.
Конечно, если всё это тебе покажется интересным, то я уж помогу, чем смогу.

Весь проект в приклеплениях.
Отредактировал DK22Pac - Суббота, 24.02.18, 19:15
Прикрепления: AdditionalCamer.rar(5.3 Kb)

DK22Pac
Модераторы
TOP Скриптер
24.02.18 19:34
Offline
Цитата wmysterio ()
И ещё: как проверить осуществляется ли сейчас Fade? Пытаюсь проверить через камеру

#include "CCamera.h"

if (TheCamera.m_bFading) {
Отредактировал DK22Pac - Суббота, 24.02.18, 19:36

wmysterio
Администраторы
Скриптер
25.02.18 20:49
Offline
Цитата DK22Pac ()
DK22Pac
спасибо, буду разбираться.
Цитата DK22Pac ()
Если у тебя нет каких-либо знаний о том, как происходит рендер в 3д-играх (DirectX)
Ну, на Unity я использовал DirectX, но это, насколько я понял, были уже враперы и весь харкор уже реализован за меня. Есть ещё несколько книг по API к ним ( +OpenGL ), но как-то не было ни желание ни необходимости заглядывать туда. Так что знаний у меня минимум ( самый примитивный ) по этой теме.
Цитата DK22Pac ()
Конечно, если всё это тебе покажется интересным, то я уж помогу, чем смогу.
Если возникнут вопросы, то конечно буду обращаться. Хочу немного самому разобраться, чтобы не бомбить вопросами по мелочи )
Цитата DK22Pac ()
m_bFading
Спасибо. Работает.

P. S. Немного не в тему, но что это у Вас, разработчиков плагинов, хаков и патчей, за привычка как-то "кодировать" название полей? smile Ну, вот тот-же "m_bFading". Я пытался найти закономерность, но накопал совсем немного. Префиксы b, p, u перед _ чаще обозначают тип данных, которые содержит поле, а вот что с буквами ( например: m ) в начале? Вижу такой способ именования не первый раз, но понял только чуток со всего )

DK22Pac
Модераторы
TOP Скриптер
26.02.18 11:36
Offline

Форум » Проекты » Ваши проекты » Plugin SDK » Вопросы по Plugin SDK (В этой теме задаются вопросы по плагину от DK22Pac)
  • Страница 3 из 3
  • «
  • 1
  • 2
  • 3
Поиск: