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

    Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
    Удачи!
  • Друзья, доброго времени суток!
    Стартовал новый литературный конкурс от "Ордена Хранителей" - "Пираты Миртанского моря".
    Каждый может принять в нём участие и снискать славу и уважение, а в случае занятия призового места ещё и получить награду. Дерзайте
  • Дорогие друзья, год подходит к концу, и пришло время подвести его итоги и наградить достойных

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

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

Jr13San


Модостроитель
Регистрация
1 Апр 2010
Сообщения
463
Благодарности
288
Баллы
230
Виртуальный том DeadGoblinFix_Multi.zip распаковать и поместить в папку "Gothic\Data\"
Умеет работать с 4-мя версиями актуальных движков: G1 Classic, G1 Siquel, G2 Classic, G2 Addon.
Кстати, скелеты тоже попали под отбор (подробнее см. гильдии в коде). А вообще проект был полезен для тестов.

Для справки:
C++:
#include "UnionAfx.h"

namespace Gothic_I_Classic {

//********************************************************************
// Чтение свойств НПС из архива (для Г1)
//********************************************************************
//0x006A31E0 protected: virtual void __thiscall oCNpc::Unarchive(class zCArchiver &)
static void __fastcall Npc_Unarchive(oCNpc* _this, void* vt, zCArchiver& ar);
static CInvoke <void(__thiscall*)(oCNpc*, zCArchiver&)> pNpc_Unarchive(0x006A31E0, Npc_Unarchive, Union.GetEngineVersion() == TEngineVersion::Engine_G1 ? IVK_AUTO : IVK_DISABLED);
static void __fastcall Npc_Unarchive(oCNpc* _this, void* vt, zCArchiver& ar)
{
    // Сначала вызываем оригинальную функцию
    pNpc_Unarchive(_this, ar);

    // Если _this - это мёртвый гоблин
    if (_this && (_this->guild == NPC_GIL_GOBBO || _this->guild == NPC_GIL_SKELETON) && _this->attribute[NPC_ATR_HITPOINTS] == 0)
    {
        // берём указатель на модель гоблина
        zCModel* pModel = _this->GetModel();

        // если указателя нет, то выходим
        if (!pModel) return;

        // получаем указатель на узел правой руки
        zCModelNodeInst* pNodeInst = pModel->SearchNode(NPC_NODE_RIGHTHAND);
        
        // если указателя нет, то выходим
        if (!pNodeInst)    return;

        // иначе, стираем визуал узла
        pModel->SetNodeVisual(pNodeInst, NULL, FALSE);
    }
}


}



namespace Gothic_I_Addon {

// 0x006D5AD0 protected: virtual void __thiscall oCNpc::Unarchive(class zCArchiver &)
static void __fastcall Npc_Unarchive(oCNpc* _this, void* vt, zCArchiver& ar);
static CInvoke <void(__thiscall*)(oCNpc*, zCArchiver&)> pNpc_Unarchive(0x006D5AD0, Npc_Unarchive, Union.GetEngineVersion() == TEngineVersion::Engine_G1A ? IVK_AUTO : IVK_DISABLED);
static void __fastcall Npc_Unarchive(oCNpc* _this, void* vt, zCArchiver& ar)
{
    pNpc_Unarchive(_this, ar);

    if (_this && (_this->guild == NPC_GIL_GOBBO || _this->guild == NPC_GIL_SKELETON) && _this->attribute[NPC_ATR_HITPOINTS] == 0)
    {
        zCModel* pModel = _this->GetModel();
        if (!pModel)
            return;

        zCModelNodeInst* pNodeInst = pModel->SearchNode(NPC_NODE_RIGHTHAND);
        if (!pNodeInst)
            return;

        pModel->SetNodeVisual(pNodeInst, NULL, FALSE);
    }
}


}



namespace Gothic_II_Classic {

// 0x006E8790 protected: virtual void __thiscall oCNpc::Unarchive(class zCArchiver &)
static void __fastcall Npc_Unarchive(oCNpc* _this, void* vt, zCArchiver& ar);
static CInvoke <void(__thiscall*)(oCNpc*, zCArchiver&)> pNpc_Unarchive(0x006E8790, Npc_Unarchive, Union.GetEngineVersion() == TEngineVersion::Engine_G2 ? IVK_AUTO : IVK_DISABLED);
static void __fastcall Npc_Unarchive(oCNpc* _this, void* vt, zCArchiver& ar)
{
    pNpc_Unarchive(_this, ar);

    if (_this && (_this->guild == NPC_GIL_GOBBO || _this->guild == NPC_GIL_GOBBO_SKELETON || _this->guild == NPC_GIL_SUMMONED_GOBBO_SKELETON) && _this->attribute[NPC_ATR_HITPOINTS] == 0)
    {
        zCModel* pModel = _this->GetModel();

        if (!pModel)
            return;
        
        // объявляем пустой указатель на узел
        zCModelNodeInst* pNodeInst = NULL;

        // пробегаемся по всем узлам модели
        for(int i = 0; i < pModel->nodeList.GetNum(); i++)
        {
            // проверяем указатель на прототип узла, если в порядке, то продолжаем
            if (pModel->nodeList[i]->protoNode)
            {
                // извлекаем название узла
                string nodeName = pModel->nodeList[i]->protoNode->nodeName;

                // если это узел правой руки (сравниваются названия)
                if (nodeName.Compare(NPC_NODE_RIGHTHAND))
                {
                    // запоминаем указатель на узел
                    pNodeInst = pModel->nodeList[i];

                    // выходим из цикла
                    break;
                }
            }
        }

        // если указатель на узел правой руки не найден
        if (!pNodeInst)
            // выходим из функции
            return;
        // иначе, стираем визуал узла
        pModel->SetNodeVisual(pNodeInst, NULL, FALSE);
    }
}


}



namespace Gothic_II_Addon {

// 0x00747230 protected: virtual void __thiscall oCNpc::Unarchive(class zCArchiver &)
static void __fastcall Npc_Unarchive(oCNpc* _this, void* vt, zCArchiver& ar);
static CInvoke <void(__thiscall*)(oCNpc*, zCArchiver&)> pNpc_Unarchive(0x00747230, Npc_Unarchive, Union.GetEngineVersion() == TEngineVersion::Engine_G2A ? IVK_AUTO : IVK_DISABLED);
static void __fastcall Npc_Unarchive(oCNpc* _this, void* vt, zCArchiver& ar)
{
    pNpc_Unarchive(_this, ar);
    
    if (_this && (_this->guild == NPC_GIL_GOBBO || _this->guild == NPC_GIL_GOBBO_SKELETON || _this->guild == NPC_GIL_SUMMONED_GOBBO_SKELETON) && _this->attribute[NPC_ATR_HITPOINTS] == 0)
    {
        zCModel* pModel = _this->GetModel();
        if (!pModel)
            return;

        zCModelNodeInst* pNodeInst = pModel->SearchNode(NPC_NODE_RIGHTHAND);
        if (!pNodeInst)
            return;
        
        pModel->SetNodeVisual(pNodeInst, NULL, FALSE);
    }
}


}
PHP:
// G1
#engine [0x225BA11E]
    #patch [Fix]
        LoadLibrary ("DeadGoblinFix.dll")
    #/patch
#/engine

// G1A
#engine [0x02648DED]
    #patch [Fix]
        LoadLibrary ("DeadGoblinFix.dll")
    #/patch
#/engine

// G2
#engine [0xA2EE682C]
    #patch [Fix]
        LoadLibrary ("DeadGoblinFix.dll")
    #/patch
#/engine

// G2A
#engine [0x2BCD7E30]
    #patch [Fix]
        LoadLibrary ("DeadGoblinFix.dll")
    #/patch
#/engine
 

Вложения

  • DeadGoblinFix_Multi.zip
    8,5 KB · Просмотры: 125

N1kX


Модостроитель
Регистрация
13 Ноя 2009
Сообщения
6.176
Благодарности
5.697
Баллы
910
Насчет скелетов, никто не замечал у них оружия в слоте после смерти... Узнал новенькое :)
 

Test Level

Участник форума
Регистрация
1 Ноя 2011
Сообщения
1.770
Благодарности
557
Баллы
275
N1kX, возможно, имелись ввиду скелеты гоблинов.
 

N1kX


Модостроитель
Регистрация
13 Ноя 2009
Сообщения
6.176
Благодарности
5.697
Баллы
910
Ну, увидел проверку на гильдию скелетов гоблинов, извиняюсь
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.410
Благодарности
3.241
Баллы
525
Тебя же это не пугает? Тот же сп, только умеет в разы больше.
Главное, чтобы это НЕ пугало игроков. СистемПак сейчас уверенно занимает категорию "мастхэв". А вот по поводу Юни не знаю, насколько она популярна у игроков, и насколько охотно они переходят на эту платформу. Предполагаю, что Юня станет наследницй СистемПака. В будущем.

Насчет скелетов, никто не замечал у них оружия в слоте после смерти... Узнал новенькое :)
Имеются в виду скелеты из Г1, которые вооружаются аналогично гоблинам. Но анимация смерти у них такова, что появившегося в слоте оружия практически не видно.
 

Slavemaster


Модостроитель
Регистрация
10 Июн 2019
Сообщения
1.086
Благодарности
1.910
Баллы
320
не знаю, насколько она популярна у игроков
Как только станет популярна у мододелов, станет популярна и у игроков. Оно же несложно ставится: ставишь готику и через ресурс менеджер ставишь патч и сам юнион. Всё.
 

MaGoth

★★★★★★★★★★★
Администратор
Регистрация
7 Янв 2003
Сообщения
19.367
Благодарности
7.816
Баллы
995
ElderGamer, так Юня это и есть СП только с кучей доп., возможностей.. *ded*
 

Phantom95

Участник форума
Регистрация
31 Июл 2014
Сообщения
2.227
Благодарности
1.911
Баллы
370
Как насчёт реализации такой внутренней функции движка на базе юниона?
Посильная ли задача?
Примеры её использования привёл в теме по доработке сиквела. Если в кратце, то она нужна для нормальной визуализации процесса передачи предмета между нпс и визуализации сбора пищи в короб, к примеру для нпс работающих в поле или травников/друидов/алхимиков и т.д. и т.п.

Daedalus:
FUNC VOID AI_PlayAniWithItems (VAR C_NPC n0, VAR STRING s0, VAR C_ITEM i1, VAR INT num1, VAR STRING "ZS_RIGHTHAND" VAR C_ITEM i2, VAR INT num2, VAR STRING "ZS_LEFTHAND", VAR INT num3, VAR INT num4) { };



n0 - инстанция нпс, s0 - название анимации, i1 - первый предмет, который будет добавлен в правую руку в num1 кадре анимации, i2 - второй предмет, который будет добавлен в левую руку в num2 кадре анимации, num3 - кадр удаления первого предмета от правой руки, num4 - кадр удаления второго предмета от левой руки.
 

Phantom95

Участник форума
Регистрация
31 Июл 2014
Сообщения
2.227
Благодарности
1.911
Баллы
370
В Humans.mds:
// Reis aufklauben und in Korb ablegen
ani ("t_PickRice" 2 "" 0.1 0.1 M. "Hum_PickRice_M01.asc" F 141 189 FPS:10)

Экземпляр C_ITEM:
instance ITMI_RICE(C_Item)
{
name = NAME_RICE;
mainflag = ITEM_KAT_NONE;
flags = ITEM_MULTI;
value = Value_MobsiItem;
visual = "BASKET_RICE.ASC";
material = MAT_METAL;
description = name;
text[5] = NAME_Value;
count[5] = Value_MobsiItem;
};
 

Вложения

  • HUMANS-T_PICKRICE.rar
    3,2 KB · Просмотры: 26

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.301
Благодарности
4.641
Баллы
625
Phantom95 Не пойдет. Дай мне исходник анимации...
 

Phantom95

Участник форума
Регистрация
31 Июл 2014
Сообщения
2.227
Благодарности
1.911
Баллы
370

Вложения

  • HUM_PICKRICE_M01.rar
    42,8 KB · Просмотры: 24

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.410
Благодарности
3.241
Баллы
525
она нужна для нормальной визуализации процесса передачи предмета между нпс
Гм. Вот Ведьмак 3, вроде бы, довольно продвинутая игра в плане анимаций. По сравнению с Готикой, уж точно. Но даже там нет такого. Думаю, реализация плавной передачи предмета из слота в слот - непростая задача. Нужно в процессе проигрывания анимации передачи как-то совместить в одной точке два слота с полным совпадением координат и ориентации в пространстве. Не уверен, что это реализуемо на готическом движке.

и визуализации сбора пищи в короб
А здесь, как мне кажется, задача ещё более сложная, чем в предыдущем случае. При нормальной реализации. :confused:

Декомпиляция анимаций с таким ключом, к сожалению, часто приводит к тому, что исходник оказывается повреждённым. То ли кадры там перепутаны местами, то ли попытка восстановить отсутствующие кадры глючит.
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.301
Благодарности
4.641
Баллы
625
ElderGamer объединить вектора слотов то я могу, равно как и ненавязчивый менеджер анимации.. Тут вопрос не в сложности. Просто нахрена оно надо? :)
Я бы лучше сделал расшаривание сундука с периодическим доставанием рандомного содержимого, чисто чтобы персонаж просто поглазел на него и засунул обратно.

В качестве условия выступал бы радиус bbox объекта и, если он размером где-то с кулак, триггерил бы персонажа на действие. Например яблоко или кошель золота.
 

N1kX


Модостроитель
Регистрация
13 Ноя 2009
Сообщения
6.176
Благодарности
5.697
Баллы
910
Spacer или GS упорно пытаются показать, что пропущено ; (типо пропущено у return 1 )
Я в упор не вижу, где пропустил ;
Все переменные определены в Story_Global
Значения правильные использую...
Daedalus:
//функция, чтобы считывать значения из выбранного пункта из меню
func void logentry_func()
{
    //новая переменная
    var string newlogentry;
    //считываем эту переменную из меню
    newlogentry = mem_getgothopt("MOD_PREDO", "LOG_ENTRY");
    //дальше необходимо проверить выбранное значение и произнести необходимые настройки,
    //если выбрано выкл, то будет старая система вывода, в другом случае новая
    if(hlp_strcmp(newlogentry, "0") && (!hlp_strcmp(newlogentry, "1")))
    {
        newlogentrys = FALSE;
        oldlogentrys = TRUE;
        return 1;
    }
    else if(hlp_strcmp(newlogentry, "1") && (!hlp_strcmp(newlogentry, "0")))
    {
        newlogentrys = TRUE;
        oldlogentrys = FALSE;
        return 1;
    };
    return 0;
};

00:12 Fatal:-1 Expected ';' ( line 14 ) .... <zParser.cpp,#599>
00:12 Fatal:-1 Unknown identifier : ; ( line 14 ) .... <zParser.cpp,#599>
 

MaGoth

★★★★★★★★★★★
Администратор
Регистрация
7 Янв 2003
Сообщения
19.367
Благодарности
7.816
Баллы
995
это весь файл ?
 

N1kX


Модостроитель
Регистрация
13 Ноя 2009
Сообщения
6.176
Благодарности
5.697
Баллы
910
Сверху Снизу