<aside> 💡 TLDR: Нужно просто вставить скрипт в свободную вкладку NPC и выбрать настройки

</aside>

Cодержание


Для ГМа

Предусловия

  1. Нужно иметь список всех ID диалогов, которые составляют собой недоступный диалог. Добавлять только секцию — допустимо, но неудобно для игрока, потому что вернуться “назад” у него опции не будет.

Untitled

Использование

<aside> 💡 Не забудьте включить скрипт на вкладке “Настройки!

Untitled

</aside>

  1. Кликнуть по НПЦ с диалогом лопатой “Сценарист” из CustomNPC, создать новую свободную вкладку и вставить туда шаблон ниже
  2. Заполнить шаблон по инструкциям внутри
var BLOCKEDIDS = [158, 159, 160] //айди для блокировки
var BUSYID = 174; //диалог, который показывается при блокировке. 174 дефолт

var COMMENT = true; //сообщать ли о занятости в чат?
var ACTOR = "&a" + "@dp" + "&r"; //от кого оправляется сообщение.
//@p - игрок что пытается открыть диалог. @dp - игрок, у которого диалог сейчас открыт
var MESSAGE = "@p пытается подойти к консоли, но её занимает @dp";

var LOG = false;
var DIALOG_ID;
var STOREDDATA;

function dialog(event) {
    STOREDDATA = event.player.world.getStoreddata();

    DIALOG_ID = event.dialog.getId();

    //if at least one of blocked ids active
    for (var i = 0; i < BLOCKEDIDS.length; i++) {
        var data = String(STOREDDATA.get("active"+BLOCKEDIDS[i]))

        if (LOG) {event.player.message("data is " + "active"+BLOCKEDIDS[i] +" = " + data)}

        //not empty -- it's active
        if (data !== "0" && data !== "null") {

            //But the player is not a current player
            if (data !== event.player.getDisplayName()) {
                event.player.showDialog(BUSYID, String(data))

                //show a comment if enabled
                if (COMMENT) {
                    event.player.message(buildMessage(ACTOR, MESSAGE, event.player.getDisplayName(), data));
                }
                //stopping the search to save computing capacities
                return;
            }
        }

    }

    //Nashorn does not support Array.includes(), so I implemented it myself
    var includes;

    for (var i = 0; i < BLOCKEDIDS.length; i++) {
        if (BLOCKEDIDS[i] == DIALOG_ID) {
            includes = true;
        }
    }

    if (includes) {
        //adding current player's name to the memeory as an active dialog
        STOREDDATA.put("active" + DIALOG_ID, event.player.getDisplayName());
        if (LOG) {event.player.message("&eput&r active" + DIALOG_ID + "=" + STOREDDATA.get("active" + DIALOG_ID))}
    }

}

function dialogClose(event) {

    STOREDDATA = event.player.world.getStoreddata();
    DIALOG_ID = event.dialog.getId();

    var includes;

    for (var i = 0; i < BLOCKEDIDS.length; i++) {
        if (BLOCKEDIDS[i] == DIALOG_ID) {
            includes = true;
        }
    }

    if (includes) {
        STOREDDATA.put("active" + DIALOG_ID, "0");
    }

    if (LOG) {event.player.message("&eon finish&ractive" + DIALOG_ID + "=" + STOREDDATA.get("active" + DIALOG_ID))}

}

function buildMessage(actor, message, playerCurrent, playerBusy) {

    var result = String(ACTOR + ": " + MESSAGE);

    while (result.indexOf("@p") != -1) {
        result = result.replace(/@p/gi, playerCurrent);
    }

    while (result.indexOf("@dp") != -1) {
        result = result.replace(/@dp/gi, playerBusy);
    }

    return result;
}

Для админа

cnpcs-scripting-examples/lockOnDialog.js at main · sithamet/cnpcs-scripting-examples

Потенциальная доработка

Нельзя редактировать текст одного и того же диалога блокировки (174), ибо он один для всех игроков.

Но можно генерировать диалоги в спецкатегории, подставляя туда свой текст.

Это, однако, вызывает много вопросов, которые нужно выяснить

  1. Насколько быстрый поиск объекта диалога по ID или имени через хендлер диалогов?
  2. Нужно ли их удалять? Насколько это производительно?
  3. Есть ли лимит в CustomNPC по количеству диалогов?