Внимание! Рисунок интерактивный, можно кликать зеленые кнопки.
Редактор диалога - прост и удобен в работе, но все же нужно знать некоторые приемы. Как и в обычном текстовом редакторе, здесь можно копировать текст, плюс целые ветки диалога. Можно также открыть несколько диалогов и составлять диалог копированием веток из открытых. Также в редакторе предусмотрены связки, т.е. линьки, они переводят диалог на ранее написанные ветки, и отображаются серым цветом. При этом показана только начальная ветка связки, но всю ветку можно просмотреть, кликнув правой кнопкой «Тест». Очень полезная фишка - это перетаскивание веток диалога. Для этого достаточно прижать ветку левой кнопкой мыши, и вставить в нужную часть диалога. Удаленные ветки отправляются в мусор, т.е. собственную корзину редактора, откуда их можно извлечь. Закрыв редактор диалога, очистится и папка мусор, помните об этом.
Для начала построения диалога, нужно знать, что диалог строится снизу вверх. Чтобы верхние ветки не открывались раньше времени, их блокируют скриптами. В нашем примере на фразу героя в первом диалоге: “Привет! Как дела!” мы ставим скрипт в строку “Совершены действия”. При создании модуля приходится часто задавать порядок ветвей диалога, поэтому я рекомендую написать несколько универсальных скриптов построения диалога. Разберем это на примере 1 диалога, скрипт имеет простой вид:
void main()
{
SetLocalInt(GetPCSpeaker(),"D1_"+GetTag(OBJECT_SELF), 1);
} |
Мы присваиваем говорящему, в нашем случае (для настолки) герою, переменную D1_ плюс тэг персонажа с которым говорим. Допустим тэг у него будет Lera_1 т.е. переменная будет иметь такой стринг: D1_ Lera_1
Переменную с таким стрингом и равной единицы, мы будем проверять у других персонажей, чтобы отследить диалог с нашим первым персонажем, скриптом:
int StartingConditional()
{
// Проверить местные переменные
if(!(GetLocalInt(GetPCSpeaker(), "D1_Lera_1") == 1))
return FALSE;
return TRUE;
} |
Поверьте, что таких скриптов у вас в модуле наберется не так много, гораздо больше будет именно обращений к нашему персонажу с тэгом Lera_1. Поэтому мы можем написать еще ряд универсальных проверок, для обращений к одну и тому же персонажу. Имея разные тэги у персонажей, вы избавите себя от выдумывания новых локалок и написания кучи скриптов. Сам скрипт:
int StartingConditional()
{
// Проверить местные переменные
if(!(GetLocalInt(GetPCSpeaker(), "D1_"+GetTag(OBJECT_SELF)) == 1))
return FALSE;
return TRUE;
} |
Как видно, мы проверяем на герое, т.е. том кто обратится GetPCSpeaker(), нашу переменную с привязкой тэга, равную единицы. Этот скрипт мы смело можем ставить на проверку т.е. строку "Текст появляется при…" второй ветки нашего диалога. При первом диалоге мы проскочим эту ветку "Диалог 2", но нам нужно еще заблокировать самую верхнею ветку. Для этого напишем еще два аналогичных скрипта на присвоение и проверку локальной переменной, но уже поставив “D2_”. Расставив все скрипты по своим местам, мы получим, что при первом диалоге, у нас останется незаблокированной только самая нижняя ветка диалога. Ведя последовательно диалог, мы будем подниматься все выше по веткам диалога.
Отследить все скрипты действия диалога, мы можем, кликнув верхнею кнопку - “Выделить Действия”. При этом вы увидите выделение ветки красным контуром (см. верхний рисунок). А вот проследить блокировки, нельзя, нет такой кнопки, но можно в графе “Комментарии” оставлять свои заметки о текущей проверке, тогда кликнув кнопку “Выделить Комментарии” у вас будут выделены все проверки…
Разберем еще две важных кнопки 1 и 2 на верхнем рисунке. Первая - “Вставить Знак”, позволяет делать вам вставки в диалог, что сделает его более интерактивным и красочным. Поставьте курсор, в поле просмотра и ввода текста, в нужную часть строки, и кликните эту кнопку. Выбран нужную авто замену слов для мужских и женских героев (М Ж), кликните “ОК”. У вас появится тэг кода авто замены, например:
Вот непруха <brother/sister>.... Неужто всех перебили?
Еще в авто замене есть коды выделения цветом, пользуясь ими помните, что после каждого выделения, нужно ставить тэг окончания выделения цветом. Он для всех цветов один - </Start> Например окрасим нашу строку наполовину в красный цвет:
Вот <StartCheck>непруха</Start> <brother/sister>.... Неужто всех перебили?
На экране монитора мы получим такой текст, если у нас герой М.
Вот непруха брат… Неужто всех перебили?
Редактор - стандартные замены
- Парень – Девушка <Boy/Girl> <boy/girl>
- Брат – Сестра <Brother/Sister> <brother/sister>
- Мужчина – Женщина <Man/Woman> <man/woman>
- День – Ночь <Day/Night> <day/night>
- Он – Она <He/She> <he/she>
- Лорд – Леди <Lord/Lady> <lord/lady>
- Мистер – Миссис <Mister/Missus> <mister/missus>
- Хозяин – Хозяйка <Master/Mistress> <master/mistress>
- Сер – Мадам <Sir/Madam> <sir/madam>
- Имя героя <FirstName>
- Полное имя героя <FullName>
- Класс героя <Class>
Стандартные замены могут начинаться, как с малой, так и с заглавной буквы, за исключением имени.
<StartCheck>(Kpacный)</Start>
<StartHighlight>(Синий)</Start>
<StartAction>(Зеленый)</Start>
Разберем для чего нужна вторая кнопка “Редактировать текст на многих языках”. Кликнув по этой кнопке, у нас выводится окно ввода текста, который можно ввести из другого редактора, например “Word”. Собственно мы уже все и разобрали, осталось только напомнить, что обратно текст из тулсета можно вывести из этого окна, предварительно сделав расклад клавиатуры в обоих редакторах – русскоязычный.
Разберем еще одну важную кнопку под номером 3 на верхнем рисунке редактора. Это ваш помощник написания несложных скриптов “Мастер скриптов”. Его работу не буду рассматривать, просто обратите внимание, что все скрипты должны быть обязательно компилированы, иначе они не будут исполняться… Более сложные скрипты для проверки нескольких предметов, и операций с большим количеством предметов, можно найти в разделе “Предметы”.
Рассмотрим панельку “Другие действия”. Здесь можно настроить анимацию при диалоге, как для героя, так и для НПС, все зависит на какой ветке будет стоять анимация, звук или запись в журнале. Кстати, анимацию звук и журнальные записи отражают и верхние кнопки редактора. При нажатие, они выделяют все ветки, на которых вы использовали данные операции. Звуковой файл можно выбрать в этой панельки из базовых, и даже прослушать, кликнув по соответствующей кнопке. А вот журнальные записи, это только ваших рук дело. Их можно выбрать из ранен написанных в редакторе журнала. Можно также открыть их прям из редактора журнала и отредактировать, или просто освежить память просмотром…
Как проставить анимацию и звуки, обычно это не вызывает проблем, не буду на этом заострять внимание, гораздо важней знать для чего служит скрипт nw_wolk_wp в панели “Текущий Файл”. Строка “Нормальный” отвечает за обычное прерывание диалога в игре, посредством клика веток диалога. А строка “Прервано” – это есть отклик на нашим клавиши “Esc”. Стандартный скрипт просто запускает функцию WolkWayPoints для НПС, чтобы он мог заняться после диалога своими текущими делами. Вы так же можете добавить в этот скрипт свои задумки, главное оставить запуск этой функции. Так же бывает необходимость наоборот убрать или блокировать запуск этой функции, например в кат сценках. Если при этом поставить галку “Прекращение увеличения”, то это даст возможность не потревожить камеру, если диалог проходит и заканчивается в режиме кат сцены.
Есть еще одна дыра в редакторе, на которую я бы хотел обратить ваше внимание. Для квестов часто приходится носить определенные предметы и делать на них реакцию НПС. Можно во многих случаях обойтись парой тройкой универсальных скриптов. Стоит помнить при построение диалога, о том, что забирать квестовый предмет нужно обязательно на ветки НПС а не героя, предварительно сделав на этой ветке еще раз проверку на предмет, т.к. в процессе диалога, у героя можно открыть инвентарь и выбросить этот предмет на землю. Вот скрипт для проверки предмета:
#include "nw_i0_tool"
int StartingConditional()
{
if(!HasItem(GetPCSpeaker(), ("Item1_"+GetTag(OBJECT_SELF))))
return FALSE;
return TRUE;
}
// Проверить наличие предмета
// Предмет имеет тег (Тэг предмета + Тэг Говорящего) |
А вот скрипт, который закроет дыру с уловкой выбрасывания предмета. Даже если герой опустит предмет на землю, то этот предмет все равно удалится:
void main()
{
object oPC = GetPCSpeaker();
object oItem = GetItemPossessedBy(oPC, "Item1_"+GetTag(OBJECT_SELF));
if(GetIsObjectValid(oItem))
DestroyObject(oItem);
else
DestroyObject(GetNearestObjectByTag("Item1_"+GetTag(OBJECT_SELF)));
}
// Удалить предметы из инвентаря игрока |
Теперь поговорим еще о написание диалогов для разных героев, т.е. мужчин и женщин. Редактор Neverwinter Nights позволят немного отразить эту тему, но не в полной мере. Бывает необходимо разделить ветки по половому признаку, нужно просто записать две ветки параллельно, заблокировав каждую скриптом:
int StartingConditional()
{
// Добавить ограничение пола: Только мужчина
if(GetGender(GetPCSpeaker()) != GENDER_MALE)
return FALSE;
return TRUE;
} |
int StartingConditional()
{
// Добавить ограничение пола: Только женщина
if(GetGender(GetPCSpeaker()) != GENDER_FEMALE)
return FALSE;
return TRUE;
} |
Это немного неудобно, когда нужно изменить всего несколько букв в слове. В этом случае вам поможет простой скрипт авто замены слов или их окончаний, который можно ставить как на проверку, так и на действие. Если у вас неактивные токены, тогда просто достаточно один раз их задать в скрипте, например, при старте модуля в слоте модульных свойств OnModulLoad.
int StartingConditional()
{
object oPC = GetFirstPC();
if (GetGender(oPC)==GENDER_MALE)
{
SetCustomToken(2001, "ел");
SetCustomToken(2002, "Господин");
SetCustomToken(2003, "");
SetCustomToken(2004, "");
}
else
{
SetCustomToken(2001, "ла");
SetCustomToken(2002, "Госпожа");
SetCustomToken(2003, "ла");
SetCustomToken(2004, "а");
}
// ========== ЦВЕТОВАЯ ЗАМЕНА =========
SetCustomToken(2030, "</c>"); // (color end TAG)
SetCustomToken(2031, "<c°°°>"); // Серый
SetCustomToken(2032, "<cууу>"); // Белый
SetCustomToken(2033, "<c уу>"); // Лозоревый
SetCustomToken(2034, "<cу у>"); // Розовый
SetCustomToken(2035, "<cуу >"); // Желтый
SetCustomToken(2036, "<c у >"); // Зеленый
SetCustomToken(2037, "<c °у>"); // Голубой
SetCustomToken(2038, "<c aю>"); // Синий
SetCustomToken(2039, "<cу !>"); // Красный
SetCustomToken(2040, "<cЫa >"); // Коричневый
SetCustomToken(2041, "<cюa >"); // Оранжевый
SetCustomToken(2042, "<cДYц>"); // Фиолетовый
SetCustomToken(2043, "<c}} >"); // Болотный
return TRUE;
} |
Как будет выглядет такая запись в редакторе диалога?
Вот непруха <CUSTOM2002>… Неужто ты всех перебил<CUSTOM2004>?
Это будет выглядить в игре для героя женщины:
Вот непруха Госпожа… Неужто ты всех перебила?
Для цветовой замены строка в редакторе:
Вот <CUSTOM2039>непруха<CUSTOM2030> <CUSTOM2002>… Неужто ты всех перебил<CUSTOM2004>?
Строка в игре:
Вот непруха Госпожа… Неужто ты всех перебила?
Цветовую замену можно делать и в скрипте. Вот пример:
AssignCommand(oPC, SpeakString("Вот <cу !>непруха</c>!..."));
Для тех, кто еще хочет добавить своих цветов.
НВН понимает теги цветов, т.е. можно кусок текста покрасить в нужный цвет. Делается это примерно так: <cКЗС>text</c>
К – величина красного цвета
З – величина зеленого цвета
С – величина синого цвета
т.е. парным тегом <c> задается область текста, которая будет окрашена в цвет КЗС. Каждый символ КЗС имеет свой код, т.е. числовое значение, которое и используется для записи параметра цвета. Величины цветов можно подобрать в палитре выбора цвета в редакторе, а величину кода в таблице символов. (см. таблицу в любом букваре) Заносим в тэг цвета нужные символы, соответствующие заданным величинам цветовой гаммы.
Нумерация символов идет от нуля по возрастающей с верхнего символа, слева на право. Первым символом, который мы можем записать будет пробел, а его величина 32. Теперь смотри наш цвет: 112; 228; 143. Ищем примерные буковки, получаем: p ф П забиваем их в тэг, получаем код: <cpфП> новый тэг, можно вставлять и будет цвет, который выбрали.
В диалоге могут участвовать несколько персонажей. Для этого служит слот “Тег говорящего” владельца диалога, или отдельной ветки… Определив тег владельца диалога, или ветки, мы можем подключить к диалогу нескольких НПС. Как это сделать? Очень просто, достаточно открыть локацию, где будет находиться нужный НПС. И, тогда в слоте, среди прочих, появится и его тег. Вам останется только выбрать нужного НПС, при этом сразу же появится и его портрет. Сохранив диалог, не пугайтесь, если в другой локации, где нет этого НПС, пропадет его портрет. Ничего в этом нет страшного, главное мы уже вбили в диалог его тег, и диалог сработает, если рядом будет этот НПС. В противном случае, диалога не будет… Нет рядом НПС – нет и диалога с этой веткой! Помните об этом, и блокируйте такие ветки диалога, другими ветками самого владельца диалога.
Хочу еще поделиться багом, с определением тега, владельца ветки диалога. Желательно на эту ветку не вешать скрипт проверки дополнительного условия! Бывает, диалог начинается, хотя условие скрипта не выполнено…Видно, движок не может одновременно пробить тег, и выполнить ваш скрипт проверки. Если по другому никак не построить диалог, то лучше самому вбить в скрипт проверку тега и проверку условия. Например:
//::///////////////////////////////////////////
//:: Проверить тег владельца диалога и локалку
//::///////////////////////////////////////////
int StartingConditional()
{
if(GetLocalInt(GetPCSpeaker(), "LOC") == 1 &&
GetTag(OBJECT_SELF)== "VAKULA")
return TRUE;
return FALSE;
} |
|