1. Уважаемые гости и новички, приветствуем Вас на нашем форуме
    Здесь вы можете найти ответы практически на все свои вопросы о серии игр «Готика» (в том числе различных модах на нее), «Ведьмак», «Ризен», «Древние свитки», «Эра дракона» и о многих других играх. Можете также узнать свежие новости о разработке новых проектов, сыграть в увлекательные ФРПГ, восхититься творчеством наших форумчан, либо самим показать, что вы умеете. Ну и наконец, можете обсудить общие увлечения или просто весело пообщаться с посетителями «Таверны».

    Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
    Удачи!
  2. Форум аддона "Возвращение" 2.0:
    — Обсудить игру, почитать о прохождениях и/или разрешить свои вопросы по игре вы можете в одной из тем одноименного форума. Посетить...
    — Прочитать историю изменения и/или скачать последнюю версию аддона "Возвращение", вы можете на страницах наших ресурсов. Скачать...

AST SDK - Помощь по работе

Тема в разделе "Уpоки AST", создана пользователем Gratt, 12 сен 2016.

  1. Gratt

    Gratt
    Модостроитель

    Регистрация:
    14 ноя 2014
    Сообщения:
    607
    Благодарности:
    683
    Баллы:
    135
    Пол:
    Мужской
    В комплекте с AST идет API, который необходимо поместить в папку с исходниками плагина.

    Прежде всего, с гордостью заявляю, что это более чем полноценный SDK не только для AST, но и на игру Gothic в целом. Возможности пакета позволяют гибко и комфортно работать с движком, изменяя, добавляя или дополняя его стандартный функционал.

    Что необходимо знать о C/C++ для работы с SDK:

    0. Рекомендуется использовать Visual Studio 2012. бегло пробежаться по синтаксису С/С++ и заострить внимание на вещах, представленных ниже.

    1. Работа начинается с подключения заголовочных файлов. Необходимо понимать что они из себя представляют и как работают, поскольку их будет катастрофически много. Об этом можно спокойно почитать в интернете, однако кратко опишу некоторые грабли новичков:
    Открыть спойлер

    Первое, на что я обращаю внимание, в заголовочных файлах рекомендуется использовать только статические данные (static, const, extern), либо их прототипы (объявление без кода реализации). В противном случае, если производить вызов заголовочника из разных файлов исходного кода (.cpp), выскочит ошибка о переопределении данных.

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


    2. Далее следует понять что такое указатели. об этом тоже можно почитаете в интернете. для справки поясню:
    Открыть спойлер

    Указатель - это ссылка на объект в памяти. наглядно показываю задачкой как оно работает:
    int A; // Переменная типа int
    int* B = &A; // Указатель на переменную типа int
    int** C = &B; // Указатель на указатель на переменную типа int
    A = 10; // присваиваем A значение 10
    // Рассмотрим результаты вывода задачи

    Print(A); // Результат = 10
    Print(*B); // Результат = 10
    Print(**C); // Результат = 10
    Print(&A); // Результат = адрес расположения элемента A
    Print(B); // Результат = адрес расположения элемента A
    Print(*C); // Результат = адрес расположения элемента A
    Print(&B); // Результат = адрес расположения указателя B
    Print(C); // Результат = адрес расположения указателя B
    Print(&C); // Результат = адрес расположения указателя C
    A, к примеру, имеет адрес 0x00000700. (& (амперсанд) получает адрес объекта в памяти)
    B ссылается на адрес 0x00000700, в котором находится объект A.
    соответственно, C ссылается на адрес B, по которому лежит адрес A.


    3. Классы. все построено на классах и структурах. частично скриптеры с ними уже знакомы, так что особых проблем тут не возникнет.
    Открыть спойлер

    основные понятия, которые следует изучить для написания своих нормальных классов:
    1. конструкторы и деструкторы.
    2. уровни доступности: public, private, protected...
    3. статический метод(функция)/свойство(переменная)
    4. виртуальный метод. отличие от обычного. абстрактный класс. (по желанию)
    5. соответственно почитать о наследовании (по желанию)

    4. От себя советую изучить макросы #define. очень простая и удобная штука

    В остальном многие понятия вам уже знакомы, если приходилось копаться в скриптах (дедал по синтаксису нечто между Паскалем и Си)

    -------

    Определить путь выходного файла можно заранее определить в системную папку игры, пройдя в меню Проект->Свойства->Общие->Выходной каталог & Наименование. (хоткей компиляции F7 на 2012 студии)

    -------

    Плагины уже имеют все необходимые настройки и основные функции событий (Покадровый цикл, второстепенный поток, инициализация плагина...), найти их можно в фильтре Source
     

    Вложения:

    • Undecorated.txt
      Размер файла:
      1,2 МБ
      Просмотров:
      27
    Последнее редактирование: 29 сен 2016
    Поблагодарили gggg12345678!, Дикарь, Banderas1989 и 3 других пользователя.
  2. Jr13San

    Jr13San Участник форума

    Регистрация:
    1 апр 2010
    Сообщения:
    435
    Благодарности:
    85
    Баллы:
    190
    Пол:
    Мужской
    Saturas, применительно к типу zSTRING ни один выше приведённый метод не работает.
    Код:
    //loading.tga
    zSTRING myStr; char buf[20];
    int* pGothzString = (int*)0x8B2504;
    memcpy(&buf,pGothzString,20);
    myStr = zSTRING(buf);
    MsgBox(myStr);//работает
    MsgBox(zSTRING(buf));//или так
    
    zSTRING* zstr1 = (zSTRING*)0x8B2504;
    MsgBox(*zstr1);//вылет
    
    zSTRING zstr2 = *(zSTRING*)0x8B2504;
    MsgBox(zstr2);//вылет
    
    zSTRING*& mstr3 = *(zSTRING**)0x8B2504;
    MsgBox(mstr3);//вылет
    
    Также хотелось увидеть примеры записей данных разных типов по адресам. Кроме memcpy().
    Я так понял, что записывать по адресу переменной типа zSTRING нельзя больше её длины(Length). Иначе будет замена следом идущих данных?

    PS:
    Код:
    std::string str = *(std::string*)0x8B2504;
    MsgBox(zSTRING(str.c_str()));//вылет
    
     
    Последнее редактирование: 4 янв 2017
  3. Gratt

    Gratt
    Модостроитель

    Регистрация:
    14 ноя 2014
    Сообщения:
    607
    Благодарности:
    683
    Баллы:
    135
    Пол:
    Мужской
    zSTRING zMDL_NODE_NAME_HEAD = *(zSTRING*)0x008D8A08;

    zSTRING* zMDL_NODE_NAME_HEAD = (zSTRING*)0x008D8A08; // указатель на строку. так делать не рекомендую, поскольку в идеале нужно приводить типы 1 в 1 как в огиринале

    при чем тут мемкопи? берешь иду, копируешь адрес и присваиваешь по нему инфу к своей переменной

    даже если предположить что такое возможно, до тех пор, пока ты не пишешь туда данные, ничего ней не будет
     
    Последнее редактирование: 4 янв 2017
    Jr13San сказал Спасибо
  4. Saturas

    Saturas
    Модостроитель

    Регистрация:
    11 фев 2009
    Сообщения:
    1.816
    Благодарности:
    535
    Баллы:
    275
    Пол:
    Женский
    нет, ты не понял меня, если тип объявлен как указатель, то его только через указатель и потом в ссылку на указатель, иначе не сработает.

    тип std::string ИСПОЛЬЗОВАТЬ НИВКОЕМ СЛУЧАЕ НЕЛЬЗЯ ПРИМЕНИТЕЛЬНО к zSTRING, ибо zSTRING унаследован от std::string 6!!! Студии, а в каждой студии размер этого класса разный.

    zSTRING zCTexture::zTEX_DEFAULT_TEXTURE_FILE = *(zSTRING*)0x0099B2C0; вот так нужно получать ссылки/указатели на строки движка. И никак иначе.
     
    Последнее редактирование модератором: 4 янв 2017
    Jr13San сказал Спасибо
  5. Jr13San

    Jr13San Участник форума

    Регистрация:
    1 апр 2010
    Сообщения:
    435
    Благодарности:
    85
    Баллы:
    190
    Пол:
    Мужской
    Вы мне подскажите как вывести в мессаджбокс строку по адресу "0x8B2504" и что там за тип. Я предполагал, что там std::string.

    PS:
    Ошибка: Не удаётся определить член в области видимости.
    error C2655: zCTexture::zTEX_DEFAULT_TEXTURE_FILE: недопустимое определение или повторное объявление в текущей области видимости

    Код:
    char str = *(char*)0x8B2504;
    MsgBox(zSTRING(str));//выводит "l"
    
    //Вот правильный ответ:
    char* str = (char*)0x8B2504;
    MsgBox(zSTRING(str));//выводит "loading.tga"
    
     
    Последнее редактирование: 4 янв 2017
  6. Saturas

    Saturas
    Модостроитель

    Регистрация:
    11 фев 2009
    Сообщения:
    1.816
    Благодарности:
    535
    Баллы:
    275
    Пол:
    Женский
    char* там тип, но зачем? там просто loading.tga и все. Вообще иду юзать не рекомендую, все к чему можно и нужно получать доступ есть в файле что я кидал выше, то чего в нем нет, значит и не следует трогать вообще, ибо можно серьезно нарушить работу.
    Нет, в корне не верно, строка там хранится в виде указателя, так что менять как угодно, а вот то что хочешь поменять ты, во первых поменять не сможешь(ибо эта область ридонли, и там только константы лежат) во вторых есть риски что игра крешнится.
     
    Последнее редактирование: 4 янв 2017
  7. Saturas

    Saturas
    Модостроитель

    Регистрация:
    11 фев 2009
    Сообщения:
    1.816
    Благодарности:
    535
    Баллы:
    275
    Пол:
    Женский
    Это был пример объявления, на статической переменной класса, для обычных переменных все тож самое кроме ClassName::

    А для твоей задачи, хукаешь 0x006C2690 public: virtual void __thiscall oCGame::OpenLoadscreen(bool, zSTRING)
    и после выполнения основного кода( который по указателю на родную функцию) пишешь - load_screen->InsertBack("myloadscreen.tga");

    Имя переменной load_screen в твоем случае может быть другим, посмотри в класса oCGame
     
    Последнее редактирование модератором: 4 янв 2017
    Jr13San сказал Спасибо
  8. Jr13San

    Jr13San Участник форума

    Регистрация:
    1 апр 2010
    Сообщения:
    435
    Благодарности:
    85
    Баллы:
    190
    Пол:
    Мужской
    В следующей сборке появится класс "zFILE_VDFS"?
    Хотел проверить, загружен ли файл в виртуальную файловую систему, по названию, без полного пути. Там вроде есть похожие функции.
    Пробую пока так, но это реально не то:
    Код:
    bool fex = zFILE("zF1_A4.tga").Exists();
    MsgBox(fex);//"1" (файла нет)
    
    bool fex = zFILE("zF1_A1.tga").Exists();
    MsgBox(fex);//"1" (файла есть)
    
    Возможно нужно указывать полный путь до файла. Но это не известная величина.
     
  9. Saturas

    Saturas
    Модостроитель

    Регистрация:
    11 фев 2009
    Сообщения:
    1.816
    Благодарности:
    535
    Баллы:
    275
    Пол:
    Женский
    Объекты класса zFILE создавать таким образом НЕЛЬЗЯ! То как сейчас сделано, можно сказать что оно не работает, жди 003 там все это реализовано.
    В будущем этот процесс будет выглядеть так:
    zFILE* pFile = zfactory->CreateZFile("myfile.file");
    И уже с указателем pFile работаем.
     
    Jr13San сказал Спасибо
  10. Jr13San

    Jr13San Участник форума

    Регистрация:
    1 апр 2010
    Сообщения:
    435
    Благодарности:
    85
    Баллы:
    190
    Пол:
    Мужской
    Добавил public(выделены) для доступа к объектам:
    zccollisionobject.h (открыть)

    class zCCollisionObject //sizeof 0x8C
    {
    struct BIT_ARRAY
    {
    BYTE tMove:1; //01
    BYTE tRotate:1; //02
    };
    zMAT4 m_mOldVobTrafo; //4
    zMAT4 m_mVobTrafo; //44

    public:
    zCVob* m_pVob; //84
    BIT_ARRAY f; //88
    public:
    //

    virtual zCCollisionObjectDef* GetCollObjClass(void)const
    {
    XCALL(0x0054D1E0);
    };
    ...


    class zCCollisionReport //sizeof 0x34
    {
    float m_fDistance; //4
    zVEC3 m_vContactPoint; //8
    zVEC3 m_vNormal1; //14
    zVEC3 m_vNormal2; //20
    public:
    zCCollisionObject* m_pCollObj1; //2C
    zCCollisionObject* m_pCollObj2; //30

    void zCollisionReport()
    {
    XCALL(0x0054C550);
    };
    ...

    Добавил хук по звуку от столкновения:
    CallBackExp.cpp (открыть)
    Код:
    //005ECAE0 ; public: void __thiscall zCSoundManager::StartHitSound(class zCVob *, enum  zCSoundManager::zTSndManMedium, enum  zCSoundManager::zTSndManMedium, int, int, class zCCollisionReport const *)
    ASTVOID<void(__thiscall*)(zCSoundManager *, zCVob *, int&, int&, int, int, zCCollisionReport const *)> pStartHitSound(0x005ECAE0);
    void __fastcall StartHitSound(zCSoundManager* _this, void* DetourShit, zCVob* vob, int& TSnd1, int& TSnd2, int p1, int p2, zCCollisionReport const * cReport)
    {
    
        if (cReport->m_pCollObj1)
        {
            if (cReport->m_pCollObj1->m_pVob)
            {
                MsgBox(cReport->m_pCollObj1->m_pVob->GetObjectName());
            }
            else
            {
                MsgBox("No pVob1");
            }
        }
        else
        {
            MsgBox("No pCollObj1");
        }
    
        //снаряд нормально определяется!
        /*if (cReport->m_pCollObj2->m_pVob)
        {
            MsgBox(cReport->m_pCollObj2->m_pVob->GetObjectName());
        };*/
    
        pStartHitSound(_this, vob, TSnd1, TSnd2, p1, p2, cReport);
    }
    
    void HookExp()
    {
        CCallBack::Attach(&(PVOID&)pStartHitSound, StartHitSound);
    }
    


    Результат после выстрела в доску типа oCMob.
    Report.txt

    Такая же ситуация с функцией:
    //006A09C0 ; public: virtual void __thiscall oCAIArrowBase::ReportCollisionToAI(class zCCollisionReport const &)
    Там тоже снаряд определяется как коллизион объект - 2, а любые манипуляции с первым объектом приводят к вылету. Интересно, в чём может быть ошибка? На Икарусе я с этой функцией работал. В отчёте объекты столкновения определялись.
     

    Вложения:

    • Report.txt
      Размер файла:
      14,4 КБ
      Просмотров:
      7
    Последнее редактирование: 6 янв 2017
    MaGoth сказал Спасибо
  11. MaGoth

    MaGoth ★★★★★★★★★★★
    Администратор

    Регистрация:
    7 янв 2005
    Сообщения:
    12.690
    Благодарности:
    5.572
    Баллы:
    740
    Пол:
    Мужской
    Такие портянки суй текстовым файлом во вложения..
     
  12. Saturas

    Saturas
    Модостроитель

    Регистрация:
    11 фев 2009
    Сообщения:
    1.816
    Благодарности:
    535
    Баллы:
    275
    Пол:
    Женский
    Потому что zCCollisionObject - является базовым виртуальным классом, из него методы вызывать нельзя, либо виртуалка битая, впозже гляну чо там. А вообще подробнее опиши чот не понятно чо ты вообще делаешь.
     
  13. Jr13San

    Jr13San Участник форума

    Регистрация:
    1 апр 2010
    Сообщения:
    435
    Благодарности:
    85
    Баллы:
    190
    Пол:
    Мужской
    В Икарусе можно, а здесь нельзя. Смешно как-то. Я не над вами, а над ситуацией...

    Всё те же окна. В оконном проёме строит триггер типа zCTrigger. Об него "спотыкается" летящий снаряд.
    Я пытаюсь найти объект в который попала стрела или болт, чтобы потом по древу родителя(Триггера) найти потомка стекло и сменить у него текстуру. Там из отчёта всё было бы всё видно. А он не работает.

    В смысле стрельнуть лучём во время её столкновения?
     
    Последнее редактирование: 6 янв 2017
  14. Gratt

    Gratt
    Модостроитель

    Регистрация:
    14 ноя 2014
    Сообщения:
    607
    Благодарности:
    683
    Баллы:
    135
    Пол:
    Мужской
    какие еще триггеры? какие потомки? зачем так усложнять? доведи до ума сами трейсреи и не морочь себе голову
     
  15. Saturas

    Saturas
    Модостроитель

    Регистрация:
    11 фев 2009
    Сообщения:
    1.816
    Благодарности:
    535
    Баллы:
    275
    Пол:
    Женский
    Попробуй убрать префикс virtual во всех классах коллизий. Именно он может все ломать, потому икарус и рабоатет ибо там нету понятия виртуалок в принципе и вызываются основные функции. хотя виртуалка тут не причем я думаю, где то еще косяк. И покажи как ты делал на икарусе.
     
    Последнее редактирование: 6 янв 2017
  16. Jr13San

    Jr13San Участник форума

    Регистрация:
    1 апр 2010
    Сообщения:
    435
    Благодарности:
    85
    Баллы:
    190
    Пол:
    Мужской
    Не помогло. Мне кажется с самим хуком на функцию что-то не то.
     
  17. Saturas

    Saturas
    Модостроитель

    Регистрация:
    11 фев 2009
    Сообщения:
    1.816
    Благодарности:
    535
    Баллы:
    275
    Пол:
    Женский
    А лол, все понятно, ты откуда взял это?
    StartHitSound(zCSoundManager* _this, void* DetourShit, zCVob* vob, int& TSnd1, int& TSnd2, int p1, int p2, zCCollisionReport const * cReport)
    почему TSnd1/2 у тебя ссылки? откуда ты это взял?
     
  18. Jr13San

    Jr13San Участник форума

    Регистрация:
    1 апр 2010
    Сообщения:
    435
    Благодарности:
    85
    Баллы:
    190
    Пол:
    Мужской
    Подсмотрел из этой функции:
    Код:
    int GetSoundMaterial(zCVob*,/*zCSoundManager::zTSndManMedium*/int&)
        {
            XCALL(0x0069EF30);
        };
    У вас же нет перечисления "zCSoundManager::zTSndManMedium".
     
  19. Saturas

    Saturas
    Модостроитель

    Регистрация:
    11 фев 2009
    Сообщения:
    1.816
    Благодарности:
    535
    Баллы:
    275
    Пол:
    Женский
    Ты вообще понимаешь что такое перечисление? И можешь отличить GetSoundMaterial(zCVob *,zCSoundManager::zTSndManMedium &) от
    //005ECAE0 ; public: void __thiscall zCSoundManager::StartHitSound(class zCVob *, enum zCSoundManager::zTSndManMedium, enum zCSoundManager::zTSndManMedium, int, int, class zCCollisionReport const *) ?
    И Вот еще, НАСТОЯТЕЛЬНАЯ просьба в иде не смотреть имена функций, они там неверно андекорированы, и много не правильного там, смотри в том файле что я кинул. А так же не доверять тем функциям где закоменчены аргументы в АПИ, они закоменчены были очень давно, и может быть много не точностей.
     
  20. Jr13San

    Jr13San Участник форума

    Регистрация:
    1 апр 2010
    Сообщения:
    435
    Благодарности:
    85
    Баллы:
    190
    Пол:
    Мужской
    Понимаю.
    enum zCSoundManager::zTSndManMedium - перечисление.
    zCSoundManager::StartHitSound() - функция
    zCSoundManager::zTSndManMedium - также может быть член класса.

    В первом случае тип ссылки, а во втором одно из перечислений.

    PS:
    Вот, теперь понятно сказал. :)

    Кстати, может быть и вправду нужно было сделать так:
    ASTVOID<void(__thiscall*)(zCSoundManager *, zCVob *, int, int, int, int, zCCollisionReport const *)> pStartHitSound(0x005ECAE0);
    void __fastcall StartHitSound(zCSoundManager* _this, void* DetourShit, zCVob* vob, int TSnd1, int TSnd2, int p1, int p2, zCCollisionReport const * cReport)

    Сейчас попробую. Потому что перечисление - это обычное число, типа Int.

    PS2:
    Нет, ничего не вышло. И без "виртуалов" также вылетает.
    Также без virtual не работает ссылка на cReport->m_pCollObj2->m_pVob. А с ними, как было прежде - работает.
     
    Последнее редактирование: 6 янв 2017
  21. Saturas

    Saturas
    Модостроитель

    Регистрация:
    11 фев 2009
    Сообщения:
    1.816
    Благодарности:
    535
    Баллы:
    275
    Пол:
    Женский
    Нет, в первом случае ссылка на перечисление, а во втором случае просто перечисление, что не понятно?
     
    Jr13San сказал Спасибо

Поделиться этой страницей