Уважаемые гости и новички, приветствуем Вас на нашем форуме
Здесь вы можете найти ответы практически на все свои вопросы о серии игр «Готика» (в том числе различных модах на нее), «Ведьмак», «Ризен», «Древние свитки», «Эра дракона» и о многих других играх. Можете также узнать свежие новости о разработке новых проектов, восхититься творчеством наших форумчан, либо самим показать, что вы умеете. Ну и наконец, можете обсудить общие увлечения или просто весело пообщаться с посетителями «Таверны».
Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно. Вам необходимо обновить браузер или попробовать использовать другой.
Не уверен, что я понял, о чём ты спрашиваешь. Возможно, вопрос об объекте игрового мира (не помню название), который наносит урон при пересечении его поверхности. Такие объекты действительно работают ненадёжно, по крайней мере в Г1. Если вопрос об этом, то можно попробовать активировать у объекта повторное нанесение урона. В свойствах объекта можно установить интервал времени, через который будет наноситься новая порция урона.
не в vdf? Я хочу один доспех из Архолоса вытащить, я правильно понял, что теперь искать его в файлах KM_Anims и KM_Textures? Приложение скачал, с помощью него и открываю эти vdf
Не подскажешь, где хранятся данные получаемого опыта за убийство мобов?
А то в исправленных скриптах, у ряда мобов, опыт несколько порезан и хотелось бы восстановить справедливость, так сказать.
В XP_Constans.b не увидел инфы, например, о том же молодом волке, другого файла со схожим названием найти не удалось.
// 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
1) Если тебе нужен компилятор (v100), то нужно установить ещё и Visual Studio 2010.
Название образа VS 2010: "ru_visual_studio_2010_professional_x86_528367.iso", ну либо то, что найдёшь в сети.
2) По поводу перехватчиков. Они работают по адресам функций. Например:
Здесь "pGame_SetShowPlayerStatus" - это указатель на оригинальную перехватываемую функцию,
"Game_SetShowPlayerStatus" - это та функция, в которую будет перенаправлен вызов.
Если в своём проекте ты откроешь файл: "Engine SDK\1. Gothic I\Names_G1.hpp", и с помощью поиска(Ctrl+F) найдёшь в нём адрес 0x00638BE0, то он укажет на функцию:
В каждом движке свои адреса функций. И то есть, используя адреса Г1 из того примера, но уже в движке Г2а, ты можешь попасть на случайную функцию или область памяти, которые могут иметь непредсказуемые последствия или просто вылет, при условии что конфигурация решения была для Г2а. А чтобы этого не произошло, тебе нужно поменять все адреса перехватчиков в коде.
Ищешь и подставляешь всё аналогичным образом:
Заходишь в файл: "Engine SDK\4. Gothic II NoTR\Names_G2A.hpp", находишь в нём интересующую функцию по названию:
Но будь внимателен при переносе функций, т.к. для разных движков они могут выглядеть по разному:
Поэтому сверяй:
- тип: void
- соглашение о вызовах: __thiscall
- принадлежность к классу: oCGame::SetShowPlayerStatus
- и аргументы: (int)
В зависимости от этого может меняться код перехватчика.
Ну и естественно, для работы с G2a, необходимо выбрать другую конфигурацию решения "G2A MD Release":
Сейчас популярен другой метод перехвата функций, с помощью так называемой связки HOOK-AS.
Более подробно эту реализацию можешь изучить в других готовых проектах разных форумчан (кто этим занимался, например:
Gratt, Xeдин, Slavemaster ).
Есть ли способ проследить открыт ли инвентарь на экране? хочу записать его состояние в условие. Так же на будущее, как с ним работать, ничего толкового не нашёл
мне бы через union sdk понять как это сделать, думаю тут замешано oCViewDialogInventory, но хотелось бы и другой путь узнать, может я просмотрел. искал через player->, но что-то всё не то
Народ. Как мне мои скрипты написанные на .d запаковать в .vdf формат ? Просто видел некоторые vdf файлы, при распаковке которых (с помощью GothicVDFS) были не dat файлы, а .d (.d скрипты находились в : SYSTEM\AUTORUN). Хотя в уроках писали что нельзя запаковать .d в .vdf...
mas0raksh, Если прям скрипты-скрипты, то лучше пихать их в DAT. и потом уже упаковывать в VDF(MOD).
Если это скриптовые патчи, сделанные на union, то можно просто пихать их в том VDF(MOD).
DAMROCK, чем тебе через player не понравилось? Там есть объект inentory2 (oCNpcInventory → oCItemContainer). Поиском по Gothic API можно найти список s_openContainers, вот в нем будут лежать все открытые в данный момент контейнеры. Если твой player->inventory2 является частью этого списка, то значит инвентарь игрока открыт.
DAMROCK, чем тебе через player не понравилось? Там есть объект inentory2 (oCNpcInventory → oCItemContainer). Поиском по Gothic API можно найти список s_openContainers, вот в нем будут лежать все открытые в данный момент контейнеры. Если твой player->inventory2 является частью этого списка, то значит инвентарь игрока открыт.
Спасибо за разъяснение.
Возник такой вопрос о барах: хочу реализовать вертикальный бар, можно ли как-то переключить направление сжатия текстуры с x на y?
На данном сайте используются файлы cookie, чтобы персонализировать контент и сохранить Ваш вход в систему, если Вы зарегистрируетесь.
Продолжая использовать этот сайт, Вы соглашаетесь на использование наших файлов cookie.