Skip to content

Переходы между сценами

Традиционные переходы в INSTEAD выглядят как ссылки над описанием сцены. Для определения таких переходов между сценами используется атрибут сцены -- список 'way'. В списке определяются комнаты, в виде имён комнат или переменных-ссылок, аналогично списку 'obj'. Например:

lua
room {
	nam = 'room2';
	disp = 'Зал';
	dsc = 'Вы в огромном зале.';
	way = { 'main' };
};

room {
    nam = 'main';
	disp = 'Главная комната';
	dsc = 'Вы в большой комнате.';
	way = { 'room2' };
};

При этом, вы сможете переходить между сценами 'main' и 'room2'. Как вы помните, 'disp' может быть функцией, и вы можете генерировать имена переходов на лету. Или использовать title, для разделения имени сцены как заголовка и как имени перехода:

lua
room {
	nam = 'room2';
	disp = 'В зал';
	title = 'В зале';
	dsc = 'Вы в огромном зале.';
	way = { 'main' };
};

room {
    nam = 'main';
	title = 'В главной комнате';
	disp = 'В главную комнату';
	dsc = 'Вы в большой комнате.';
	way = { 'room2' };
};

При переходе между сценами движок вызывает обработчик 'onexit' из текущей сцены и 'onenter' в той сцене, куда идёт игрок. Например:

lua
room {
	onenter = 'Вы заходите в зал.';
	nam = 'Зал';
	dsc = 'Вы в огромном зале.';
	way = { 'main' };
	onexit = 'Вы выходите из зала.';
};

Конечно, как и все обработчики, 'onexit' и 'onenter' могут быть функциями. Тогда первый параметр это (как всегда) сам объект - комната, а второй -- это комната куда игрок собирается идти (для 'onexit') или из которой собирается уйти (для 'onenter'). Например:

lua
room {
	onenter = function(s, f)
		if f^'main' then
			p 'Вы идёте из комнаты main.';
		end
	end;
	nam = 'Зал';
	dsc = 'Вы в огромном зале.';
	way = { 'main' };
	onexit = function(s, t)
		if t^'main' then
			p 'Я не хочу назад!'
            return false
		end
	end;
};

Запись вида:

if f^'main' then

Это сопоставление объекта с именем. Это альтернатива записям:

if f == _'main' then

Или:

if f.nam == 'main' then

Или:

if std.nameof(f) == 'main' then

Как видим на примере onexit, эти обработчики, кроме строки, могут возвращать булевое значение статуса. Аналогично обработчику onact, мы может отменить переход, вернув false из onexit/onenter.

Вы можете сделать возврат статуса и другим способом, если это кажется вам удобным:

lua
	return "Я не хочу назад", false

Если же вы используете функции 'p'/'pn'/'pr', то просто возвращайте статус операции с помощью завершающего 'return', как показано в примере выше.

Важно!

Следует отметить, что при вызове обработчика 'onenter' указатель на текущую сцену (here()) ещё не изменён!!! В INSTEAD есть обработчики 'exit' (уход из комнаты) и 'enter' (заход в комнату), которые вызываются уже после того, как переход произошёл. Эти обработчики рекомендованы к использованию всегда, когда нет необходимости запрещать переход.

Иногда есть необходимость, чтобы название перехода отличалось от названия комнаты, в которую ведёт этот переход. Существует несколько способов сделать это. Например, с помощью 'path'.

lua
room {
	nam = 'room2';
	title = 'Зал';
	dsc = 'Вы в огромном зале.';
	way = { path { 'В главную комнату', 'main'} };
};

room {
	nam = 'main';
    title = 'Главная комната';
	dsc = 'Вы в большой комнате.';
	way = { path {'В зал', 'room2'} };
};

На самом деле, 'path' создаёт комнату с атрибутом 'disp', который равен первому параметру, и специальной функцией 'onenter', которая перенаправляет игрока в комнату, заданную вторым параметром 'path'.

Если вы укажете три параметра:

way = { path {'#взал', 'В зал', 'room2'} };

То первый параметр станет именем (или тегом, как в приведённом примере) такой комнаты.

Альтернативная форма записи с явным заданием атрибута nam:

way = { path { nam = '#взал', 'В зал', 'room2'} };

Вы можете менять название перехода после того, как переход происходил хотя бы раз, и вы узнали, что же это за комната:

way = { path {'#вдверь', 'В дверь', after = 'В гостиную', 'room2'} };

Все параметры, кроме имени перехода, могут быть функциями.

Таким образом, 'path' позволяет именовать переходы удобным способом.

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

Нет особого смысла прятать переход "дверь". Просто в функции 'onenter' сцены внутри дома мы проверяем, а есть ли у героя ключ? И если ключа нет, говорим о том, что дверь закрыта и запрещаем переход. Это повышает интерактивность и упрощает код. Если же вы хотите сделать дверь объектом сцены, поместите её в комнату, но в 'act' обработчике сделайте осмотр двери, или дайте возможность игроку открыть её ключом (как это сделать - мы рассмотрим позже), но сам переход дайте сделать игроку привычным способом через строку переходов.

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

lua
obj {
	nam = 'часы';
	dsc = [[Тут есть старинные {часы}.]];
	act = function(s)
		enable '#часы'
		p [[Вы видите, что в часах есть потайной ход!]];
	end;
}

room {
	nam = 'Зал';
	dsc = 'Вы в огромном зале.';
	obj = { 'часы' };
	way = { path { '#часы', 'В часы', 'inclock' }:disable() };
};

В данном примере, мы создали отключённый переход, за счёт вызова метода 'disable' у комнаты, созданной с помощью 'path'. Метод 'disable' есть у всех объектов (не только комнат), он переводит объект в отключённое состояние, которое означает, что объект перестаёт быть доступным игроку. Замечательным свойством отключённого объекта является то, что его можно включить с помощью 'enable()';

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

Альтернативный вариант заключается не в выключении, а 'закрытии' объекта:

lua
obj {
	nam = 'часы';
	dsc = [[Тут есть старинные {часы}.]];
	act = function(s)
		open '#часы'
		p [[Вы видите, что в часах есть потайной ход!]];
	end;
}

room {
	nam = 'Зал';
	dsc = 'Вы в огромном зале.';
	obj = { 'часы' };
	way = { path { '#часы', 'В часы', 'inclock' }:close() };
};

В чём разница? Выключение объекта означает то, что объект перестаёт быть доступным для игрока. Если в объекте вложены другие объекты, то и эти объекты становятся недоступными.

Закрытие объекта делает недоступным содержимое данного объекта, но не сам объект.

Однако, в случае комнат, и закрытие комнаты и отключённые комнаты приводят к одному результату -- переход на них становится недоступным.

Ещё один вариант:

lua
room {
	nam = 'inclock';
	dsc = [[Я в часах.]];
}:close()

obj {
	nam = 'часы';
	dsc = [[Тут есть старинные {часы}.]];
	act = function(s)
		open 'inclock'
		p [[Вы видите, что в часах есть потайной ход!]];
	end;
}

room {
	nam = 'Зал';
	dsc = 'Вы в огромном зале.';
	obj = { 'часы' };
	way = { path { 'В часы', 'inclock' } };
};

Здесь мы закрываем и открываем не переход, а комнату, в которую ведёт переход. path не показывает себя, если комната, в которую он ведёт, отключена или закрыта.