Помощь - Поиск - Пользователи - Календарь
Полная версия: Азы скриптинга NWN/NWN2
Город Мастеров > РЕДАКТОРЫ > Neverwinter Nights 2 Obsidian Toolset
Страницы: 1, 2
Aiwan
Да, все верно. Мы еще один вариант блоков рассмотрим. Подожденм остальных. declare.gif
Vhall
Что-то написал. Даже компилируется. Работает или нет - сказать не могу - не понятен нужный результат.
Для чего мы ставим и проверяем локалки? Откомментировал вопросами.
[ OFFTOP ]
Neverwinter Script Source
void main( )
{
  object oTrigger = OBJECT_SELF; // То на чем стоит скрипт
  object oDoor = GetObjectByTag( "DOOR_AIWAN_01" ); // Наша дверь
  object oNpc; // Объявим НПС но не укажем, кто он именно
  object oPC = GetEnteringObject( ); // Тот кто НАСТУПИЛ на триггер
  string sSpeak = "Кто последний тот тухлый банан!";

  if( GetIsPC( oPC ) == TRUE ) // Если это верно ТО выполняется то что между скобок
  { // ПЕРВАЯ открытая скобка

    /* ВТОРОЙ ВНУТРЕННИЙ БЛОК */

    if ( GetLocalInt( oTrigger, "AIWAN_PC_DO_IT" )== 1 ) // Если локалка РАВНА 2 ТО: //почему "2"? не 1?
    { // ВТОРАЯ открытая скобка

        oNpc = GetNearestObjectByTag( "NPC_AIWAN" );
        SetLocalInt( oTrigger, "AIWAN_PC_DO_IT", 2 );
        SendMessageToPC( oPC, "Сработал второй блок" );

    } // ВТОРАЯ закрытая скобка

    /* ТРЕТИЙ ВНУТРЕННИЙ БЛОК */

    if ( GetLocalInt( oTrigger, "AIWAN_PC_DO_IT" ) == 0 )
    { // ТРЕТЬЯ открытая

        oNpc = GetNearestObjectByTag( "NPC_AIWAN" );
        SetLocalInt( oTrigger, "AIWAN_PC_DO_IT", 1 );
        SendMessageToPC( oPC, "Сработал третий блок" );
    }  // ТРЕТЬЯ закрытая

    /* четвертый внутренний блок */
   
    if ( GetLocalInt( oTrigger, "AIWAN_PC_DO_IT" ) == 0 ) //?
    { // четвертая открытая

        oNpc = GetNearestObjectByTag( "NPC_AIWAN" );
        SetLocalInt( oTrigger, "AIWAN_PC_DO_IT", 3 ); //?
        SendMessageToPC( oPC, "Сработал четвертый блок" );
    }  // четвертая закрытая

      SendMessageToPC( oPC, "Сработал ОСНОВНОЙ блок" );
      AssignCommand( oNpc, ClearAllActions( ) ); // Чистим стек команд
      AssignCommand( oNpc, SpeakString( sSpeak ) ); // Говорит фразу
      AssignCommand( oNpc, ActionForceMoveToObject( oDoor, TRUE ) ); // Бежит к двери

  } // ПЕРВАЯ закрытая скобка

}
Aiwan
Vhall, мы присваиваем локалки что бы блоки сработали ОДИН раз за проход скрипта сверху вниз. Посомтри внимательно.

В первом внутреннем блоке мы проверяем переменную AIWAN_PC_DO_IT равную 1. Внутри блока мы поставили эту локальную со значением 2. Тем самым мы сделали так, что бы второй раз наступив на триггер скрипт не сработал внутри этого блока.

Neverwinter Script Source

    /* ВТОРОЙ ВНУТРЕННИЙ БЛОК */

    if ( GetLocalInt( oTrigger, "AIWAN_PC_DO_IT" )== 1 ) // СРАБОТАЕТ ВО ВТОРОЙ РАЗ
    {

      // Ставим значение 2. Второй раз скрипт этот блок не запустит. Тут проверка на 1
        SetLocalInt( oTrigger, "AIWAN_PC_DO_IT", 2 );
    }

    /* ТРЕТИЙ ВНУТРЕННИЙ БЛОК */

    if ( GetLocalInt( oTrigger, "AIWAN_PC_DO_IT" ) == 0 ) // ОН СРАБОТАЕТ В ПЕРВЫЙ РАЗ
    {
        // Этот блок сработает САМЫЙ первый, так как проверка переменной на ноль
        // Мы присвоим значение 1. Так как блок с проверкой на 1 вверху выше, то
        // скрипт не будет ее запускать в этот раз. Мы верх уже прошли и пошлди ниже.
        SetLocalInt( oTrigger, "AIWAN_PC_DO_IT", 1 );
    }

    /* ТУТ НУЖНО ДОПИСАТЬ ЕЩЕ ОДИН БЛОК*/

    if ( GetLocalInt( oTrigger, "AIWAN_PC_DO_IT" ) == 2 ) // СРАБОТАЕТ ВО ВТОРОЙ РАЗ
    {
    // Смотрим здесь. Проверка идет на значение 2. Т.е. он попросту ОБНУЛЯЕТ наши
    // переменные для замкнутого круга.
        SetLocalInt( oTrigger, "AIWAN_PC_DO_IT", 0 );
        SendMessageToPC( oPC, "Сработал четвертый блок" );
    }


Ты предсталяешь наверное такой расклад:

Neverwinter Script Source

    if ( GetLocalInt( oTrigger, "AIWAN_PC_DO_IT" ) == 0 )
    {
        SetLocalInt( oTrigger, "AIWAN_PC_DO_IT", 1 );
    }

    if ( GetLocalInt( oTrigger, "AIWAN_PC_DO_IT" )== 1 )
    {

        SetLocalInt( oTrigger, "AIWAN_PC_DO_IT", 2 );
    }

    if ( GetLocalInt( oTrigger, "AIWAN_PC_DO_IT" ) == 2 )
    {
        SetLocalInt( oTrigger, "AIWAN_PC_DO_IT", 0 );
    }


Но он не верен, так как в скрипте ЗА ОДИН раз сработают все три блока а нам надо что бы каждый работал один раз за проход. Мы сделали так:

Neverwinter Script Source

    if ( GetLocalInt( oTrigger, "AIWAN_PC_DO_IT" )== 1 )
    {

        SetLocalInt( oTrigger, "AIWAN_PC_DO_IT", 2 );
    }
    if ( GetLocalInt( oTrigger, "AIWAN_PC_DO_IT" ) == 0 )
    {
        SetLocalInt( oTrigger, "AIWAN_PC_DO_IT", 1 );
    }

    if ( GetLocalInt( oTrigger, "AIWAN_PC_DO_IT" ) == 2 )
    {
        SetLocalInt( oTrigger, "AIWAN_PC_DO_IT", 0 );
    }

Соотвественно у нас работает первый раз средний блок. Второй раз верхний и нижний следом за ним ОБНУЛЯЯ локалку. В третий раз сработает средний и так далее. Понятно?

Добавлено через 50

п.с. В комменте я ошибся там проверка на 1 а я написал 2. Вот ты мог и запутаться. Извини.
Vhall
scratch_one-s_head.gif Вот так?
[ OFFTOP ]
Neverwinter Script Source
void main( )
{
  object oTrigger = OBJECT_SELF; // То на чем стоит скрипт
  object oDoor = GetObjectByTag( "PLC_DC_Slum01" ); // Наша дверь
  object oNpc; // Объявим НПС но не укажем, кто он именно
  object oPC = GetEnteringObject( ); // Тот кто НАСТУПИЛ на триггер
  string sSpeak = "Кто последний тот тухлый банан!";

  if( GetIsPC( oPC ) == TRUE ) // Если это верно ТО выполняется то что между скобок
  { // ПЕРВАЯ открытая скобка

    /* ВТОРОЙ ВНУТРЕННИЙ БЛОК */

    if ( GetLocalInt( oTrigger, "VHALL_PC_DO_IT" )== 1 ) // Если локалка РАВНА 2 ТО:
    { // ВТОРАЯ открытая скобка

        oNpc = GetNearestObjectByTag( "n_watchman" );
        SetLocalInt( oTrigger, "VHALL_PC_DO_IT", 2 );
        SendMessageToPC( oPC, "Сработал второй блок" );

    } // ВТОРАЯ закрытая скобка

    /* ТРЕТИЙ ВНУТРЕННИЙ БЛОК */

    if ( GetLocalInt( oTrigger, "VHALL_PC_DO_IT" ) == 0 )
    { // ТРЕТЬЯ открытая

        oNpc = GetNearestObjectByTag( "n_watchman" );
        SetLocalInt( oTrigger, "VHALL_PC_DO_IT", 1 );
        SendMessageToPC( oPC, "Сработал третий блок" );
    }  // ТРЕТЬЯ закрытая

    /* четвертый внутренний блок */
   
    if ( GetLocalInt( oTrigger, "VHALL_PC_DO_IT" ) == 2 )
    { // четвертая открытая

        oNpc = GetNearestObjectByTag( "n_watchman" );
        SetLocalInt( oTrigger, "VHALL_PC_DO_IT", 3 );
        SendMessageToPC( oPC, "Сработал четвертый блок" );
    }  // четвертая закрытая

      SendMessageToPC( oPC, "Сработал ОСНОВНОЙ блок" );
      AssignCommand( oNpc, ClearAllActions( ) ); // Чистим стек команд
      AssignCommand( oNpc, SpeakString( sSpeak ) ); // Говорит фразу
      AssignCommand( oNpc, ActionForceMoveToObject( oDoor, TRUE ) ); // Бежит к двери

  } // ПЕРВАЯ закрытая скобка

}
Aiwan
Нет не верно. Если ты хочешь сделать так, то тебе твой последний блок что ты нарисовал надо поместить в самый верх. Зачем понятно или нет? Посомтри внимательно. У нас первый блок проверяет 1, второй 0, третий 2. Скрипт идет сверху вниз. Единица у нас проверяется вверху, так как в блоке на проверку 0 мы присвоили 1. Если бы блок с проверкой на 1 стоял после блока проверки на ноль, то сразу бы сработал следом за блоком проверки на 0. Что в сущности происходит и у тебя. Первый блок проверка на 1 (увеличили до 2), следом проверка на 0, скрипт его пропустит но опятть зайдет в блок проверки на 2 и там снова твои данные. Он выполнит их и присвоится 3. Так что если ты хочешь все три блока выполнить, то должен учитывать условие: ЕСЛИ СРАБОТАЛ БЛОК, ТО НИЖНИЕ БЛОКИ НЕ ДОЛЖНЫ СРАБОТАТЬ ПОСЛЕ ЕГО УСЛОВИЙ ЕСЛИ ТЕБЕ ЭТО НЕ НАДО.

В общем тебе сложно это? Если да не заморачивайся. Я немного сложновато дал для новичков. Поймешь потом.
Vhall
Да, может давай это... дальше?
Artlira
У меня вопрос. А занятия дальше будут? Очень хочется учиться... unsure.gif
Aiwan
Будут!
Aiwan
Продолжаем.

Создайте диалог в редакторе с четырмя корневыми строками:
1. Эта строка первого НПС.
2. Это строка второго НПС.
3. Это строка третьего НПС.
4. Я безымянный!

Теперь у вас три НПС было, создайте еще пару. Вставьте диалог один на всех ваших НПС.
Трем первым НПС измените теги на такие: NPC_ВАШ_НИК_01, NPC_ВАШ_НИК_02, NPC_ВАШ_НИК_03.
Создайте три скрипта в редакторе где бы проверялся ТЕГ НПС который разговаривает. Три разных НПС три разных скрипта. Пример первого:
Neverwinter Script Source

int StartingConditional( )
{
  object oSelf = OBJECT_SELF; // Тот с кем начали разговор на ком стоит скрипт

  if ( GetTag( oSelf ) == "NPC_ВАШ_НИК_01" ) // Если тег объекта РАВЕН
  {
      return TRUE; // То начало диалога этой строкой
  }
  return FALSE; // Ничего не произойдет, строка не появится
}

У вас получится три скрипта на три строки. Теперь расставив ваших НПС и поговорив с ними вы получите три разных ответа и четвертый ответ самый последний общий для всех. Так можно определить какого-то одного уникального НПС даже используя один шаблон диалогов на всех.



Добавлено через 2 минуты

Прятать ответы не надо. Пишите получилось у вас или нет.
Artlira
Все получилось. Каждый из заданных неписей произносит строку в зависимости от своего тега.
1. Эта строка первого НПС.
Neverwinter Script Source
int StartingConditional( )
{
  object oSelf = OBJECT_SELF; // Тот с кем начали разговор на ком стоит скрипт

  if ( GetTag( oSelf ) == "NPC_LIRA_01" ) // Если тег объекта РАВЕН NPC_LIRA_01
  {
      return TRUE; // То начало диалога этой строкой
  }
  return FALSE;
}

2. Это строка второго НПС.
Neverwinter Script Source
int StartingConditional( )
{
  object oSelf = OBJECT_SELF; // Тот с кем начали разговор на ком стоит скрипт

  if ( GetTag( oSelf ) == "NPC_LIRA_02" ) // Если тег объекта РАВЕН NPC_LIRA_02
  {
      return TRUE; // То начало диалога этой строкой
  }
  return FALSE;
}

3. Это строка третьего НПС.
Neverwinter Script Source
int StartingConditional( )
{
  object oSelf = OBJECT_SELF; // Тот с кем начали разговор на ком стоит скрипт

  if ( GetTag( oSelf ) == "NPC_LIRA_03" ) // Если тег объекта РАВЕН NPC_LIRA_03
  {
      return TRUE; // То начало диалога этой строкой
  }
  return FALSE;
}

Aiwan
Отлчино! Ждем еще кого нить...
Vhall
У меня все работает. Сомневаюсь что нужно писать ответ - ведь он почти полностью идентичен.
Всё понятно.
Aiwan
Очень радует, что вам все понятно. Продолжаем.

Мы уже разбирали что такое пременная. Теперь мы применим знания в главном составляющем грамотного мода - диалоге.

Переменная проверяется в начале корневой строки так (эта строка появится ТОЛЬКО когда переменная равна 0):
Neverwinter Script Source

//:://////////////////////////////////////////////
//:: Проверим отсутсвие переменной AIWAN_LESSON_01_DIALOG
//:: Copyright © 2007 WRG!
//:://////////////////////////////////////////////
/*
        Описание самого квеста, если нужно.
*/
//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 10.12.2007
//:://////////////////////////////////////////////
int StartingConditional( )
{
    object oPC = GetPCSpeaker( );
    int iQuest = GetLocalInt( oPC, "AIWAN_LESSON_01_DIALOG" );
//-------------------------------------------------------
    if ( iQuest == 0 ) // Если локалка равна 0.
    {
        return TRUE; // Возврат ИСТИНА, т.е. старт диалога
    }
    return FALSE; // В противном случае отбой
}


Эта строка диалога появится ТОЛЬКО когда переменная ровна 1:

Neverwinter Script Source

//:://////////////////////////////////////////////
//:: Проверим переменную AIWAN_LESSON_01_DIALOG на 1
//:: Copyright © 2007 WRG!
//:://////////////////////////////////////////////
/*
        Описание самого квеста, если нужно.
*/
//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 10.12.2007
//:://////////////////////////////////////////////
int StartingConditional( )
{
    object oPC = GetPCSpeaker( );
    int iQuest = GetLocalInt( oPC, "AIWAN_LESSON_01_DIALOG" );
//-------------------------------------------------------
    if ( iQuest == 1 ) // Если локалка равна еденице.
    {
        return TRUE; // Возврат ИСТИНА, т.е. старт диалога
    }
    return FALSE; // В противном случае отбой
}


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

Neverwinter Script Source

//:://////////////////////////////////////////////
//:: Присвоим переменную AIWAN_LESSON_01_DIALOG 1
//:: Copyright © 2007 WRG!
//:://////////////////////////////////////////////
/*
        Описание самого квеста, если нужно.
*/
//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 10.12.2007
//:://////////////////////////////////////////////
void main( )
{
    object oPC = GetPCSpeaker( );
//  object oPC = GetFirstPC( ); - так будет работать на любом месте для сингла
    SetLocalInt( oPC, "AIWAN_LESSON_01_DIALOG", 1 );
}


Все это скрипты для чайников. Коими мы с вами и являемя. Но я попробую вам дать один скрипт универсальный, что бы вы поняли, что мы с вами используем 1% потенциала кода. Например, что бы не писать 5 скриптов для 5 строк в которых существующая переменная увеличивается на 1, можно написать такой скрипт на все строки присвоения:
Neverwinter Script Source

//:://////////////////////////////////////////////
//:: Присвоим переменную универсально
//:: Copyright © 2007 WRG!
//:://////////////////////////////////////////////
/*
        Описание самого квеста, если нужно.
*/
//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 10.12.2007
//:://////////////////////////////////////////////
void main( )
{
    object oPC = GetPCSpeaker( );
//  object oPC = GetFirstPC( ); - так будет работать на любом месте для сингла

    int i = GetLocalInt( oPC, "AIWAN_LESSON_01_DIALOG" );
    // Проверим текущее состояние переменной

    // и прибавим к полученному результату единичку.
    SetLocalInt( oPC, "AIWAN_LESSON_01_DIALOG", i+1 );
}


Нескаторые ремарки. Вы заметили, что некоторые скрипты не содержат скобо {}. Я изначально пишу их везде что бы вы не путались и понимали блоки. НО. Если код скрипта содержит одну строку, то условие в блоки ставить не нужно. Пример:
Этот код
Neverwinter Script Source

int StartingConditional( )
{
    object oPC = GetPCSpeaker( );
    int iQuest = GetLocalInt( oPC, "ПЕРЕМЕННАЯ ОДЫН" );
//-------------------------------------------------------
    if ( iQuest == 1 ) // Если локалка равна еденице.
    {
        return TRUE; // Возврат ИСТИНА, т.е. старт диалога
    }
    return FALSE; // В противном случае отбой
}


РАВЕН этому:

Neverwinter Script Source

int StartingConditional( )
{
    object oPC = GetPCSpeaker( );
    int iQuest = GetLocalInt( oPC, "ПЕРЕМЕННАЯ ОДЫН" );
//-------------------------------------------------------
    if ( iQuest == 1 ) // Если локалка равна еденице.

        return TRUE; // Возврат ИСТИНА, т.е. старт диалога

    return FALSE; // В противном случае отбой
}

Так как после условия у нас одна строка для кода.

Теперь домашнее задание.

В аттаче что я прикрепил есть модуль с диалогом. Ваша задача выполнить то, что я недоделал двумя способами. Первый, по "крестьянски" второй используя универсальный скрипт. Задача. Все пять строк должны появиться. После выбора в диалоге "Увеличить или прировнять" переменную к числу, мы не должны получть строку ошибку. Задача простая, но на внимательность. жду ваших сообщений. У кого что не получилось.




Добавлено через 42 секунды

Да. Естественно локалку переименовать с вашим ником.
Artlira
У меня к сожалению не открывается модуль... Поэтому задание делаю по интуиции и возможно неправильно... unsure.gif

Сделала два одинаковых диалога на пять строк, то есть на четыре переменные и ее отсутствие (0).
1. Привет! Переменная 4.
Увеличить переменную на 1.
Все больше переменных нет...
Обнулить переменную.
Привет! Переменная 0.
Ошибка! Нет ни одной переменной!

Уйти
2. Привет! Переменная 3.
Увеличить переменную на 1.
Привет! Переменная 4.
Ошибка! Нет ни одной переменной!

Уйти
Дальше тоже самое до Привет! Переменная 0. Ветки связаны, так что можно за один раз прокрутить до 4 переменной, обнулить ее и крутить снова. Ветку про ошибку добавила для того, что бы если переменная присвоена неверно, ветка с ее проверкой не появится и появится эта про ошибку.
На каждой ветке стоит проверка в зависимости от переменной, уаказанной в диалоге.
Скрипты на проверку:
Neverwinter Script Source
int StartingConditional( )
{
    object oPC = GetPCSpeaker( );
    int iQuest = GetLocalInt( oPC, "LIRA_01_DIALOG" );

    if ( iQuest == 0 ) // Если локалка равна 0.

    return TRUE; // Возврат ИСТИНА, т.е. старт диалога

    return FALSE; // В противном случае отбой
}


Меняется только строчка - чему равна переменная 0-4.

На ветках увеличить переменную на один в первом диалоге, каждый раз писала новый скрипт на присвоение переменной:

Neverwinter Script Source
void main( )
{
    object oPC = GetPCSpeaker( );
    SetLocalInt( oPC, "LIRA_01_DIALOG", 1 );
}

Менялось только значение переменной от 0 до 4.
Во втором диалоге переменная менялась универсальным скриптом:
Neverwinter Script Source
void main( )
{
    object oPC = GetPCSpeaker( );

    int i = GetLocalInt( oPC, "LIRA_01_DIALOG" );

    // и прибавим к полученному результату единичку.
    SetLocalInt( oPC, "LIRA_01_DIALOG", i+1 );
}

Оба диалога нормально прокручиваются, при выходе и повторном диалоге, срабатывает ветка именно с той переменной на которой прервали диалог.
Вроде все получилось, но я не уверена, что задание сделано верно…


Aiwan
Пришли мне на мыло свой модуль-домашнее задание. aiwan[злая собака]wrg.ru
Artlira
Цитата
Пришли мне на мыло свой модуль-домашнее задание. aiwan[злая собака]wrg.ru


Отправила.
Aiwan
Что то нет... Пришли на ящик aiwan[собака]ya.ru
Artlira
На второй адрес вроде ушло без комментариев, а на wrg.ru - дважды сообщил, что такого адреса нет...
Aiwan
Блин, у нас после переезда со старого сервера не работали мыльники smile.gif Все починил теперь на wrg шли.

Так. Ничего не правильно smile.gif Во первых. Я УЖЕ ДАЛ ШАБЛОН. В него внесите изменения. Там уже тело диалога есть. Только расставьте скрипты. и шлите мне на мыло но модуль именуйте вашим ником, что бы я не путался. Все. Жду.

п.с. Чуть позже я понял, что ты мне прислала ПЕРВОЕ задание с тремя НПС. Это другое. Возможно ошиблась?
Artlira
Цитата
Так. Ничего не правильно Во первых. Я УЖЕ ДАЛ ШАБЛОН. В него внесите изменения. Там уже тело диалога есть. Только расставьте скрипты. и шлите мне на мыло но модуль именуйте вашим ником, что бы я не путался. Все. Жду.


Так я же и пишу – что у меня шаблон не открылся… unsure.gif Поэтому я не могу просто вставить скрипты… Я не знаю как выглядит учебный диалог, вот и набросала свой, предположив, что смысл задания это правильно присвоить переменные, что бы фразы с проверками выскакивали в определенном порядке? Как я поняла, наверно в одном диалоге присвоить нужно каждую локалку отдельно, а во втором использовать только универсальную?

Цитата
п.с. Чуть позже я понял, что ты мне прислала ПЕРВОЕ задание с тремя НПС. Это другое. Возможно ошиблась?


Нет, посмотрела, там именно два диалога с обычными и универсальной переменной. А в случае с тремя неписями проверка зависела от тэга каждого непися.
Aiwan
Artlira, я только что скачал файлик что прикрепил, открыл его. Все открылось. Ты наверное просто не поняла что файл заархивирован зипом... Модуль внутри Aiwan Test MOD.mod. Открой, разархивируй, переименуй со своим ником Artlira Test MOD.mod, и сделай как говорю. Тот модуль что ты прислала содержал ОДИН диалог первого задания про три НПС. Жду.
Artlira
Aiwan я наверно объяснила неправильно... Сам мод я достаю, у меня он в тулсете не открывается. Видимо версия не та. Поэтому я и не знаю, как выглядит шаблон.

А по отправленному модулю вообще ничего не понимаю... Там два диалога (совершенно одинаковые), только локалку я в первом присваиваю каждый раз отдельно, а во втором используя одну универсальную... Там 2 непися и у них даже имена (диалог с обычной переменной, и диалог с универсальной переменной). Скачала у себя из ящика то что отправила - нет там диалога 3-ех неписей, а только вот эти два...
Aiwan
Версия 1.68. Давай качай и делай. У меня планы на эти диалоги дальше.
Vhall
Выслал.
Artlira
Отправила.
Aiwan
Теперь мы разберем простые примеры Токенов в диалогах. К примеру мы можем в строке диалога вывести любую интересующую нас фразу, слово которое зададим параметарми скрипта найти или определить. Мы с вами писали шесть строк диалога и кучу скриптов. Я написал вам шаблон который делает все это в двух строках и трех скриптах. Не суть, что вы воспользуетесь этим когда-либо, но навыки вам нужны для того что бы понять, что так можно делать.

Вот такая функция определяет кастомный токен.
Neverwinter Script Source

SetCustomToken( 100, "Строка для токена" );


В диалоге это вставляется так: <CUSTOM100> и вместо этого тега будет ваша нужная информация. Зачем это? пример. В диалогах есть теги для имени РС, да это мы можем найти. А вот имени НПС нет... Соотвественно задав одним из токенов имя НПС мы можем им пользоваться в диалогах. Но вы должны помнить, что токены не сохраняются ни в какой памяти и что бы они работали их надо загружать перед использованием.

Я приаттачил вам модуль, в нем два новых НПС. Один как заготовка, второй мой рабочий. Вы должны изменить ГОТОВЫЕ скрипты что бы ваш диалог работал как мой. Что бы у вас не было соблазна загляуть в мои скрипты исходники я вырезал и положил отдельно в папке. Вам надо всего то поправить три скрипта. В каждом добавляется коротенькая строка. Зато вы увидите как можно делать то что выглядело у нас чутким нагромождением диалоговых строк. Да, не забудьте посомтреть на журнал. Я сделал наподобие простого квеста. Но этот квест сделан полностью по схеме тулсета, без применения скриптовой части. Потом мы попробуем это же самое отскриптить. Но это позже. Так. Качайте, переименовывайте модули, локальные переменные и правьте диалог так, что бы он работал как у НПС "Образец". Что непонятно спрашивайте.

Нажмите для просмотра прикрепленного файла
Artlira
Вроде бы все получилось. По крайней мере оно работает… yahoo.gif
Рабочая строка непися должна появляться при условии, что переменная меньше или равна 5.
Строка + появляется при условии, что переменная равна 5.
Рабочая строка игрока наоборот появляется только при условии, что переменная меньше 5.
А в универсальном скрипте, необходимо было прописать условие, что если переменная меньше 5, то к ней прибавляется 1, при других условиях присваиваем переменную равную 0?

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

Модуль отправила.
Lex
достаточно в скрипте прописывать значение того токена, который будет отображен ЕСЛИ текущее значение токена не подходит. Все переприсваивать нет нужды.
Те например дали игроку кличку, записали мы ее в токен с номером 50000 и можем юзать дальше во всех диалогах до посинения, не трогая значения токена больше нигде.
Aiwan
Artlira, я получил твое письмо и написал ответ. Занятия я продолжу. Напиши мне в приват на что сделат ьупор. Не пойму, что то наши е-майлы не проходят видно друг к другу. Если ты осталась одна, я все равно продолжу.
Aiwan
Продолжаем разговор.

Так. В данном файле лежит модуль в котором есть один полный квест про книгу. Задача игрока принести книгу заказчику. На что я хочу обратить внимание. Я попытался сделать несколько свободных моментов в квесте, а именно. Можно принести книгу и еще не говорить с хозяйкой. Можно отказаться нести книгу но найдя отдать. Можно имея книгуна руках не отдать хозяйке прямо сказав ей об этом. Вот в сущности простой квест но он имеет много ньюансов. Я не думаю, что вы сможете сразу написать такой. Я хочу что бы вы попробовали все варианты диалога. И проследили что и как работает. Например. Если отказаться от задания и получить статус квеста с локалкой 1, то имея все же книгу на руках у нас шанс отдать ее и выполнить квест появляется.

Neverwinter Script
//:://////////////////////////////////////////////
//:: Проверим взяли мы квест или нет
//:: Copyright © 2007 WRG!
//:://////////////////////////////////////////////
/*
     Вернуть книгу девушке
*/

//:://////////////////////////////////////////////
//:: Created By: Aiwan
//:: Created On: 10.12.2007
//:://////////////////////////////////////////////
#include "nw_i0_tool"

int StartingConditional( )
{
    object oPC = GetPCSpeaker( );
    int iQuest = GetLocalInt( oPC, "QUEST_BOOK" );

/* Суть этой проверки, мы могли отказаться от квеста, но потом случайно нашли
  книгу и теперь в принципе можно квест вернуть назад на точку финала. */

//-------------------------------------------------------

// Если локалка равна 1 И в сумке нет книги.
    if ( iQuest == 1 && !HasItem( oPC, "AM_IT_BOOK001" ) )
    {
        return TRUE; // Возврат ИСТИНА, т.е. старт диалога
    }
    return FALSE; // В противном случае отбой
}


Я воспользовался инклюдой биовар на проверку предмета в рюкзаке !HasItem(oPC, "AM_IT_BOOK001"). Восклицательный знак впереди говорит о том что это отрицание, т.е. НЕТ книги в рюкзаке. Вот во втором случае книга уже есть при проверке. Тут можно дать шанс игроку вернуть:
Neverwinter Script
#include "nw_i0_tool"

int StartingConditional( )
{
    object oPC = GetPCSpeaker( );
    int iQuest = GetLocalInt( oPC, "QUEST_BOOK" );

/* Суть этой проверки, мы могли отказаться от квеста, но потом случайно нашли
  книгу и теперь в принципе можно квест вернуть назад на точку финала. */

//-------------------------------------------------------

// Если локалка равна 1 И в сумке книга.
    if ( iQuest == 1 && HasItem( oPC, "AM_IT_BOOK001" ) )
    {
        return TRUE; // Возврат ИСТИНА, т.е. старт диалога
    }
    return FALSE; // В противном случае отбой
}


Обратити внимание на структуру названия скриптов. Вы можете придумать свою, но рекомендую определиться с этим ло начала работ. Например: am_sc_q01_01 АйванМодуль_StartingConditional_Quest01_переменная01. Вот примерная расстановка.

Еще. Я не использовал журнальные записи в диалогах опционально. Я все присваивал в скриптах. Почему? Дело в том, что если квесту присвоить финальную ветку, то с помощью диалога он уже не вернется на статус не выполненых. Поэтому мы можем процесс держат ьпод контролем. Сработал скрипт, сработал журнал.

В квесте, я сделал одну запись в журнале, когда мы берем книгу в свой рюкзак. Вот такой скрипт am_mod_acquired на свойствах модуля для взятия предмета в инвентарь:
Neverwinter Script
#include "nw_i0_generic"
#include "x2_inc_switches"

void main( )
{
  object oMod = GetModule( ); // Это мы определили модуль
  object oItem = GetModuleItemAcquired( ); // Сам Item объект который попал в рюкзак
  object oPC = GetModuleItemAcquiredBy( ); // Тот кто взял
  string sTagItem = GetTag( oItem ); // Таг Item-a

  if( !GetIsPC( oPC ) ) return; // Если тот кто поднял предмет не РС то возврат.

  // Для теста. Все предметы что попали в сумку опознаем атоматически.
  if( !GetIdentified( oItem ) )
  {
    SetIdentified( oItem, TRUE ); // Если предмет неопределен мы его определяем
    SendMessageToPC( oPC, ( GetName( oItem )+" - неизвестный предмет опознан." ) );
  }

//==================================================
//                               ЖУРНАЛЬНЫЕ ЗАПИСИ
//==================================================

    // -------------------------------------------------------------------------
    //                      КНИГА
    // -------------------------------------------------------------------------
    if ( sTagItem =="AM_IT_BOOK001" ) // Искомый предмет
    {
      // Если на модуле нет локалки равной тегу нашего предмета sTagItem ( см выше как он определяется )
      if( !GetLocalInt( oMod, sTagItem ) ) // Если нет на модуле то..
      {
         // Сразу присвоим модулю, что мы подняли один раз предмет
         SetLocalInt( oMod, sTagItem, TRUE );

/*
   Пометим в журнале у игрока, что мы нашли предмет. Но. Если на нашем игроке нет
   ни одной переменной  QUEST_BOOK. значит он нашел книгу случайно. Значит в журнале
   мы присвоим другую запись, о том что у нас какая то странная книга, хрен знает чья.

*/

         if( !GetLocalInt( oPC, "QUEST_BOOK" ) ) // если нет локалки то
         {
             // Добавим запись в журнал тег квеста J_QUEST_BOOK 3 - номер записи
             AddJournalQuestEntry( "J_QUEST_BOOK", 3, oPC );
         }
          else // else - ЕЩЕ выполянется если условие перед скобкой не сработало
              {
                AddJournalQuestEntry( "J_QUEST_BOOK", 4, oPC );
              }
      }
    }


//==================================================
//     СТАНДАРТНАЯ СИСТЕМА item tag - ЗАПУСК СКРИПТА равного item tag
//==================================================

     // * object oItem = GetModuleItemAcquired( );
     // * Generic Item Script Execution Code
     // * If MODULE_SWITCH_EXECUTE_TAGBASED_SCRIPTS is set to TRUE on the module,
     // * it will execute a script that has the same name as the item's tag
     // * inside this script you can manage scripts for all events by checking against
     // * GetUserDefinedItemEventNumber( ). See x2_it_example.nss
     if ( GetModuleSwitchValue( MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS ) == TRUE )
     {
        SetUserDefinedItemEventNumber( X2_ITEM_EVENT_ACQUIRE );
        int nRet =   ExecuteScriptAndReturnInt( GetUserDefinedItemEventScriptName( oItem ), OBJECT_SELF );
        if ( nRet == X2_EXECUTE_SCRIPT_END )
        {
           return;
        }

     }
}


Он присваивает две разные записи в журнал, в зависимости от того, общались мы с девушкой или нет. Я написал скртипт в нутри главноого, но НВН позволяет делать так. Создать скрипт с именем предмета, в нашем случае am_it_book001 и в него уже вписать все действия. Но мне удобнее когда все под рукой. Как вам удобнее решать самим.

Задачи: вам надо изучить все мои скрипты. Внимательно простмотреть все ветки диалогов и написать простой квест. У вас есть 2 НПС, один НПС просит игрока отдать другому НПС кольцо. Диалоги обоих НПС должны быть автономны. Все прописать в журнале, на поднятие предмета тоже.
Artlira
Вроде все получилось, хотя есть пара вопросов. Вопрос первый наверно нужно было сначала задать, а потом уже делать квест. scratch_one-s_head.gif
1. Действия должны быть следующими: 1 непись отправляет на поиски кольца (раз его нужно поднять с земли), после того как ему кольцо принесли – не забирает, а просит передать другому неписю? Ну и + все варианты? Я так сделала…
2. Обязательно ли нужно вешать на строку диалога локалку о том, что квест еще не брали, с неписем не видились? Если эту ветку кинуть в самый низ и оставить без проверок, она и должна бы 1 сработать?
3. На какой адрес отправлять задание?
Aiwan
Выкладывай тут. Пусть народ читает. будем поправлять если, что.

Если не можешь пришли на aiwan[злая собака]wrg.ru
Artlira
Aiwan вроде все отправила несколько дней назад. Может опять, не прошло где-то письмо? На какой еще адрес можно отправить?
Aiwan
Почта работает. Не пойму, почему от тебя не приходят письма. Дай мне свой е-майл я отправлю с него тебе а ты ответишь.
2_advanced
злостный оффтоп:
в нвн2 если чар находится вне локи (грузит еще, только что зашел на шард),
то действия через AssignCommand вешать на него нет смысла ph34r.gif

фикс:
Neverwinter Script
void Delayed_OnEnter(object oPC)
{
    if(!GetIsObjectValid(oPC))
        return;

    if(!GetIsObjectValid(GetArea(oPC)))
    {
        DelayCommand(0.4, Delayed_OnEnter(oPC));
        return;
    }

    AssignCommand(oPC, JumpToLocation(...));
}


в нвн1 такого не было..
Merkuta
Я понимаю, что просьба довольно наглая, учитывая сколько времени прошло, но нельзя ли возобновить уроки? Я прочитал всю тему, разобрал примеры, выполнил задания. Хочется двигаться дальше, но английским к сожалению владею не достаточно, чтобы учиться на других сайтах.
Aiwan
Merkuta, боюсь, что английский придется учить в любом случае. Уроки возобновлять уже не будем.
virusman
Merkuta, перейди к реальным задачам, а если возникнут вопросы - задавай их на этом форуме. smile.gif
Merkuta
Такой вопрос. Можно ли сделать несколько глобальных карт (не интерактивных как в SoZ, а рисованных как в оригинале и Маске). Например нужно сделать карту мира, на которой город обозначен как одна локация, но при переходе в город открывается карта города, и можно выбрать район, куда пойти.
Kcapra
Merkuta, можно сделать кастомный UI
Orochi
Ну тут Merkuta немного про другое говорит. Как я понял, это по типу карты из Dragon age 2. Тут, я думаю, вполне можно сделать вторуб карту ( с городом), а в основной при нажатии на иконку повесить скрипт на переход к карте города. scratch_one-s_head.gif
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.
Invision Power Board © 2001-2025 Invision Power Services, Inc.