Skip to content

Example randomize exits

Ruffina Koza edited this page Oct 28, 2018 · 5 revisions

Пример: перемешивать выходы из комнаты ночью

Задача

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

Подход к решению

1. Как определить время суток

Время суток содержится в поле корневого объекта .sunlight. Можно отпечатать список всех полей корневого объекта и посмотреть по нему справку:

eval ptc(.api())
...
sunlight: время суток: 0=ночь, 1=рассвет, 2=день, 3=закат
...

Поле .hour содержит конкретный час, однако в разное время года темнота наступает в разное время, поэтому поле .sunlight для нашей задачи удобнее.

2. Как выбрать случайный выход

Список полей и методов комнаты можно посмотреть командой

eval ptc(in_room.api())

где in_room - комната, где находится this, т.е. персонаж выполняющий команду eval. Нам понадобятся методы exits - список всех видимых персонажу выходов и getRoom - получить комнату, в которую ведет какая-то дверь.

Метод exits создает и возвращает список. Также новый список можно создать с помощью метода корневого объекта .List(). Поэтому методы списка можно отпечатать себе такими способами:

eval ptc(in_room.exits(this).api())
eval ptc(.List().api())

Нам пригодится метод random - получить случайный элемент списка.

Комбинируя все это вместе, получаем такой код для поиска случайной двери для персонажа ch, затем поиска комнаты, в которую эта дверь ведет и, наконец, внума (номера) этой комнаты:

var mydoors, randomDoor, randomRoom, randomDoorVnum;
mydoors = exits(ch);
randomDoor = mydoors.random();
randomRoom = getRoom(randomDoor);
randomDoorVnum = randomRoom.vnum;
return randomDoorVnum;

Избавляясь от промежуточных переменных:

return getRoom(exits(ch).random()).vnum;

3. Как перемешать выходы в комнате при ходьбе

Oбычно комнаты со случайными выходами задаются в редакторе зон, с помощью особого вида reset-a, 'randomize exits'. Для нашей задачи мы можем перемешивать выходы при попытке персонажа выйти или зайти в эту комнату. Для этого есть такие триггера:

onEntryLocation(walker,sourceRoom,door)
onExitLocation(walker,targetRoom,door)

Они подробно описаны в списке триггеров комнат.

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

.get_room_index(4000).onExitLocation = function(walker, targetRoom, door) {
    if (.sunlight == 0) 
        return getRoom(exits(walker).random()).vnum;
};

Примечание: в общем случае метод exits может вернуть пустой список (например, в комнате без выходов), тогда метод random вернет null и при попытке вызова getRoom с таким аргументом произойдет исключение. Однако в нашем случае мы уверены, что хотя бы один выход из комнаты есть: выход под номером door, ведущий в targetRoom - именно в него бы попал персонаж, если бы мы не вмешались.

4. Как присвоить один и тот же триггер нескольким комнатам сразу

В примере выше триггер onExitLocation присвоится комнате с номером 4000. Но что если таких комнат несколько, например, наша "зловещая роща" состоит из 4х комнат: 4208, 4216, 4207, 4215. Ленивый способ - присвоить триггер какой-то переменной и затем сделать четыре присваивания подряд:

var myfunc;
myfunc = function(walker, targetRoom, door) {
...
};

.get_room_index(4208).onExitLocation = myfunc;
.get_room_index(4216).onExitLocation = myfunc;
...

Более продвинутый способ - организовать все номера этих комнат в список и выполнить присваивание всем элементам списка, используя метод forEach. Этот метод принимает в параметры функцию, которую надо выполнить для каждого элемента списка. Переменная this внутри функции будет указывать на каждый элемент по очереди:

.List().add(4208, 4216, 4207, 4215).forEach(
    function() {
        .get_room_index(this).onExitLocation = function(walker, targetRoom, door) {
        ...
        };
    }
};

Готовый сценарий

Подробнее о работе со сценариями читайте в этой статье.

randomRooms = function() {
    .List().add(4208, 4216, 4207, 4215).forEach(function() {
       .get_room_index(this).onExitLocation = function(walker,targetRoom,door) {
           if (.sunlight == 0) 
              return getRoom(exits(walker).random()).vnum;
       };
    });
}

Не забудьте вызвать функцию randomRooms():

eval randomRooms()

Посмотреть, успешно ли присвоился триггер какой-то комнате, можно так:

eval ptc(.get_room_index(4215).rtapi())

Runtime fields:
onExitLocation
You can’t perform that action at this time.