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

    Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
    Удачи!

Не стесняюсь спросить....

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
кто-то пытался сделать так, чтобы уроном "DAM_FLY" отбрасывало постоянно, а не через определенное количество тыков?
Не уверен, что я понял, о чём ты спрашиваешь. Возможно, вопрос об объекте игрового мира (не помню название), который наносит урон при пересечении его поверхности. Такие объекты действительно работают ненадёжно, по крайней мере в Г1. Если вопрос об этом, то можно попробовать активировать у объекта повторное нанесение урона. В свойствах объекта можно установить интервал времени, через который будет наноситься новая порция урона.
 

Desizend

Участник форума
Регистрация
29 Май 2023
Сообщения
13
Благодарности
7
Баллы
30
Может кто расписать как вытащить доспех из мода по второму Готану?
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.002
Благодарности
971
Баллы
295
берешь файлы доспеха из папки с анимацией и папки с текстурами. открыть том мода можно с помощью программы VDFS Tool
 

Desizend

Участник форума
Регистрация
29 Май 2023
Сообщения
13
Благодарности
7
Баллы
30

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.002
Благодарности
971
Баллы
295
это зависит от мода. как правило ресурсы модов запакованы в тома *.mod
 

Desizend

Участник форума
Регистрация
29 Май 2023
Сообщения
13
Благодарности
7
Баллы
30
это зависит от мода. как правило ресурсы модов запакованы в тома *.mod
не в vdf? Я хочу один доспех из Архолоса вытащить, я правильно понял, что теперь искать его в файлах KM_Anims и KM_Textures? Приложение скачал, с помощью него и открываю эти vdf
 

Desizend

Участник форума
Регистрация
29 Май 2023
Сообщения
13
Благодарности
7
Баллы
30
всё, вроде разобрался
 

waraMax

Участник форума
Регистрация
1 Окт 2009
Сообщения
91
Благодарности
14
Баллы
175
B_GetLearnCostTalent.d (навыки) и B_GetLearnCostAttribute.d (атрибуты) в Story/B_Story.
Не подскажешь, где хранятся данные получаемого опыта за убийство мобов?
А то в исправленных скриптах, у ряда мобов, опыт несколько порезан и хотелось бы восстановить справедливость, так сказать.
В XP_Constans.b не увидел инфы, например, о том же молодом волке, другого файла со схожим названием найти не удалось.
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.002
Благодарности
971
Баллы
295

DAMROCK

Участник форума
Регистрация
23 Янв 2017
Сообщения
22
Благодарности
5
Баллы
160
Пример индикатора для Г1. Повторяет значения здоровья.

Посмотреть вложение 77699

C++:
// Indicator.cpp

#include "UnionAfx.h"

namespace Gothic_I_Classic {

//***************************************
// Макросы (для удобства понимания кода)
//***************************************
// Преобразование пикселей в виртуальные координаты относительно заданного объекта "pView"
#define PixelToVirtualX(pView, value) pView->anx(value) // по оси Х
#define PixelToVirtualY(pView, value) pView->any(value) // по оси У

// Преобразование виртуальных координат в пиксели относительно заданного объекта "pView"
#define VirtualToPixelX(pView, value) pView->nax(value) // по оси Х
#define VirtualToPixelY(pView, value) pView->nay(value) // по оси У

// указатель на индикатор (по умолчанию не задан)
oCViewStatusBar* pNewBar = NULL;

// Текстура полоски индикатора
const zSTRING newBar_bar = "BAR_NEW.TGA";


// обновление позиции и размеров нового индикатора
void newBar_UpdatePosAndSizes()
{
    // размеры берём от хп бара или же указываем свои
    if (ogame && ogame->hpBar && pNewBar)
    {
        int sx, sy;

        // получаем размеры индикатора здоровья
        ogame->hpBar->GetSize(sx, sy);

        // устанавливаем такие же размеры для нового индикатора
        pNewBar->SetSize(sx, sy);

        int x, y;

        // получаем позицию индикатора здоровья
        ogame->hpBar->GetPos(x, y);
            
        // устанавливаем позицию нового индикатора (по оси Х - такую же как и у индикатора здоровья,
        // а по оси У - отступив от верхнего края индикатора здоровья сам размер индикатора и 10 пикселей,
        // т.о. создав зазор между индикаторами в 10 пикселей)
        pNewBar->SetPos(x, y - sy - PixelToVirtualY(screen, 10));
    }
}

// обновление значения индикатора
void newBar_UpdateValue()
{
    // проверяем указатели
    if (pNewBar && player)
    {
        pNewBar->SetValue(player->GetAttribute(NPC_ATR_HITPOINTS));
        pNewBar->SetMaxRange(0, player->GetAttribute(NPC_ATR_HITPOINTSMAX));
        pNewBar->SetRange(0, player->GetAttribute(NPC_ATR_HITPOINTSMAX));
    }
}

//******************************************************************
// Перехват функции смены режима отображения индикаторов (вкл/выкл)
//******************************************************************
//0x00638BE0 public: void __thiscall oCGame::SetShowPlayerStatus(int)
static void __fastcall Game_SetShowPlayerStatus(oCGame* _this, void* vt, BOOL bShow);
static CInvoke <void(__thiscall*)(oCGame*, BOOL)> pGame_SetShowPlayerStatus(0x00638BE0, Game_SetShowPlayerStatus, IVK_AUTO);
static void __fastcall Game_SetShowPlayerStatus(oCGame* _this, void* vt, BOOL bShow)
{
    // если указатель на вьюпорт и на новый индикатор есть, а также задана команда "скрыть индикаторы"
    // (например, при вызове главного меню)
    if (screen && pNewBar && !bShow)
        // удаляем индикатор из вьюпорта
        screen->RemoveItem(pNewBar);

    // и вызываем оригинальную функцию
    pGame_SetShowPlayerStatus(_this, bShow);
}

//***************************************************
// Перехват функции обновления значений индикаторов
//***************************************************
//0x00638F90 public: void __thiscall oCGame::UpdatePlayerStatus(void)
static void __fastcall Game_UpdatePlayerStatus(oCGame* _this);
static CInvoke <void(__thiscall*)(oCGame*)> pGame_UpdatePlayerStatus(0x00638F90, Game_UpdatePlayerStatus, IVK_AUTO);
static void __fastcall Game_UpdatePlayerStatus(oCGame* _this)
{
    // вызываем оригинальную функцию
    pGame_UpdatePlayerStatus(_this);

    // если указателя на игровую сессию нет или запрещено показывать индикаторы
    if (!_this || !_this->showPlayerStatus)
        // выходим
        return;
 
    // если индикатор не создан
    if (!pNewBar)
    {
        // создаём новый индикатор
        pNewBar = new oCViewStatusBar();

        // если вьюпорт есть и индикатор создан
        if (screen && pNewBar)
        {
            // добавляем индикатор на экран
            screen->InsertItem(pNewBar, FALSE);

            // инициализируем индикатор в нулевых координатах и в масштабе х1
            pNewBar->Init(0, 0, 1.0);

            // задаём текстуры для индикатора
            pNewBar->SetTextures("BAR_BACK.TGA", "BAR_TEMPMAX.TGA", newBar_bar);

            // обновляем позицию и размеры нового индикатора
            newBar_UpdatePosAndSizes();

            // после инициализации удаляем индикатор из вьюпорта
            screen->RemoveItem(pNewBar);
        }
    }

    // если указатели на вьюпорт и индикатор существуют
    if (screen && pNewBar)
    {
        // удаляем индикатор из вьюпорта
        screen->RemoveItem(pNewBar);

        // вставляем индикатор во вьюпорт, тем сымым ставя его на передний план во время рендера zCView элементов
        screen->InsertItem(pNewBar, FALSE);

        // обновляем значение индикатора
        newBar_UpdateValue();
    }
}


//*******************************************************************************************************
// Перехват функции обновления позиций и размеров различных индикаторов при изменении разрешения экрана
//*******************************************************************************************************
//0x00638C50 public: void __thiscall oCGame::UpdateScreenResolution(void)
static void __fastcall Game_UpdateScreenResolution(oCGame* _this);
static CInvoke <void(__thiscall*) (oCGame*)> pGame_UpdateScreenResolution(0x00638C50, Game_UpdateScreenResolution);
static void __fastcall Game_UpdateScreenResolution(oCGame* _this)
{
    // вызываем оригинальную функцию
    pGame_UpdateScreenResolution(_this);

    // если указатели на вьюпорт и индикатор существуют
    if (screen && pNewBar)
    {
        // добавляем индикатор на экран
        screen->InsertItem(pNewBar, FALSE);

        // инициализируем индикатор в нулевых координатах и в масштабе х1
        pNewBar->Init(0, 0, 1.0);

        // обновляем позицию и размеры нового индикатора
        newBar_UpdatePosAndSizes();

        // после инициализации удаляем индикатор из вьюпорта
        screen->RemoveItem(pNewBar);
    }
}


}

И снова здравствуйте, пользуюсь VS17 еле как разобрался со сборкой плагина, т.к. не могу поставить SDK v(100), но вроде работает как-то, на компиляторе v(141_xp)
пытался понять как работает этот перехватчик, но так и не уловил сути, в игре, по данному примеру -ничего не меняется. Прикинул, что функции перехватчика надо прописывать в Plagin.cpp через состояния, но абсолютно не понимаю, что надо прописать в аргументах. Как же оно всё-таки работает?
PS: G2Addon
 

Jr13San


Модостроитель
Регистрация
1 Апр 2010
Сообщения
449
Благодарности
266
Баллы
230

DAMROCK,​

1) Если тебе нужен компилятор (v100), то нужно установить ещё и Visual Studio 2010.
Название образа VS 2010: "ru_visual_studio_2010_professional_x86_528367.iso", ну либо то, что найдёшь в сети.

2) По поводу перехватчиков. Они работают по адресам функций. Например:
Форматирование (BB-код):
static CInvoke <void(__thiscall*)(oCGame*, BOOL)> pGame_SetShowPlayerStatus(0x00638BE0, Game_SetShowPlayerStatus, IVK_AUTO);
Здесь "pGame_SetShowPlayerStatus" - это указатель на оригинальную перехватываемую функцию,
"Game_SetShowPlayerStatus" - это та функция, в которую будет перенаправлен вызов.

Если в своём проекте ты откроешь файл: "Engine SDK\1. Gothic I\Names_G1.hpp", и с помощью поиска(Ctrl+F) найдёшь в нём адрес 0x00638BE0, то он укажет на функцию:
Код:
0x00638BE0 public: void __thiscall oCGame::SetShowPlayerStatus(int)

В каждом движке свои адреса функций. И то есть, используя адреса Г1 из того примера, но уже в движке Г2а, ты можешь попасть на случайную функцию или область памяти, которые могут иметь непредсказуемые последствия или просто вылет, при условии что конфигурация решения была для Г2а. А чтобы этого не произошло, тебе нужно поменять все адреса перехватчиков в коде.

Ищешь и подставляешь всё аналогичным образом:
Заходишь в файл: "Engine SDK\4. Gothic II NoTR\Names_G2A.hpp", находишь в нём интересующую функцию по названию:
Код:
0x006C2D90 public: void __thiscall oCGame::SetShowPlayerStatus(int)

Затем берёшь её адрес и подставляешь в код перехватчика:
Форматирование (BB-код):
static CInvoke <void(__thiscall*)(oCGame*, BOOL)> pGame_SetShowPlayerStatus(0x006C2D90, Game_SetShowPlayerStatus, IVK_AUTO);
Но будь внимателен при переносе функций, т.к. для разных движков они могут выглядеть по разному:
Поэтому сверяй:
- тип: void
- соглашение о вызовах: __thiscall
- принадлежность к классу: oCGame::SetShowPlayerStatus
- и аргументы: (int)
В зависимости от этого может меняться код перехватчика.

Ну и естественно, для работы с G2a, необходимо выбрать другую конфигурацию решения "G2A MD Release":
Cfg.png


Сейчас популярен другой метод перехвата функций, с помощью так называемой связки HOOK-AS.
Более подробно эту реализацию можешь изучить в других готовых проектах разных форумчан (кто этим занимался, например:
Gratt, Xeдин, Slavemaster ).

Движок форума всё лучше и лучше *facepalm*
 

DAMROCK

Участник форума
Регистрация
23 Янв 2017
Сообщения
22
Благодарности
5
Баллы
160
Есть ли способ проследить открыт ли инвентарь на экране? хочу записать его состояние в условие. Так же на будущее, как с ним работать, ничего толкового не нашёл
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.002
Благодарности
971
Баллы
295
Есть ли способ проследить открыт ли инвентарь на экране?
посмотри в zParserExtender, там были функции работы с инвентарём.

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

***

 

DAMROCK

Участник форума
Регистрация
23 Янв 2017
Сообщения
22
Благодарности
5
Баллы
160
посмотри в zParserExtender, там были функции работы с инвентарём.


возможно для такой проверки лучше использовать проверку на то была ли нажата клавиша открытия инвентаря, опять же через zParserExtender

***

мне бы через union sdk понять как это сделать, думаю тут замешано oCViewDialogInventory, но хотелось бы и другой путь узнать, может я просмотрел. искал через player->, но что-то всё не то
 

mas0raksh

Участник форума
Регистрация
28 Ноя 2022
Сообщения
9
Благодарности
1
Баллы
20
Народ. Как мне мои скрипты написанные на .d запаковать в .vdf формат ? Просто видел некоторые vdf файлы, при распаковке которых (с помощью GothicVDFS) были не dat файлы, а .d (.d скрипты находились в : SYSTEM\AUTORUN). Хотя в уроках писали что нельзя запаковать .d в .vdf...
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
mas0raksh, Если прям скрипты-скрипты, то лучше пихать их в DAT. и потом уже упаковывать в VDF(MOD).
Если это скриптовые патчи, сделанные на union, то можно просто пихать их в том VDF(MOD).
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.301
Благодарности
4.636
Баллы
625
DAMROCK, чем тебе через player не понравилось? Там есть объект inentory2 (oCNpcInventory → oCItemContainer). Поиском по Gothic API можно найти список s_openContainers, вот в нем будут лежать все открытые в данный момент контейнеры. Если твой player->inventory2 является частью этого списка, то значит инвентарь игрока открыт.
 

Slavemaster


Модостроитель
Регистрация
10 Июн 2019
Сообщения
1.082
Благодарности
1.901
Баллы
320
У меня в плагине на квиклут наличие инвентаря игрока на экране определяется так:
C++:
if (player->inventory2.IsOpen() && oCNpc::game_mode != NPC_GAME_PLUNDER)
 

DAMROCK

Участник форума
Регистрация
23 Янв 2017
Сообщения
22
Благодарности
5
Баллы
160
DAMROCK, чем тебе через player не понравилось? Там есть объект inentory2 (oCNpcInventory → oCItemContainer). Поиском по Gothic API можно найти список s_openContainers, вот в нем будут лежать все открытые в данный момент контейнеры. Если твой player->inventory2 является частью этого списка, то значит инвентарь игрока открыт.
Спасибо за разъяснение.
Возник такой вопрос о барах: хочу реализовать вертикальный бар, можно ли как-то переключить направление сжатия текстуры с x на y?
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.301
Благодарности
4.636
Баллы
625
Сверху Снизу