jsiq/help/api

СКРИПТОВАЯ СИСТЕМА ЯТК, ИЛИ, КАК ПИСАТЬ СКРИПТЫ

1. Особенности JavaScript, переменные, функции и объекты

Данное руководство не может претендовать на исчерпывающее руководство по языку JavaScript?, но я попытаюсь помочь со знакомством с ним, а также показать некоторые нюансы использования яваскрипт для взаимодействия с ЯТК. Для начала, коснёмся переменных. В яваскрипт, для использования переменной, сначала необходимо её создать, для этого служит ключевое слово var. Например строка var value; // создать переменную value Для удобства программирования в ЯТК предопределены две переменные, благодаря которым переменные определять не надо. Например, можно писать:

_G['value'] = 'test!';

это же можно написать и так:

_G.value = 'test!';

Переменные сохраненные в _G (альтернативное название globals) существуют во всех параграфах. Т.е. значения в этом массиве постоянны. Но есть ещё массив _L (альтернативное название locals), где переменные сохраняются только в "пределах" параграфа - после перехода на другой параграф, массив будет абсолютно пустым.

Для создания своих функций в тексте скрипта параграфа, вы можете использовать конструкцию вида:

_L['my_func'] = function(x, y)
{
        return x * y;
}

А использовать её можно так:

addText('Результат 2*2=' + _L['my_func']());

Конечно же можно использовать и _G вместо _L, но при использовании _G для хранения ф-ий желательно не забывать их оттуда удалять. Удалить значение из массивов _G и _L в простейшем случае можно методом _delete:

_G._delete('my_func');

В яваскрипт нет полноценной объектно-ориентированной модели, но, тем не менее, в языке реализована поддержка объектов, позволяя повысить качество кода. Создать свой объект можно например вот так:

_G.player = OBJECT();
_G.player.health_max = 10;
_G.player.health = 10;
_G.player.hit = function(damage)
{
        this.health -= damage;
        if (this.health < 1)
        {
                alert('Вы умерли!);
        }
        else
        {
                alert('Здоровье: ' + this.health);
        }
}

теперь такой объект можно использовать, например так:

_G.player.hit(5);
_G.player.hit(5);

Объекты могут быть "вложенными", т.е. вы можете создавать и такие конструкции:

_G.player = OBJECT();
_G.player.health = OBJECT();
_G.player.health.current = 10;
_G.player.health.max = 10;
...

В случае, когда доступ к каким-то переменным, хрянящимся в _G (не относится к _L т.к. он "регулярно чистится"!) вы планируете обращаться часто, например, к тому же _G.player имеет смысл сделать более короткий путь к этой переменной вот таким образом:

var player = _G.player;

при этом, имя новой переменной может быть любым. Можно даже вот так:

var player_health = _G.player.health;

При этом важно помнить, что полученная переменная и переменная всё-ещё хранящаяся в _G являются одним и темже. Поэтому скрипт:

_G.text = 'test';
var myvar = _G.text;
myvar.text = 'new test';
alert(_G.text);

Выведет на экран сообщение с текстом "new test"

Логические конструкции языка не имеют отношения к ЯТК, но заслуживают внимания для того, чтобы ваши скрипты были функциональнее. Конструкция условия if имеет следующий вид:

if (условие)
{
	блок выполняющийся если условие выполнено ("правда")
}
else // не обязательная часть
{
	блок выполняющийся если условие НЕ выполнено ("ложь")
}

примеры:

1.

if (_G['text'] == 'test')
{
        alert('ok!');
}

2.

if (_G.player.health > 0)
{
        alert('ok!');
}
else
{
        alert('player died!');
}

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

for (Начальное значение; условие; Инструкция обновления)
{
	инструкции
}

Пример:

for (_G.i = 0; _G.i < 5; _G.i++)
{
        alert('Номер: ' + _G.i);
}

Дополнительно с управляющими конструкциями языка можно познакомиться  здесь.


2. API-функции ЯТК

Здесь и далее поразумевается, что:

Параграф
Локация в игре описанная текстовой формой

Действие
Один из вариантов выбора игроком ведущий на другой параграф. Подразумевается, что действие - это блок созданный в книге конструкцией вида div id="action"...
function addText(text)
Добавить текст text к тексту параграфа. Текст может быть html-отформатирован, но в Internet Explorer замечен глюк с добавлением тэга <p>:
// НЕ РАБОТАЕТ!!!
addText('<p>Какойто текст</p>');

// работает
addText('<' + 'p>Какойто текст</' + 'p>');

// работает
addText('<span>Какойто текст</span>');
function setText(text)
Заменить текст параграфа на содержимое text. Текст может быть html-отформатирован.
function addAction(text, action, evaltext, visible, style)
Добавить новое действие к списку действий параграфа
function showAction(n)
Показать действие номер n
function hideAction(n)
Спрятать действие номер n
function showAllActions()
Показать все действия
function hideAllActions()
Спрятать все действия
function showArticle(n)
Перейти на параграф n, причем n - всегда строка. Если необходимо перейти на параграф "по цифре", используйте goto_str()
function get_url(text, action)
Возвращает строку с html-кодом ссылки, выполняющей скрипт action и текстом text, где action должен быть строкой
function goto_str(p1, p2)
Сформировать строку вида "p1_p2", где p2 - не обязателен, тогда результат будет - строка "p1" Может пригодиться при написании скриптов вложенных друг-в-друга, например:
  ... onclick="addText('<a href=\'#\' onclick=\'showArticle(goto_str(5, 2));\'>Перейти</a>')" ...
function rnd(min, max)
Вернуть случайное число от min до max
function customDice(dice, count, mod1, mod2, res)
Кинуть count кубиков с dice количеством граней (подразумевается, что на гранях числа от 1 до dice), к каждому результату прибавить mod1, к сумме прибавить mod2, вернуть сумму Если при вызове передать массив последним параметром, ф-ия сохранит в этот массив результаты каждого броска
  _G.result = customDice(6, 2); // кинуть 2d6 без модификаторов

3. Описание дополнительных ЯТК-модулей (плагинов)

3.1 Инвентарь

3.1.1 Объект инвентаря

INVENTORY()
Создать новый объект инвентаря
  _G.inventory = INVENTORY();

методы объекта инвентаря:

.isItem(name)
Проверка наличия в инвентаре предмета с названием name. Если предмет будет найден, результат - его номер, иначе результат -1

.isItemCount(name, at_least_count)
Проверка наличия в инвентаре at_least_count штук предметов с названием name. Если нужное кол-во будет найдено, результат true, иначе false
.getItem(name)
Найти и "вернуть" предмет с названием name. Если предмет не найден, результат - null.
.addItem(name, cnt, func)
Создать и добавить в инвентарь предмет с названием name, количеством cnt (func - функция использования предмета, см. описание объекта ITEM)
.removeItem(name, cnt)
Убрать из инвентаря cnt штук предмета с названием name
.on_update
Если задать этот callback, то он будет вызываться каждый раз при изменении содержимого инвентаря: при использовании методов .addItem и .removeItem
 _G.inventory.on_update = function()
{
 Alert('Инвентарь только-что изменился!');
}
 _G.inventory.addItem('предмет', 2);
.removeItemByNum(n, cnt)
Забрать cnt штук предметов номер n из инвентаря
.getListAsHTML(delim, show_count)
Получить список содержимого инвентаря в виде строки. При формировании списка, используется символ-разделитель delim (если не указно - строка "<br>"), а если show_count равен true, то отображается и кол-во каждого предмета.

3.1.2 Класс предмета ITEM

ITEM(name, count, func)
Создать новый объект предмета
  _L.new_item = ITEM('новый предмет', 2);

свойства объекта предмета:

.name
Название (обязательно)
.count
Кол-во предметов, если при создании не указано равно 1
.on_use
Ф-ия которая хранится вместе с предметом, например, в ней можно реализовать скрипт отрабатывающий "использование" предмета (не обязательно)

3.1.3 Комплексный пример

<div class="onload">
  _G.inventory = INVENTORY();
  _L.new_item = ITEM('весчь');
  _G.inventory.add(new_item);
  _L.new_item.cnt = 2; // изменяем кол-во предметов "весчь" прямо в инвентаре(!) (new_item "смотрит" на этот предмет!)
  _G.inventory.addItem('большая штука', 1, function()
  {
    alert('Вы только что заюзали бАльшую штуку!');
  });
  _G.inventory.on_update = function()
  {
    alert('Содержимое инвентаря: ' + _G.inventory.getAsHTML(', ', true);
  }
  _G.inventory.add(ITEM('ещё одна весчь', 2));
  alert('Предмет "большая штука" имеет в инвентаре номер ' + _G.inventory.isItem('большая штука'));
  _G.inventory.getItem('большая штука').on_use(); // используем предмет
</div>

3.2 Изображение к параграфу

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

jsIQ.article_img_div
HTML-элемент (обычно div) в который будет загружаться изображение
jsIQ.article_default_img
HTML-код который будет отображён, если к параграфу не указано изображение
<div class="preload">
  jsIQ.article_img_div = $('#image'); // говорим, что отображать картинку в элементе с id="image"
  jsIQ.article_default_img = '<b>нет картинки!</b>';
</div>
<div class="img">data/1.jpg</div>

3.3 Диалоговые окна

После подключения плагина, для отображения окна, его сначала необходимо создать:

jsIQ.dialogs.add(eid, params)
Ищет элемент с id=eid и инициализирует его с параметрами params
jsIQ.dialogs.show(eid)
Отображает диалоговое окно с содержимым элемента с id=eid
jsIQ.dialogs.hide(eid)
Закрывает диалоговое окно с содержимым элемента с id=eid
DIALOG_INIT(eid, params)
Тоже самое что jsIQ.dialogs.add(eid, params)
DIALOG_SHOW(eid)
Тоже самое что jsIQ.dialogs.show(eid)
Пример
...
<div id="myWindow" class="myWindowClass">Тут пусто, но это же всего пример! :)</div>
...

<div id="book" ...>
...
<div class="onload">
 jsIQ.dialogs.add('#myWindow', {addClose:true})::
 jsIQ.dialogs.show('#myWindow');
</div>
...
</div>

(для правильного отображения окна, необходимо добавить описание класса myWindowClass в файл dialogs.css по аналогии с другими окнами)

3.4 FLV видео плеер

jsIQ.video.play(link)
Воспроизвести видеофайл link
jsIQ.video.close()
Удалить плеер со страницы

4. Функции работы с элементами страницы

is_valid(v)
Возвращает true если v не null и не undefined
get_value(id)
Возвращает значение элемента с id раным id (простите за каламбур). Под значением подразумевается value элементов типа input
set_value(id, val)
Устанавливает значение элемента с id в val. Под значением подразумевается value элементов типа input
make_unclickable(elem)
Делает гиперссылку неактивной, заодно меняя ей стиль для обозначения того, что она более не активна
get_element(id)
Получить указатель на элемент id

5. Расширенный функционал

jsIQ.createActionEx(text, action, evaltext, visible, style)
Создать новое действие
setActionVisible(n, value)
Установить видимость действия номер n в значение value (true/false)
sys_msg(msg, level)
Сохранить в системный лог jsIQ сообщение msg. level - не обязательный параметр обозначающий уровень ошибки, где 1 - ошибка, 2 - предупреждение, 3 - уведомление. jsIQ фильтрует поступающие сообщения по уровню сообщения.