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

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

новые внешние функции

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
971
Баллы
295
на базе Union можно создавать новые внешние функции которые могут решить ту или иную задачу при написание скриптов. Подробнее про то как создаются внешние функции можно почитать в топике @Slavemaster.

В данном топике я предлагаю выложить уже готовые внешние функции.
названиеописаниефункцияфайлподробнее
Экипировка НПС указанное оружие
Daedalus:
func void NPC_EquipWeapon(var C_NPC npc, var c_item itm );
Externals_MW7.dll
Функции для работы с парсерами - PARzParserExtender.dll
Имитация событий анимацийzOrcHunter.vdf
Функции работы с дневником - LOGzParserExtender.dll
Функции работы с вобами (прокси-классы) - VOBzParserExtender.dll
Вспомогательные возможностиzParserExtender.dll
Внешние переменныеzParserExtender.dll
funcName в AI очередьzParserExtender.dll
Замена торговца
Daedalus:
func void NPC_SetTrader(var c_npc newnpc)
Externals_MW7.dll
Открыть / закрыть инвентарь
Daedalus:
func void NPC_CloseInventory(var c_npc)

func void NPC_OpenInventory(var c_npc,var INV_MODE)
Externals_MW7.dll
Смена собеседника
Daedalus:
func void npc_setTalking(var c_npc newnpc)
Externals_MW7.dll
...


обновленно 1.11.2023
 

Вложения

  • zParserExtender.zip
    298,8 KB · Просмотры: 8
  • 2023_11_1_Externals_MW7.zip
    23,2 KB · Просмотры: 5
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
971
Баллы
295
Экипировка НПС указанное оружие
Daedalus:
func void NPC_EquipWeapon(var C_NPC npc, var c_item itm );
данную функцию лучше "завернуть" и сделать пару внутренних функций с более "тонкими" настройками

№ п/п
***********
кодпример использования
1(1)функция int проверяет есть ли инстанция оружия в инвентаре НПС и если есть то экипирует и возвращает true.

Daedalus:
func int C_NPC_EquipWeapon(var C_NPC npc, var int itmWeapon )
{
    if Npc_GetInvItem(npc,itmWeapon)
    {
        NPC_EquipWeapon(npc,item);
        return true;
    };
    return false;
};
Daedalus:
func void DIA_****_Info()
{
    if (C_NPC_EquipWeapon(self,ItMw_2h_Sld_Axe))
    {
       // у нпс есть указанного оружие --> одеваем
      // бла бла
    }
   else
    {
       // у нпс нет указанного оружия
        AI_EquipBestMeleeWeapon(self);
    };
};
2(2)функция void если инстанции оружия в инвентаре нет, то создаётся новая. указанное оружие одевается

Daedalus:
func void B_NPC_EquipWeapon(var C_NPC npc, var int itmid )
{
    if (!Npc_GetInvItem(npc,itmid))
    {
        CreateInvItem (npc, itmid);
        Hlp_PrintConsole(Str_Format("  B_NPC_EquipWeapon[%s] --> return true", npc.name));
    };
    NPC_EquipWeapon(npc,item);
};
Daedalus:
    B_NPC_EquipWeapon(self,ItMw_2h_Pal_Sword);

Код:
    B_NPC_EquipWeapon(hero,ulumulu); // герой одеват улу-мулу

Daedalus:
var c_npc npc; = Hlp_GetNpc (PAL_200_Hagen);
B_NPC_EquipWeapon(npc,ItMw_2H_Blessed_02); // Лорд Хаген одевает Меч Ордена
при необходимости функции можно дописать: проверять флаги оружия, сравнивать параметры НПС и требования оружия и т.д. и т.п.
Daedalus:
func void B_Update_AtrNPC (var C_Npc slf, var C_item itm)
{
    Hlp_msg = Str_Format("  B_Update_AtrNPC[%s]: %s", slf.name, itm.name);
 
    if (itm.cond_atr[2] ==    ATR_STRENGTH)
    {
        if (slf.attribute[ATR_STRENGTH] < itm.cond_value[2])
        {
            slf.attribute[ATR_STRENGTH] = itm.cond_value[2];
            Hlp_msg = Str_Format("%s ATR_STRENGTH = %i", Hlp_msg, itm.cond_value[2]);
        };
    }
    else if (itm.cond_atr[2] ==    ATR_DEXTERITY)
    {
        if (slf.attribute[ATR_DEXTERITY] < itm.cond_value[2])
        {
            slf.attribute[ATR_DEXTERITY] = itm.cond_value[2];
            Hlp_msg = Str_Format("%s ATR_DEXTERITY = %i", Hlp_msg, itm.cond_value[2]);
        };
    }
    else
    {
        Hlp_msg = Str_Format("%s пропуск", Hlp_msg);
    };
 
    Hlp_PrintConsole(Hlp_msg);
};





Код:
namespace NAMESPACE
{
    int __cdecl NPC_EquipWeapon()
    {
        // сохран¤ем состо¤ние текущего парсера:
        // - текущую инстанцию (используетс¤ в коде инстансов)
        // - переменные HERO, SELF, OTHER, VICTIM, ITEM (если мы в основном парсере)
        ParserScope scope{ zCParser::GetParser() };

        oCNpc* npc;
        oCItem* pItem;

        // достаЄм аргументы из парсера
        ZARGS(npc, pItem);

        ASSERT(npc);

        //ogame->GetTextView()->PrintTimedCXY(Z"Key removed: " + npc->name + pItem->name, 5000.0f, nullptr);
        //npc->EquipItem(pItem);
        npc->EquipWeapon(pItem);
        //npc->EquipArmor(pItem);
 
        return 0;
    }

    ZEXTERNAL(void, NPC_EquipWeapon, oCNpc*, oCItem*);
}

функция добавлена в Externals_MW7.dll
 

Вложения

  • zNPC_EquipWeapon.zip
    21,4 KB · Просмотры: 3
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
971
Баллы
295
Имитация событий анимаций
  1. Npc_TriggerAniEvent - обрабатывает событие мгновенно
  2. AI_TriggerAniEvent - ставит событие в очередь
Аргументы:
  1. NPC
  2. Идентификатор события: число от 6 до 11, соответствующее этим константам
    1684851040480.png
  3. Строка - название связанного слота
  4. Целое число - индекс предмета или -1
Пример вызова: AI_TriggerAniEvent(hero, 11, "ZS_LEFTHAND", ItFo_Bread)

Slavemaster написал(а):
Пример вызова: AI_TriggerAniEvent(hero, 11, "ZS_LEFTHAND", ItFo_Bread)
C++:
namespace NAMESPACE
{
    oCMsgManipulate* TriggerAniEventImpl(oCNpc*& npc)
    {
        int subtype;
        zSTRING slotName;
        int instance;

        ZARGS(npc, subtype, slotName, instance);

        if (npc && npc->homeWorld && subtype >= oCMsgManipulate::EV_INSERTINTERACTITEM && subtype <= oCMsgManipulate::EV_EXCHANGEINTERACTITEM)
        {
            zSTRING itemName = (instance > 0) ? COA(parser, GetSymbol(instance), name) : "";
            return new oCMsgManipulate(static_cast<oCMsgManipulate::TManipulateSubType>(subtype), itemName, slotName);
        }

        return nullptr;
    }

    int __cdecl AI_TriggerAniEvent()
    {
        ParserScope scope{ parser };
        oCNpc* npc;

        if (oCMsgManipulate* message = TriggerAniEventImpl(npc))
            npc->GetEM()->OnMessage(message, npc);

        return false;
    }

    int __cdecl Npc_TriggerAniEvent()
    {
        ParserScope scope{ parser };
        oCNpc* npc;

        if (ZOwner<oCMsgManipulate> message{ TriggerAniEventImpl(npc) })
            npc->OnMessage(message.get(), npc);

        return false;
    }

    ZEXTERNAL(void, AI_TriggerAniEvent, oCNpc*, int, zSTRING, int);
    ZEXTERNAL(void, Npc_TriggerAniEvent, oCNpc*, int, zSTRING, int);
}
 

Вложения

  • zOrcHunter.vdf
    94,5 KB · Просмотры: 1
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
971
Баллы
295
Функции работы с дневником - LOG
Daedalus:
// Возвращает статус записи в дневнике:
// Отсутствует - (-1)
// Free - 0
// Running - 1
// Success - 2
// Failure - 3
// Obsolete - 4
func int Log_GetTopicStatus(var string topic)

// Возвращает страницу на которой расположена запись в дневнике.
// Отсутствует - (-1)
// Missions - 0
// Notes - 1
// All - 2
func int Log_GetTopicSection(var string topic)
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
971
Баллы
295
Функции работы с вобами (прокси-классы) - VOB
Daedalus:
// Возвращает текущую позицию объекта в мире
func C_Position Vob_GetVobPosition( var C_Vob vob )

// Задает текущую позицию объекта в мире
func void Vob_SetVobPosition( var C_Vob vob, var C_Position pos )

// Возвращает универсальные данные объекта zCVob
func C_Vob_Data Vob_GetVobData( var C_Vob vob )

// Задает универсальные данные объекта zCVob
func void Vob_SetVobData( var C_Vob vob, var C_Vob_Data data )

// Возвращает данные объекта zCVobLight
func C_Light_Data Vob_GetLightData( var C_Vob vobLight )

// Задает данные объекта zCVobLight
func void Vob_SetLightData( var C_Vob vobLight, var C_Light_Data data )

// Очищает список цветов анимации для источника света
func void Vob_ClearLightAniList( var C_Vob vobLight )

// Добавляет позицию в список цветов
func void Vob_AddLightAniColor( var C_Vob vobLight, var C_Color col )

// Добавляет позицию в список цветов
func void Vob_AddLightAniColorRGB( var C_Vob vobLight, var int r, var int g, var int b )

// Возвращает данные объекта oCMOB
func C_Mob_Data Vob_GetMobData( var C_Vob mob )

// Задает данные объекта oCMOB
func void Vob_SetMobData( var C_Vob mob, var C_Mob_Data data )

// Возвращает данные объекта oCMobInter
func C_MobInter_Data Vob_GetMobInterData( var C_Vob mobInter )

// Задает данные объекта oCMobInter
func void Vob_SetMobInterData( var C_Vob mobInter, var C_MobInter_Data data )

// Возвращает данные объекта oCMobLockable
func C_MobLockable_Data Vob_GetMobInterData( var C_Vob mobLock )

// Задает данные объекта oCMobLockable
func void Vob_SetMobInterData( var C_Vob mobLock, var C_MobLockable_Data data )
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
971
Баллы
295
Вспомогательные возможности

Daedalus:
// Если функция определена в скриптах, то она будет вызываться каждый кадр
func event GameLoop()

// А эта функция будет вызвана при входе в игровое меню
func event GameInit()
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
971
Баллы
295
Внешние переменные
var int DIA_CurrentInstance - содержит ID текущей инстанции C_Info. Может значительно упростить код или сделать его универсальнее. Следует определить в скриптах. Сценарии использования:
Daedalus:
Info_ClearChoices(DIA_CurrentInstance)
Info_AddChoice(DIA_CurrentInstance, ..., ...)
Npc_KnowsInfo(hero, DIA_CurrentInstance)
Создание функции-обертки на основе этой переменной:
Daedalus:
func int C_HeroKnowsCurrentInfo()
{
return Npc_KnowsInfo(hero, DIA_CurrentInstance);
};
var string DIA_CurrentName - содержит имя текущей инстанции C_Info. Может быть полезно в отладочных целях. Следует определить в скриптах. Сценарии использования:
Daedalus:
Hlp_PrintConsole(DIA_CurrentName)
Hlp_PrintConsole(Str_Format("%s[%s]", DIA_CurrentName, self.name))
Hlp_StrCmp(DIA_CurrentName, "DIA_DiegoOw_Teach")
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
971
Баллы
295
funcName в AI очередь
Daedalus:
// Ставит вызов функции funcName в AI очередь
// и при ее вызове помещает значения slf & oth
// в глобальные self & other (соотвественно)
func void AI_CallScript(var string funcName, var C_Npc slf, var C_Npc oth)

ставим в очередь проигрывания звука о повышение уровня. B_GivePlayerXP
Daedalus:
func void B_SndPlay_LEVELUP()
{
    Snd_Play ("LEVELUP");
};

Daedalus:
    if(hero.exp >= hero.exp_next)
    {
        hero.level                          += 1;
        hero.exp_next                       += (hero.level + 1) * 500;
 
        hero.attribute[ATR_HITPOINTS_MAX]   += HP_PER_LEVEL;
        hero.attribute[ATR_HITPOINTS]       += HP_PER_LEVEL;
 
        hero.lp                             += LP_PER_LEVEL;
 
        AI_PrintScreen (PRINT_LEVELUP,-1,YPOS_LEVELUP,FONT_SCREEN,2);
        AI_CallScript("B_SndPlay_LEVELUP", self, other);
    };
удаление старое брони ПОСЛЕ получения новой.

(что бы НПС не стоял "голый" во время диалога)
Daedalus:
func void B_Remove_OldArmor()
{
    Hlp_PrintConsole("  B_Remove_OldArmor...");
    if (C_IsNpc(self,KDF_500_Pyrokar) == true)
    {
        if(Kapitel == 1)    {  B_GiveInvItems(hero,self,ITAR_NOV_L,1); };
        if(Kapitel == 3)    {  B_GiveInvItems(hero,self,ITAR_KDF_L,1); };

    };

    if (C_IsNpc(self,PAL_200_Hagen) == true)
    {
        Hlp_PrintConsole("  B_Remove_OldArmor --> ITAR_MIL_L");
        B_GiveInvItems(hero,self,ITAR_MIL_L,1);
    };
};


func void B_GiveArmor(var int itemInstance)
{
    CreateInvItem(hero,itemInstance);
    AI_PrintScreen(ConcatStrings(item.description,PRINT_ItemTaken),-1,YPOS_ItemTaken,FONT_ScreenSmall,2);
    
    if (C_IsNpc(self,KDF_500_Pyrokar) == true)
    || (C_IsNpc(self,PAL_200_Hagen) == true) 
    {
        AI_EquipArmor(hero,itemInstance);
        AI_CallScript("B_Remove_OldArmor", self, other);
    };
};
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
971
Баллы
295
Замена торговца
Daedalus:
 func void NPC_SetTrader(var c_npc newnpc)
Может решать такие задачи как:
  • создание общего ассортимента для нескольких торговцев
  • использования клона НПС для торговли (нельзя будет ограбить)
пример использования
Daedalus:
INSTANCE DIA_Lee_trader(C_INFO)
{
    npc         = SLD_800_Lee;
    nr          = 99;
    condition   = DIA_Lee_trader_Condition;
    information = DIA_Lee_trader_Info;
    permanent   = TRUE;
    trade        = TRUE;
       description = DIALOG_TRADE_v4;
};


FUNC INT DIA_Lee_trader_Condition()
{
    if (self.aivar[AIV_TalkedToPlayer] == TRUE)
    {
        return TRUE;
    };
};

FUNC VOID DIA_Lee_trader_Info()
{
    //AI_Output (other, self, "DIA_Khaled_TRADE_15_00");
 
    AI_Output(other,self,"DIA_Zuris_WAREZ_15_00");
    //Покажи мне свои товары.
    AI_Output(self,other,"DIA_Lee_PMSchulden_04_05");

    var c_npc newnpc;  newnpc = Hlp_GetNpc(SLD_823_Khaled);
 
    B_GiveTradeInv(newnpc);
    NPC_SetTrader(newnpc);
};
функцию добавил в плагин. плагин обновил в первом сообщение.

p.s.
Данное решение предложил Gratt в 2018 тут Не стесняюсь спросить....
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
971
Баллы
295
Код:
//  func void NPC_CloseInventory(var c_npc);
функция закрывает инвентарь. мне эта функция понадобилась для закрытия инвентаря когда герой употребялет "Северный Тёмный". Применять вы её можете там где инвентарь мешает, например при игре на лютни, использование метлы и так далее
если герой употребляет "северный тёмный", то инвентарь закрывается
Код:
func void Use_Joint()
{
    if (Npc_IsPlayer (self))
    {
        NPC_CloseInventory(hero);
        Wld_PlayEffect ("SLOW_TIME", self, self, 0, 0, 0, FALSE);
    };
};
игра на Лютне
Код:
func void UseLute()
{
    if Npc_IsPlayer(self)
    {
        NPC_CloseInventory(self);
    
        if (Play_Lute == FALSE)
        {
            B_GiveXP (10);
            Play_Lute = TRUE;
        };
    };
};


1686774659790.jpeg
1686774666398.jpeg


функция добавлена в Externals_MW7.dll

***

Код:
//  func void NPC_OpenInventory(var c_npc,var INV_MODE);
функция открывает инвентарь.

код для теста
C++:
func event GameLoop()
{

    if      (Hlp_KeyToggled(KEY_NUMPAD0))    {   NPC_OpenInventory(hero,0);  }      //INV_MODE_DEFAULT,       // 0
    else if (Hlp_KeyToggled(KEY_NUMPAD1))    {   NPC_OpenInventory(hero,1);  }   //INV_MODE_CONTAINER,   // 1
    else if (Hlp_KeyToggled(KEY_NUMPAD2))    {   NPC_OpenInventory(hero,2);  }   //INV_MODE_PLUNDER,      // 2
    else if (Hlp_KeyToggled(KEY_NUMPAD3))    {   NPC_OpenInventory(hero,3);  }   //INV_MODE_STEAL,       // 3
    else if (Hlp_KeyToggled(KEY_NUMPAD4))    {   NPC_OpenInventory(hero,4);  }   //INV_MODE_BUY,          // 4
    else if (Hlp_KeyToggled(KEY_NUMPAD5))    {   NPC_OpenInventory(hero,5);  };   //INV_MODE_SELL,        // 5
                                                                                                                                 //INV_MODE_MAX          // 6
};

1685540606323.jpeg
1685540594739.jpeg
1685540599531.jpeg

функция добавлена в Externals_MW7.dll

***
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
От резервист)))
 

MW 7


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

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
971
Баллы
295
ElderGamer а ты не пробовал на движке Г1 использовать AI_CallScriptдля вывода текста на экран например при записи в журнал ? я помню что у тебя в коде как то хитро ставилось в очередь AI такие вещи :)
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
а ты не пробовал на движке Г1 использовать AI_CallScript
Нет, не пробовал. В текущей сборке мод-фикса пока сохраняется возможность работы без наличия Union. Поэтому некоторые вещи работают "на костылях". Юня используется для реализации дополнительных возможностей и исправления косяков. И пока нужды в использовании этой функции не было.
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Тут определяющим фактором является то, что работа со скриптами происходит с использованием Соурсера, а это сразу исключает из использования в проекте все функции, которых он не знает. Для использования новых функций приходится вводить в скрипты мини-функции пустышки, которые подменяются средствами Union на вариант, в котором эти новые функции присутствуют. Соответственно, проект, компилируемый Соурсером, должен сохранять работоспособность и без использования возможностей Юнион.
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
971
Баллы
295
Тут определяющим фактором является то, что работа со скриптами происходит с использованием Соурсера, а это сразу исключает из использования в проекте все функции, которых он не знает
Gratt же в Sourcer добавил меню для новых внешних функций
6. Добавлено полноценное меню для новых внешних функций.
1587176759444.png
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Честно говоря, из описания не понял, что это даёт. :)
 

MW 7


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