Город Мастеров
IPB

Здравствуйте, гость ( Вход | Регистрация )

 Правила этого форума ПРАВИЛА РАЗДЕЛА
 
Тема закрытаОткрыть новую тему
> Журналы, динамические диалоги и журналы, лигбез
_kaa_
сообщение Oct 1 2005, 19:10
Сообщение #1


Level 9
Иконки Групп

Класс: Волшебник
Характер: Chaotic Good
Раса: Дракон
NWN: Скриптинг [PW]



Часть 1.

Журналы
Краткая статья о журналах.
Что это такое, для чего, как использовать и немного про динамические журналы.

Начнем с примеров. Отрываем тулсет, заходим в редактор журнала (tools->Journal Editor , или жмем CTRL-ALT-J)

(IMG:http://kaa.mhost.ru/nwn/img/shot1-1.gif)
рисунок 1.1

Структура журнала – двухуровневая. Первый уровень – название записи, т.е. то что будет видно в игре когда запись не раскрыта, так сказать заголовок конкретного под-журнала.
Второй уровень добавляется к указанной записи, обычное использование – шаги выполнения квеста.
\(корень журнала)
+запись 1 – квест (уровень 1)
+квест 1, шаг 1 (уровень 2)
+квест 1, шаг 2 (уровень 1)

+ запись 2, (уровень 1)


Давайте для простоты договоримся о том, как что будем называть.
Есть журнал, он один. Есть редактор журнала, тоже один.
Есть множество записей в журнале – так и буду их называть, запись журнала или сокращенно просто запись. Синонимы – поджурнал, квест.
Для каждой записи можно задать сколько угодно шагов, каждый будет иметь свой номер, название и возможно статус завершения квеста.

Пока вернемся к рисунку 1.1, разберем все что там есть.

Category: Тут описываются основные параметры записи.
Name: Название записи, отображается в игре
Tag Тег записи, используется для управления из диалога/из скрипта . Тег надо делать уникальным в пределах модуля.
Priority Приоритет записи. Если будут активны более одной записи, можно менять порядок отображения квестов в игре, задавая больший приоритет записи (квесту).
XP Тут можно задать количество опыта, получаемого за квест. Это значение можно получить из скрипта, используя функцию GetJournalQuestExperience(string sTag), где sTag – тег нужной записи.

(IMG:http://kaa.mhost.ru/nwn/img/shot1-2.gif)
рисунок 1.2

Добавляем шаги квеста. Каждый шаг имеет свое название (поле text), которое будет показываться игроку, когда он раскроет запись в журнале, ID – обычно номер шага и флажок – является ли этот шаг завершающим. Если достигнут этот шаг – запись переходит из категории «активные квесты» в категорию «выполненные квесты» в журнале игрока в игре.

Собственно на этом вся работа по журналу и заканчивается, дальше посмотрим как можно управлять журналом из диалогов и из скриптов.

Напомню про «цвета», как их можно использовать. НВН понимает теги цветов, т.е. можно кусок текста покрасить в нужный цвет. Делается это примерно так:
<cRGB>text</c>
т.е. парным тегом <c> задается область текста, которая будет окрашена в цвет RGB. Вся сложность в задании параметров. Каждый символ имеет свой код, его числовое значение и используется в качестве параметра.

(IMG:http://kaa.mhost.ru/nwn/img/shot1-3.gif)
рисунок 1.3

Не любой символ можно задать напрямую через тулсет, но выбрать «близко» к 0 или к 255 можно, обычно использую символ “ ” (код 32) и русскую “ю” (код 224).
Т.е. если мы хотим выбрать красный цвет – задаем <cю >text</c>. Полученный RGB цвет будет иметь значение R:224,G:32,B:32, что довольно близко к красному цвету.
Для «продвинутых»: Если есть желание – можно сделать библиотеку и в ней после компиляции попробовать поменять цвета на близкие к 0 и к 255


Добавлено в 20:12
Часть 2.

Как редактировать журнал – разобрались, посмотрим как ими управлять. Т.е. зачем вообще нам нужны записи в журнале.
Для примера создадим примерно такую запись в журнале:

(IMG:http://kaa.mhost.ru/nwn/img/shot2-1.gif)
рисунок 2.1

Создадим простой диалог, в котором можно будет получить наш «квест»
Открываем редактор диалогов (tools->Converstion Editor, или CTRL-ALT-V)
Создаем простой диалог, используя кнопку “add”-добавить.

(IMG:http://kaa.mhost.ru/nwn/img/shot2-2.gif)
рисунок 2.2

В ответе игрока «Да» переходим на закладку «Other Action» (Другие действия) и в поле Journal выбираем нашу запись и начальный шаг квеста.

Теперь, если игрок поговорит с НПС, которому назначен этот диалог и ответит «Да» - у него в журнале появится новая запись, текст которой будет содержать информацию из шага номер 1 (именно его мы задали в диалоге)

Если вы еще не знаете, что такое «скрипты» - дальше можно не читать, вся работа с журналом требует как минимум умения работы с помощником.

Посмотрим, как можно организовать проверку условий выполнения «квеста», проверить выполнение «шагов» и перейти на следующий шаг.

Пусть у нас все тот-же НПС в том же диалоге должен
1) выдать квест,
2) проверить выполнение «шага 1».,
3) выдать задание «шаг 2» и так далее до конца.

Основная «трудность» при работе с журналом – нельзя получить из скриптов\диалогов номер активного в данный момент шага. Т.е. нам приходится помнить это самим.

Давайте заведем локальную переменную для игрока, которая будет отображать, какой сейчас шаг активен. (расмотрим вариант для сингл-модуля, с шардами чуть сложнее из-за необходимости идентифицирования игрока)

Вернемся к нашему диалогу (рисунок 2.2). Перейдем на закладку “Action Taken” (Пункт был выбран), т.е. какой скрипт запустить в случае, если игрок выбрал данный пункт диалога.
Пишем имя скрипт, пусть будет «my_q001_taken01» (my_ - преффикс, чтобы не пересечься случайно со скриптами bioware или любыми другими, q001- номер квеста, taken01 –номер «взятого» шага. Уже по имени нам будет понятно, что примерно скрипт делает.

Жмем кнопку редактировать, тулсет скажет нам что такого скрипта нет, жмем ОК и пишем скрипт.
Neverwinter Script Source
void main()
{
    SetLocalInt(GetModule(),"my_q001_step",1);
}


Скрипт просто устанавливает «глобальную» переменную, т.е. переменную модуля, по имени «my_q001_step» равным 1. Теперь из других скриптов мы можем узнать, какой шаг активен в квесте.


Жмем F7 – компилировать и сохранить скрипт, если ошибок нет – выходим из редактора скриптов.


Давайте добавим в диалог новую запись, ответ НПС в случае если шаг 1 выбран. И заодно уберем из диалога фразу о получении квеста, если квест уже был взят.
Для этого нужно написать скрипт на закладке Text Appears When (Текст появится при условии). Сначала для уже существующей записи, проверим что квест еще не получен и только в этом случае выводим фразу, предлагающую взять квест.
Скрипты с условием выглядят чуть по другому, даже если мы начинаем новый скрипт – сразу формируется шаблон скрипта. Дело в том, что такой скрипт должен возвращать число, если это будет 0 (FALSE, ложь) – фраза в диалоге не появится, 1 – появится.
Назовем скрипт «my_q001_when01», т.е. условие появления шага 01 для квеста номер 001.
Neverwinter Script Source
int StartingConditional()
{
    int iResult;

    iResult = GetLocalInt(GetModule(),"my_q001_step") == 0;
    return iResult;
}


В скрипте мы проверяем переменную, в которой хранится (или еще только будет храниться) номер шага. Если там храниться 0 (в нашем случае там будет 0 до ответа «Да» в диалоге), то возвращается 1 (т.е. верно условие «номер_шага равен 0»).

После того как мы получи квест и попытаемся снова поговорить с НПС – ничего не произойдет, НПС выдаст приветствие и больше ничего. Чего мы пока и добивались.
Теперь добавим в диалог вторую фразу, которая появится в случае, если шаг 1 уже был взят. Там же по идее должна быть проверка на то, что условия квеста для завершения шага 1 выполнены, но у нас пока нет такой цели.

(IMG:http://kaa.mhost.ru/nwn/img/shot2-3.gif)
рисунок 2.3

Скрипты для проверки условий появления фразы и после ответа «Да» отличаются только одной цифрой, номером шага который они проверяют.

Вот и все, закончили самое простое.
В принципе такие простые квесты проще строить Plot Wizard’ом, он позволяет основные простые типы квестов (убить, убить и принести докозательство, найти и принести) сконструировать прямо в нем, просто выбирая нужных НПС, вещи или создавая новых (прям в нем). Правда полученный в результате код будет не оптимальным и вряд ли подойдет для шардов.

Добавлено в 20:13
Часть 3. Custom tokens. (Метки пользователя)


Что такое custom tokens и для чего они используются.
Метки {Метка – token (маркер, токен)} используют тот же механизм, что и раскраска цвета. В текст вставляется тег вида
<CUSTOMXXXX>, где XXXX – просто номер. Номера с 0 до 9 используются bioware в своих скриптах, их использовать нельзя. На место метки при выводе информации подставляется значение метки, которое задается с помощью скриптов функцией
Neverwinter Script Source
void SetCustomToken(
    int nCustomTokenNumber,     // номер метки
    string sTokenValue          // текст
);


Самый простой пример использования в диалогах. При обращении НПС к игроку можно менять часть фразы, в зависимости от пола игрока, т.е. он\она, лорд/леди и т.п., включая окончания. Вот к примеру скрипт Олвина, задающий 20 возможных меток в зависимости от пола персонажа, добавляется в условие Text Appears When (хотя можно куда угодно, до вывода токена)
Neverwinter Script Source
int StartingConditional()
{
    object oPC = GetPCSpeaker();
    if (GetGender(oPC)==GENDER_MALE)
    {
        SetCustomToken(2001, "он");
        SetCustomToken(2002, "его");
        SetCustomToken(2003, "ему");
        SetCustomToken(2004, "друг");
        SetCustomToken(2005, "мужчина");
        SetCustomToken(2006, "мой");
        SetCustomToken(2007, "Ясень копий");
        SetCustomToken(2008, "ся");
        SetCustomToken(2009, "");
        SetCustomToken(2010, "Хозяин");
        SetCustomToken(2011, "пришел");
        SetCustomToken(2012, "ел");
        SetCustomToken(2013, "мог");
        SetCustomToken(2014, "приятель");
        SetCustomToken(2015, "гость");
        SetCustomToken(2016, "ый");
        SetCustomToken(2017, "");
        SetCustomToken(2018, "ец");
        SetCustomToken(2019, "господин");
        SetCustomToken(2020, "человек");
    }
    else
    {
        SetCustomToken(2001, "она");
        SetCustomToken(2002, "ее");
        SetCustomToken(2003, "ей");
        SetCustomToken(2004, "подруга");
        SetCustomToken(2005, "женщина");
        SetCustomToken(2006, "моя");
        SetCustomToken(2007, "Фрейя обручий");
        SetCustomToken(2008, "ась");
        SetCustomToken(2009, "а");
        SetCustomToken(2010, "Хозяйка");
        SetCustomToken(2011, "пришла");
        SetCustomToken(2012, "ла");
        SetCustomToken(2013, "могла");
        SetCustomToken(2014, "красавица");
        SetCustomToken(2015, "гостья");
        SetCustomToken(2016, "ая");
        SetCustomToken(2017, "ла");
        SetCustomToken(2018, "ка");
        SetCustomToken(2019, "госпожа");
        SetCustomToken(2020, "женщина");
    }
    return TRUE;
}

Теперь если в диалоге напишем
CODE

Добрый день <CUSTOM2006> <CUSTOM2019>

и поставим этот скрипт в условие показа скрипта, то в зависимости от пола НПС будет говорить «Добрый день мой господин» или «Добрый день моя госпожа»
Для английского языка (и других, на которые переведена игра) проще, там токены можно выбрать прямо в диалоге.

Надеюсь идея понятна – метка позволяет нам из скрипта менять содержимое диалогов, журнала и много чего еще.

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

К сожалению метки плохо работают в именах объектов. Если вы зададите имя объекта в виде <CUSTOMZZZZ> и инициализируете токен – на существующие объекты это не окажет влияния. Если вы создадите новый объект – имя изменится на заданное вами значение. Но если вы измените это значение – имя на объекте останется не изменным до смены локации игроком.
Это применимо к именам placable object’ов, с item’ами даже такое не работает.
Поле “description” тоже не изменится.
Получить значение метки из скрипта тоже нельзя.
Добавлено в [mergetime]1128183350[/mergetime]
Попозже допишу про динамические диалоги, как сделать один диалог для множества действий.

Сообщение отредактировал _kaa_ - Oct 1 2005, 19:14
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Chimeric
сообщение Oct 7 2005, 06:25
Сообщение #2


Пушкин
Иконки Групп

Класс: Обыватель
Характер: Chaotic Neutral
Раса: Гигант
NWN: Тексты



Отлично, а нельзя назначать опыт за выполнение отдельных шагов квеста? Если это ступени, то было бы логично капать по чуть-чуть XP, а в конце дать большой куш. Или обязательно оформлять это как отдельные квесты?

Второй вопрос: что там с перепиской уже существующих записей?
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Клемент Астилон
сообщение Oct 7 2005, 06:46
Сообщение #3


Level 11
Иконки Групп

Класс: Клерик
Характер: Chaotic Good
Раса: Полуэльф
NWN: DM



Великолепный туториал. :good:

Опыт дается с помощью скрипта который на ветвь диалога вешаем ;)
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Валеско
сообщение Oct 7 2005, 08:54
Сообщение #4


Epic Level
Иконки Групп

Класс: Бард
Характер: Chaotic Neutral
Раса: Животное
МАСТЕР Пера



кинуть что ли в "кузницу слов"?..
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
_kaa_
сообщение Oct 7 2005, 16:20
Сообщение #5


Level 9
Иконки Групп

Класс: Волшебник
Характер: Chaotic Good
Раса: Дракон
NWN: Скриптинг [PW]



QUOTE (Chimeric @ Oct 7 2005, 07:25)
Отлично, а нельзя назначать опыт за выполнение отдельных шагов квеста? Если это ступени, то было бы логично капать по чуть-чуть XP, а в конце дать большой куш. Или обязательно оформлять это как отдельные квесты?


В записи журнала хранится только одно поле для опыта, за завершение всего квеста. Но в любом случае каждый шаг обрабатывается либо в журнале со скриптом, либо просто скриптом, где никто не мешает тебе выдать опыт. Запись в журнале - скорее "заготовка" и описание квеста, вся реализация ложится на скриптера (от чего и пытаюсь избавиться с помощью QS).
Хорошим вариантом будет, к примеру, выдавать на каждом шаге часть заданного XP. Скажем в журнале 5 шагов, в скрипте из диалога выдавать после завершения шага 1/N-ую опыта, скажем 1/10 и всю или часть в конце квеста. Тогда будет легче балансировать квесты относительно друг-друга, и не нужно будет лезть в каждый скрипт для исправления.

QUOTE
Второй вопрос: что там с перепиской уже существующих записей?


В стандартном варианте нет такого понятия "перезапись". Есть заготовленный журнал, состоящий из записей. Можно активировать квест, "передвинуть" на следующий шаг.
Neverwinter Script Source
void AddJournalQuestEntry(
    string sCategoryTag,
    int nEntryID,
    object oCreature,
    int bAllPartyMembers = TRUE,
    int bAllPlayers = FALSE,
    int bAllowOverrideHigher = FALSE
);

nEntryID - как раз и есть номер шага.
Если изменения состояния квеста идет не через диалог, а через скрипт - тут можно задать чуть больше параметров.
bAllPartyMembers - для одного игрока или для всей партии изменять состояние квеста
bAllPlayers - для одного игрока или для всех игроков изменять состояние квеста
bAllowOverrideHigher - тут указывается, можно ли "откатиться" в более раннее состояние квеста, т.е. сделать шаг "назад" в квесте.
По задумке bioware номер шага (ID) отражает степень готовности квеста. Т.е. если мы каким то способом пришли к шагу 8, именно этот параметр определяет, сможем ли мы попасть на , к примеру, шаг 4.
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Isendel
сообщение Oct 8 2005, 20:18
Сообщение #6


Level 10
***

Класс: Бард
Характер: Chaotic Good
Раса: Эльф



Стерто

Сообщение отредактировал Isendel - Oct 8 2005, 20:46
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Nashman
сообщение Oct 8 2005, 23:11
Сообщение #7


Level 8
***

Класс: Тайный Лучник
Характер: Lawful Good
Раса: Эльф



Медаль за ОФИГЕННО КЛАСНУЮ статтю получает _kaa_....
Благодарю за это тебя....З большой буквы Т.... :)
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
Valleo
сообщение Oct 24 2005, 06:28
Сообщение #8


Level 4
**

Класс: Друид
Характер: Neutral Evil
Раса: Эльф
NWN: Скриптинг [PW]



Ню это видимо давно кому то надо было сделать, и наш Каа честно справился с задачей ;)

QUOTE
Попозже допишу про динамические диалоги, как сделать один диалог для множества действий.

Когда? Очень интерестно... ;)
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения
_kaa_
сообщение Oct 28 2005, 20:14
Сообщение #9


Level 9
Иконки Групп

Класс: Волшебник
Характер: Chaotic Good
Раса: Дракон
NWN: Скриптинг [PW]



Тут продолжение
Поскольку уже не для "зеленых" новичков и больше нужно для шардов (хотя и для развитых модулей пригодится)
Вернуться в начало страницы
Скопировать ник в поле быстрого ответа
+Ответить с цитированием данного сообщения

Тема закрытаОткрыть новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



Текстовая версия Сейчас: 28th March 2024 - 18:29