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

    Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
    Удачи!
    Скрыть объявление
  2. Форум аддона "Возвращение" 2.0:
    — Обсудить игру, почитать о прохождениях и/или разрешить свои вопросы по игре вы можете в одной из тем одноименного форума. Посетить...
    — Прочитать историю изменения и/или скачать последнюю версию аддона "Возвращение", вы можете на страницах наших ресурсов. Скачать...
    Скрыть объявление

Важно Создание скриптовой зацикленной функции при помощи Trigger-Script (ZEN)

Тема в разделе "Скриптинг", создана пользователем Myxomop, 22 фев 2010.

  1. Myxomop

    Myxomop

    Регистрация:
    28 май 2005
    Сообщения:
    2.219
    Благодарности:
    1.598
    Баллы:
    355
    Пол:
    Мужской
    Решил переписать в отдельный развернутый урок, старый и частично поврежденный после переезда форума ответ.

    Создание скриптовой зацикленной функции при помощи Trigger-Script (ZEN)

    -----------------------------------

    Зачем это нужно?
    С помощью этой циклической связки скриптов игры и триггера мира (ZEN) можно в реальном времени отслеживать текущие параметры и состояния ГГ, ставить на них условия и возможные реакции, а также много чего другого.

    Принцип действия.
    После запуска игры (модификации) из скриптов игры вызывается триггер, расположенный в мире (ZEN) игры, который в свою очередь через установленный промежуток времени снова вызывает скриптовую функцию и выполняет все что в ней написано. И так по кругу, т.е. зациклено.

    -----------------------------------

    Работа в Spacer.
    Создание скриптового триггера в Spacer.

    Запускаем Spacer и грузим в него свой ZEN.

    Входим в режим обзора (F3) и летим куда-нибудь в центр мира.
    (Триггер можно разместить в ЛЮБОМ месте мира, например в небе, его все равно видно не будет.)

    Выходим из режима обзора и заходим в панель Objects, выделяем вкладку Create.

    Далее раскрываем: zCTriggerBase (abstract) -> zCTrigger и выделяем oCTriggerScript как на скриншоте ниже:

    trig1.jpg

    После этого на свободном пространстве мира жмем правой кнопкой мыши и в появившемся контекстном меню жмем на Insert[oCTriggerScript].

    trig2.jpg

    Если все получилось, панель Objects поменяет вкладку на Modify, в которой и будем настраивать наш свежесозданный Trigger-Script.

    trig3.jpg

    На данном скриншоте основные параметры обведены рамкой либо подчеркнуты, но в любом случае и остальные параметры лучше выставить также.

    Рассмотрим более детально.

    vobName: CYCLE_TRIGGER //Имя триггера.
    Должно в точности соответствовать вызываемому триггеру из скриптовой функции B_CYCLE_FUNCTION, которая будет описана ниже.

    ActivationFilter: //Фильтр срабатывания.
    Поставить все значения в TRUE, иначе не будет работать, все остальные параметры в рамке тоже по скриншоту.

    FireBehavior: //Скорость реакции
    fireDelaySec:0.1 //Время ответа триггера для вызова скриптовой функции, т.е. время цикла, в данный момент 1/10 секунды.
    sendUntrigger:TRUE

    scriptFunc:B_CYCLE_FUNCTION //Собственно, сама вызываемая зацикленная функция, в скриптах может быть только типа void

    После не забываем сохранить ZEN! :)

    -----------------------------------

    Работа со скриптами.
    Создание функции, вызываемой триггером, можно разместить где-угодно, но не после startup.d

    func void B_CYCLE_FUNCTION()
    {
    if(hero.attribute[ATR_HITPOINTS_MAX] == 0) //Проверка, загружен ли ГГ в мир игры. Если игра еще не загрузила ГГ в игру, значение максимальной жизни ГГ будет равно 0 и вызов триггера будет происходить до выполнения своих нужных функций. Это проверка необходима, т.к. если ГГ еще не загружен в игру и функция начнет полную отработку, возможен вылет из игры.
    {
    Wld_SendTrigger("CYCLE_TRIGGER"); //Вызов триггера c именем CYCLE_TRIGGER для зацикливания всей функции.
    return; //Выход из функции.
    };

    //Если ГГ уже загружен в игру, дальше идет полная отработка цикла, куда можно вставлять множество своих нужных функций...

    MyFunction1();
    MyFunction2();
    MyFunction3();

    Wld_SendTrigger("CYCLE_TRIGGER"); //Вызов триггера c именем CYCLE_TRIGGER для зацикливания всей функции.
    };

    ----

    Запуск скриптовой функции из startup.d

    func void init_world() //функция инициализации мира, срабатывает при каждой загрузке мира, в том числе из сохранения игры, где world является именем WORLD.ZEN.
    {
    B_CYCLE_FUNCTION(); //вызов описанной ранее скриптовой функции при инициализации мира.
    };

    Обновил скриншоты и немного дополнил комментарии для лучшего понимания работы цикла.
     
    Последнее редактирование модератором: 1 фев 2016
  2. Myxomop

    Myxomop

    Регистрация:
    28 май 2005
    Сообщения:
    2.219
    Благодарности:
    1.598
    Баллы:
    355
    Пол:
    Мужской
    Бонус, к вышеописанному. Возможно кому-нить пригодится.

    Собственно обычные часы :D
    Определяет внутриигровое время с точностью до минуты с возможностью вывода на экран. А кому нужно может и добавлять время.

    Принцип работы:
    Фунция часов B_GetTime вставленная в зацикленный триггер-скрипт по очереди перебирает все значения часов и минут и если находит текщее, то выводит на экран. Чем меньше время цикла триггер-скрипта, тем точнее определяют время часы. Рекомендуемые значения ответа триггера 1 секунда или меньше.

    Код:
    Глобальные переменные.
    var int time_hour; //Перебор часов.
    var int time_minutes; //Перебор минут.
    
    func void B_GetTime()
    {
    	var string concatText;
    	
    	var int t;
    	var int m;
    	
    	if(Wld_IsTime(time_hour,0,time_hour,59)) //Если текущее значение time_hour находится в пределах текущего времени игры.
    	{
    		t = time_hour; //t = текущему часу в игре.
    	};
    	if(Wld_IsTime(t,time_minutes,t,time_minutes + 2))  //Если текущее значение time_minutes находится в пределах текущего часа и между границами минут в игре.
    	{
    		m = time_minutes + 1;  //m = текущей минуте.
    	};
    	
    	time_hour += 1; //Перебор всех часов
    	time_minutes += 1;  //Перебор всех минут
    	
    	if(time_hour >= 24)
    	{
    		time_hour = 0;
    	};
    	if(time_minutes >= 60)
    	{
    		time_minutes = 0;
    	};
    	
    	//Построение индикатора вида ЧЧ:ММ
    	concatText = "";
    	if(t < 10) //Если значение часов меньше 10, например 9:00
    	{
    		concatText = ConcatStrings(concatText, "0"); //Перед цифрой часов добавляется 0 (нуль), 09:00
    	};
    	concatText = ConcatStrings(concatText, IntToString(t));
    	
    	concatText = ConcatStrings(concatText,":");
    	
    	if(m < 10) //Если значение минут меньше 10
    	{
    		concatText = ConcatStrings(concatText, "0"); //Перед цифрой минут добавляется 0 (нуль) 
    	};
    	concatText = ConcatStrings(concatText, IntToString(m));
    	PrintScreen(concatText,50,90,FONT_ScreenSmall,1);
    };
     
  3. Phantom95

    Phantom95 Участник форума

    Регистрация:
    31 июл 2014
    Сообщения:
    1.049
    Благодарности:
    390
    Баллы:
    135
    Пол:
    Мужской
    Небольшое дополнение, чтоб часы отображались в правом верхнем углу нужно прописать в функции PrintScreen числа "96" и "1" заместо "50" и "90" соответственно
     
    BlackWolf поблагодарил.
  4. Kreol Nekr

    Kreol Nekr Участник форума

    Регистрация:
    21 ноя 2014
    Сообщения:
    104
    Благодарности:
    64
    Баллы:
    70
    Пол:
    Мужской
    Обьясните пожалуйста, какой триггер и какая у него должна быть функция, чтобы он срабатывал после взятия квеста в определенное время и появлялась запись в дневнике?
    Я поставил скриптовый зацикленный триггер,и написал ему вот такую функцию:

    func void EVT_GLOBALTRIGGER_FUNC()
    {
    if((hero.attribute[ATR_HITPOINTS_MAX] == 0) && (MIS_REGADARK == LOG_Running) && Wld_IsTime(0,0,2,0))
    {
    B_LogEntry(TOPIC_REGADARK,"Я дождался ночи, но кажется все спокойно... Думаю, стоит подойти к Реге и поинтересоваться как ей спится.");
    }
    else
    {
    Wld_SendTrigger("GLOBAL_TRIGGER_1");
    return;
    };
    Wld_SendTrigger("GLOBAL_TRIGGER_1");
    };
    Но он не срабатывает ни при загрузке мира, ни при взятии квеста ни при наступлении 12 часов.
     
  5. Vlad_Torop

    Vlad_Torop Участник форума

    Регистрация:
    2 май 2014
    Сообщения:
    576
    Благодарности:
    354
    Баллы:
    120
    Пол:
    Мужской
    На вскидку:
    В условии срабатывания твоего триггера стоит hero.attribute[ATR_HITPOINTS_MAX] == 0,это значит что он сработает если ГГ не загружен в мир.Да и сам скрипт выстроен не правильно.
    И вообще,как я понимаю,этот триггер нужен тебе лишь на время действия миссии,так что в глобальной зацикленной функции нет необходимости.Проще создать обычный триггер-скрипт,и запустить его в диалоге,где берется миссия.
    А сам скрипт триггера можно переделать так:
    Открыть спойлер

    func void EVT_GLOBALTRIGGER_FUNC()
    {
    if(MIS_REGADARK == LOG_Running) && Wld_IsTime(0,0,2,0))
    {
    B_LogEntry(TOPIC_REGADARK,"Я дождался ночи, но кажется все спокойно... Думаю, стоит подойти к Реге и поинтересоваться как ей спится.");
    }
    else
    {
    Wld_SendTrigger("GLOBAL_TRIGGER_1");
    };
     
    Последнее редактирование: 20 фев 2016
    Kreol Nekr поблагодарил.
  6. Kreol Nekr

    Kreol Nekr Участник форума

    Регистрация:
    21 ноя 2014
    Сообщения:
    104
    Благодарности:
    64
    Баллы:
    70
    Пол:
    Мужской
    Ну спасибо, попробуем... Только вот не совсем понял, как его к диалогу привязать?
     
  7. Vlad_Torop

    Vlad_Torop Участник форума

    Регистрация:
    2 май 2014
    Сообщения:
    576
    Благодарности:
    354
    Баллы:
    120
    Пол:
    Мужской
    Пиши в диалоге:Wld_SendTrigger("GLOBAL_TRIGGER_1");
     
    Дикарь поблагодарил.

Поделиться этой страницей

Neverwinter