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

    Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
    Удачи!
  • Друзья, доброго времени суток! Спешите принять участие в оценке работ на конкурсе "Таинственные миры" 2024!
    Ждем именно вас!

    Ссылка на конкурсную тему - тык
    Ссылка на тему с работами участников- тык

В разработке... триггеры на юнион

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.923
Благодарности
926
Баллы
275
Традиционно я начну со слов благодарности Gratt который лишает нас костылей.​

Для работы Триггеров потребуется последняя версия юнион вкоторую входит zparser. Ссылка на тему с юнион Gothic ½ - Union (патч для Gothic)

где нибудь в файле скриптов пропишете класс триггера и две инстанции
Daedalus:
//класс триггера
class C_Trigger
{
  var int Delay;
  var int Enabled;
  var int AIVariables[16];
};
 
instance SelfTrigger (C_Trigger) {};
instance FirstTrigger (C_Trigger) {};

Локальныйглобальный
в локальном триггере может быть записано 1-3 НПС
  1. NPC, который при вызове функции будет помещаться в self.
  2. NPC, который при вызове функции будет помещаться в other.
  3. NPC, который при вызове функции будет помещаться в victim.
в глобальном триггере нет записанных НПС
AI_StartTriggerScriptEx("NPC_Trigger_Attribute_TimeBonus", 1, hero, null, null)AI_StartTriggerScriptEx("NPC_Trigger_Attribute_TimeBonus", 1, null, null, null)
AI_StartTriggerScript("NPC_Trigger_Attribute_TimeBonus", 1)
подробнее Gothic ½ - Расширение возможностей парсера | zParserExtender [плагин для Union]
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.923
Благодарности
926
Баллы
275
Баффы от зелий

Баффы будем реализовывать на примере зелий повышающих на время атрибуты НПС.
Инстанции зелий
Пропишем инстанции новых зелий. В инстанции зелий я указываю параметры для баффа.
Daedalus:
instance ItPo_Bonus_MANA(C_Item)
{
    ...
    ...
 
    on_state[0] = UseItPo_TimeBonus;

    cond_atr[1] = ATR_MANA;           // атрибут который меняем
 
    TEXT[1]     = NAME_Bonus_MANA;      COUNT[1] =     MANA_Bonus_Elixier;     // на сколько меняется атрибут
    TEXT[2]     = NAME_Sec_Duration;    COUNT[2] =     Time_Bonus_MANA;        // сколько секунд длится эффект
};
функцию use*** делаю общую для всех зелий, беря данные для баффа уже из инстанции зелья.
Daedalus:
    func void UseItPo_TimeBonus()
    {
        Start_Trigger_Attribute_TimeBonus(self, item.cond_atr[1], item.COUNT[1], item.COUNT[2]);
    };

функции запускающей триггер
Первое на что стоит обратить внимание это что триггер может быть глобальный, то есть тот который действует во всех мирах и локальный который "привязан" к НПС и действует в конкретном мире. По рекомендации Гратта будем использовать для героя глобальные триггеры. Поэтому я сделаю проверку ссылки на НПС, если окажется что slf это герой я просто обнулю ссылку, сделав её "пустой".
Daedalus:
if (Npc_IsPlayer(slf))
    {
        // Обнуляем slf  --> Триггер будет глобальным
        slf = Hlp_GetNpc(-1);
    };
далее ставим запуск триггера на "старт" и задаём ему наши свойства:
Daedalus:
trigger = AI_StartTriggerScriptEx("NPC_Trigger_Attribute_TimeBonus", 1, slf, null, null);
trigger.AIVariables[0] = time;           // число повторов(секунд) триггера
trigger.AIVariables[1] = attribute;      // атрибут который будем изменять
trigger.AIVariables[2] = value;          // значение на которое будем менять атрибута
приведу полный код функции запуска. в ней есть закомментированный фрагмент который я использовал в прошлой версии.
Daedalus:
func void Start_Trigger_Attribute_TimeBonus(var c_npc slf,var int attribute,var int value,var int time)
{
    var C_Trigger trigger;
 
    /*
    if (Npc_IsPlayer(slf))
    {
        // Глобальный Триггер для Героя
        trigger = AI_StartTriggerScript("Hero_Trigger_Attribute_TimeBonus", 1); // Global trigger
    }
    else
    {
        // локальный триггер для других НПС
        trigger = AI_StartTriggerScriptEx("NPC_Trigger_Attribute_TimeBonus", 1, slf, null, null); // local trigger
    };
    */
 
    if (Npc_IsPlayer(slf))
    {
        // Обнуляем slf  --> Триггер будет глобальным
        slf = Hlp_GetNpc(-1);
    };
    trigger = AI_StartTriggerScriptEx("NPC_Trigger_Attribute_TimeBonus", 1, slf, null, null);

    //trigger.Delay = 1000;                       // частота вызова триггера. 1000 это раз в секунду. Буду устанавливать внутри NPC_Trigger_Attribute_TimeBonus
     trigger.AIVariables[0] = time;           // число повторов(секунд) триггера
    trigger.AIVariables[1] = attribute;      // атрибут который будем изменять
     trigger.AIVariables[2] = value;          // значение на которое будем менять атрибута
 
    Hlp_PrintConsole(Str_Format(" --> NPC_Trigger_Attribute_TimeBonus slf = %s; time = %i", slf.name, time));
};

функция цикл loop
Важно(!)
ничего не мешает сделать две разные функции, одну для героя, другую для прочих НПС(если это вообще нужно). скорее всего это даже будет правильным.
Ввиду того что в данном примере используется общий цикл луп( и для локального и для глобального триггеров) нужно будет добавить проверка на "self". в глобальном триггере "self" будет пустой.
Daedalus:
func int NPC_Trigger_Attribute_TimeBonus()
{
    var C_Npc npc;
    if (Hlp_IsValidNpc(self))     { npc = Hlp_GetNpc(self);  }
    else                          { npc = Hlp_GetNpc(hero);  };

в первой итерации я делаю проверку на то не запускается ли триггер повторно, это можно сделать проверив соотв. аивиир у НПС или создав у него уникальный предмет. при повторном запуске триггера можно что нибудь сделать с НПС, а триггер уничтожить. так же в первой итерации я устанавливаю частоту вызова триггера, повышаю атрибут и создаю уникальный предмет-маркер.
Daedalus:
    // первая итерация
    if (SelfTrigger.Delay < 1000)
    {
        if Npc_GetInvItem(npc,ItPo_Bonus_Active)
        {
            // у НПС есть ItPo_Bonus_Active, значит это повторный вызов Триггера
            B_KillNPCItPo(npc);
            return LOOP_END;
        };
 
        SelfTrigger.Delay = 1000; // раз в секунду
        CreateInvItem(npc,ItPo_Bonus_Active);
        B_RaiseAttributeTimeBonus(npc,SelfTrigger.AIVariables[1],SelfTrigger.AIVariables[2]);
    };

При выходе из триггера, я удаляю уникальный предмет и изменяю атрибуты НПС.
Daedalus:
    // выход
    if (SelfTrigger.AIVariables[0] <= 0)
    {
        Npc_RemoveInvItem(npc,ItPo_Bonus_Active);
        B_RaiseAttributeTimeBonus(npc,SelfTrigger.AIVariables[1], -SelfTrigger.AIVariables[2]);
        return LOOP_END;
    };
уменьшение кол-во запусков триггера и LOOP_CONTINUE
Daedalus:
    SelfTrigger.AIVariables[0] -= 1;        // счётчик времени

    return LOOP_CONTINUE;
};

вот в принципе и всё. файлы работающего проекта в скрепке.
 

Вложения

  • 2023_12_03_Trigger_Attribute_TimeBonus.zip
    4,7 KB · Просмотры: 1
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.923
Благодарности
926
Баллы
275
Давайте сразу же в качестве примера сделаем какой просто триггер, который будем нам решать сюжетную задачу.

Лорд Андре и Гильдия воров
Итак, герой докладывает Андре о том что нашёл гильдию воров, после чего Лорд Андре даёт герою пару дней на ликвидацию гильдии. Будем прописывать запуск триггер прям из функции диалога
Daedalus:
func void DIA_Andre_DGRunning_Verrat()
{ 
      ...
  
    // запуск триггера
    var C_Trigger trigger;
    trigger = AI_StartTriggerScriptEx("Trigger_Andre_DGRunning_Verrat_loop", 1, self, null, null);
    trigger.Delay = 60000;                  // частота вызова триггера. раз в минуту.
    trigger.AIVariables[0] = Wld_GetDay();  // в триггер записываем текущий день
};

в самой функции триггера делаем простую проверку на то прошло ли уже нужное кол-во дней, после чего отключаем триггер :)
Код:
func int Trigger_Andre_DGRunning_Verrat_loop()
{
    // self это Андре
  
    if (SelfTrigger.AIVariables[0] <= (Wld_GetDay() - 2))
    {
        ...
        return LOOP_END;
    };
    return LOOP_CONTINUE;
};

вот и всё:) рабочий пример в скрепке
 

Вложения

  • Trigger_Andre_DGRunning_Verrat_loop.zip
    1,8 KB · Просмотры: 1
Сверху Снизу