Skip to content

Fenia examples

Ruffina Koza edited this page Oct 4, 2019 · 13 revisions

Свалка примеров, как выполнить ту или иную задачу на Фене.

Как проверить, находится ли персонаж под защитой святилища

Для проверки этого или любого другого битового флага используется метод .isset_bit:

if (.isset_bit(ch.affected_by, .tables.affect_flags.sanctuary)) {

}

Также можно воспользоваться битовым оператором и, &:

// Типичный набор сопротивляемостей у сатира:
eval ptc(.tables.res_flags.names(res_flags))
disease wood

// Проверяем что битовая маска не нулевая
eval ptc(res_flags & .tables.res_flags.wood)
8388608

// А в этом случае - нулевая.
eval ptc(res_flags & .tables.res_flags.holy)
0

// Поэтому в сценарии можно писать:
if (ch.res_flags & .tables.res_flags.wood) {
    ch.act("Палки тебе не страшны!");
}

Проверить, что предмет находится внутри данного контейнера

Предмет в 99.9% случаев будет в одном из трех мест: внутри другого предмета, в руках у персонажа или на полу в комнате.

if (item.in_obj == container) {
    item.getRoom().echo("%^O1 находится внутри %O2.", item, container);
} else if (item.carried_by != null) {
    item.getRoom().echo("%^O4 несёт %C1.", item, item.carried_by);
} else if (item.in_room != null) {
    item.getRoom().echo("%^O1 просто лежит на полу в комнате '%s'.", item, item.in_room.name);
}

Выбор случайного персонажа в комнате

Поле комнаты ppl хранит список (List) всех персонажей в этой комнате. Поэтому для работы с ним доступны все методы списка, в том числе random:

eval ptc(in_room.ppl.api())      - вывести API для списка

eval ptc(in_room.ppl.random().name)  - вывести имя случайного персонажа в комнате

Если необходим любой случайный персонаж, кроме ch, этот элемент можно вычесть из списка методом sub и продолжить работать так же:

var vict;

vict = ch.in_room.ppl.sub(ch).random();
if (vict != null) {

}

Цикл по всем персонажам в комнате

Поле комнаты ppl содержит список персонажей в комнате, и для работы с ним удобно использовать синтаксис for (element in list). Предварительно из этого списка можно вычесть ch, чтобы не делать эту проверку внутри самого цикла.

// Переменную mob не надо предварительно объявлять с помощью var.
for (mob in ch.in_room.ppl.sub(ch)) {
    if (.chance(10)) {
        mob.interpret("эмоц глупо хихикает.");
    }
}

Подсчет согруппников в комнате

var group;

group = 0;
for (gch in ch.in_room.ppl) {
    if (ch.is_same_group(gch))
        group = group + 1;
}

ch.act("Рядом с тобой %d членов твоей группы, включая тебя.", group);

Как проверить погоду и флаги помещения

Пусть у нас есть персонаж ch, и ему надо вывести сводку о погоде, если он снаружи помещения.

if (.isset_bit(ch.in_room.room_flags, .tables.room_flags.indoors))
    ch.act("Сперва выйди на улицу.");
else if (.sky == 0) 
    ch.act("Над тобой ясное синее небо.");
else if (.sky == 1)
    ch.act("Небо затянуто тучами.");
else if (.sky == 2)
    ch.act("Идёт дождь.");
else
    ch.act("Гремит гром и сверкают молнии, лучше поищи укрытие!");

Работа с типами местности комнаты

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

if (ch.in_room.sector_type == .tables.sector_table.forest)
    ch.act("Наконец-то ты в лесу!");
var s;

s = .tables.sector_table.name(
            ch.in_room.sector_type);

if (s == "forest")
    ch.act("Вокруг тебя лес.");
else if (s == "field");
    ch.act("Степь да степь кругом.");
else if (s == "city")
    ch.act("Ты в городской местности.");

Проверить, есть ли у персонажа какое-то оружие

if (ch.get_eq_char("wield") != null) {
    // ...
}

Выяснить параметры оружия персонажа

Для этого найдем предмет в локации wield, проверим, что это оружие, и проанализируем его параметры.

var w, damtype, ave;

w = ch.get_eq_char("wield");
if (w != null && w.item_type == .tables.item_table.weapon) {
    ch.act("%^O1 имеет тип удара %s и среднее повреждение %d.",
                     w,
                     .tables.weapon_flags.name(w.value3),
                     w.ave);

    if (w.value3 == .tables.weapon_flags.pierce
        || w.value3 == .tables.weapon_flags.stab)
    {
        ch.act("Это оружие отлично подходит для удара в спину.");
    }
}

Повесить аффект, изменяющий особенности оружия, например, winters touch

Этот аффект сделает оружие обмораживающим на 10 тиков.

var af;

af = .Affect();
af.type = "winters touch";
af.where = .tables.affwhere_flags.weapon;
af.level = 50;
af.duration = 10;
af.bitvector = .tables.weapon_type2.frost;

obj.affectAdd(af);

Предварительно неплохо бы проверить, не обладает ли оружие уже какими-то необычными свойствами:

if (obj.hasWeaponFlag("flaming shocking frost"))
    return;

Повесить простой аффект на персонажа, например, backguard

Этот аффект ничего не изменяет (не задействованы поля location, modifier и т.д.), но на него есть проверка из умений blackjack и ему подобных.

var af;

af = .Affect();
af.type = "backguard";
af.level = ch.modifyLevel;
af.duration = 2;
ch.affectAdd(af);

Более компактная запись:

// Создать и повесить на персонажа аффект на 2 тика.
ch.affectAdd(
         .Affect("backguard", ch.modifyLevel, 2));

Как нанести зависящие от уровня повреждения и выдать сообщение

var dam, vict;

vict = ch.fighting;
ch.act("Ты бьешь по %C3 со страшной силой.", vict);
ch.rvecho(vict, "%^C1 бьет по %C3 со страшной силой.", ch, vict);
vict.act("%^C1 бьет по тебе со страшной силой.", ch);

dam = .dice(ch.modifyLevel, 18);
// Повреждение с сообщением "Твое землятрясение" и типом повреждений 'none'.
ch.damage(vict, dam, "earthquake", "none");
You can’t perform that action at this time.