[#] Реализация НПС в Instead
RSS-bot(tavern,2) — All
2018-04-13 21:51:19


Эта заметка предназначена начинающим авторам наInstead.

Во всех квестах конечно есть НПС с которыми можно общаться, получать задания и т.д. Исторически разработчики не заморачивались разнообразием реплик НПС-болванчиков. Один и тот же диалог запускался при каждом обращении. Я лично считаю это вполне нормальным поведением и данью классическим квестам и рпг, но некоторые считают иначе и ниже я приведу пару способов разнообразить поведение НПС.

Обычно НПС выглядит как-то так:



obj {
nam = 'Трактирщик';
dsc = 'За барной стойкой {трактирщик} протирает стаканы ветхим полотенцем.';
act = function()
walk 'Разговор с трактирщиком';
end;
};


Итак вариант №1: завести специальную квестовую переменную отвечающую за реплики трактирщика. Пишу:



global { -- определение глобальных переменных
q1 = 0;
};

Переписываю трактирщика:




obj {
nam = 'Трактирщик';
dsc = 'За барной стойкой {трактирщик} протирает стаканы ветхим полотенцем.';
act = function()
if q1 == 0 then
walk 'Разговор с трактирщиком';
q1 = 1;
else
walk 'Другой разговор с трактирщиком';
end;
end;
};

Ладно, но может есть способ попроще? Вариант №2: использование функции visits(). visits() возвращает количество посещений комнаты или диалога. Код тогда будет такой:




obj {
nam = 'Трактирщик';
dsc = 'За барной стойкой {трактирщик} протирает стаканы ветхим полотенцем.';
act = function()
if visits('Разговор с трактирщиком') == 0 then
walk 'Разговор с трактирщиком';
else
walk 'Другой разговор с трактирщиком';
end;
end;
};

Хорошо, а если трактирщик выдает какой-то предмет для выполнения квеста? Как например в Fallout 2 Мамаша в Дыре даёт обед для Смитти?




obj {
nam = 'Трактирщик';
dsc = 'За барной стойкой {трактирщик} протирает стаканы ветхим полотенцем.';
act = function()
if not have 'Обед для Смитти' then
walk 'Разговор с трактирщиком';
else
p 'Ты ещё не отнёс обед для Смитти? Поторопись, остынет же!';
end;
end;
};

Кстати реакцию по else я заменил просто кратким напоминанием о задании. Но вот герой отнёс обед, вернулся и опять получает диалог про обед? Нелогично, хотя во многих ММОРПГ обычное дело — дейлики всякие. Можно использовать переменную или опять visits().




obj {
nam = 'Трактирщик';
dsc = 'За барной стойкой {трактирщик} протирает стаканы ветхим полотенцем.';
act = function()
if not have 'Обед для Смитти' and visits('Разговор с трактирщиком') == 0 then
walk 'Разговор с трактирщиком';
elseif have 'Обед для Смитти' then
p 'Ты ещё не отнёс обед для Смитти? Поторопись, остынет же!';
else
walk 'Другой разговор с трактирщиком';
end;
end;
};

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




obj {
nam = 'Трактирщик';
dsc = 'За барной стойкой {трактирщик} протирает стаканы ветхим полотенцем.';
act = function()
if q1 == 0 then
walk 'Разговор с трактирщиком';
elseif have 'Обед для Смитти' then
p 'Ты ещё не отнёс обед для Смитти? Поторопись, остынет же!';
else
walk 'Другой разговор с трактирщиком';
end;
end;
};

И уже в диалоге если герой согласился сделать задание, присвойте q1 = 1;

Заключение: Конечно можно всё это сделать в самом диалоге при помощи cond и тегов, но иногда в результате получается настолько запутанная конструкция, что реально проще раскидать всё это на несколько более простых диалогов, а логику оставить в самом объекте-НПС, как в примерах выше. Впрочем образцы диалогов я возможно опишу в отдельной заметке.
А ещё есть интересная функция seen(), которая тоже часто пригождается в условиях.

Ответьте на опрос ниже и конечно лайк, шер и ретвит! Вопросы пишите в комментариях.

Ссылка: https://ifhub.club/2018/04/13/realizaciya-nps-v-instead.html