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

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

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

Jr13San


Модостроитель
Регистрация
1 Апр 2010
Сообщения
435
Благодарности
261
Баллы
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 · Просмотры: 117

N1kX


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

Test Level

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

N1kX


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

ElderGamer


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

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

Slavemaster


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

MaGoth

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

Phantom95

Участник форума
Регистрация
31 Июл 2014
Сообщения
2.226
Благодарности
1.907
Баллы
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.226
Благодарности
1.907
Баллы
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 · Просмотры: 25

Gratt


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

Phantom95

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

Вложения

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

ElderGamer


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

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

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

Gratt


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

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

N1kX


Модостроитель
Регистрация
13 Ноя 2009
Сообщения
5.819
Благодарности
5.221
Баллы
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.371
Благодарности
7.801
Баллы
995
это весь файл ?
 

N1kX


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