L'James Notetag System v.1.1


Автор: L'James
Ссылка: http://pastebin.com/GfQaiXZF

Скрипт упрощает работу с ноуттегами в кастомных скриптах.
Возможности
  • Выполнение кода при нахождении регэкса
  • Автоматическое получение данных из тегов с помощью заданных правил]



Использование
Для настройки скрипта используется несложный DSL
Код:
LJ::NOTETAGS.extension do
 
   # Extension styling
   trait_parser create_parser.add_anon_matcher("[%s]"){|x| true}
 
   # Parameter schemes' registraion
 
   declare_features do  
     register :power, hash(:percent).set_key_limit(:fire, :ice, :lightning)
     # Registers notetags like <power fire 150%> - hash parameter. 
   end
 
   declare_skill do
     register :piercing, trait
   end
 
   declare(RPG::Actor, RPG::Enemy) do
     register :undead, trait
   end
 end
После чего параметры можно получить, используя obj.param_name или obj.get_param(:param_name)
Также можно задать features, которые будут вести себя, как стандартные features(без понятия, как их кто переводит) в RPG Maker VXA. Потом их можно получить с помощью battler.feature_name или battler.get_feature(:feature_name)
Более подробно - в инструкции. (Инструкция на кривом английском в самом скрипте более актуальная, чем этот перевод)

Спойлер Инструкции:
L'James Notetag System v 1.0

ОПИСАНИЕ
Скрипт служит для облегчения работы с ноуттегами в кастомных скриптах

Возможности
* Выполнение заданного действия при совпадении заданного регэкса
* Автоматическое получение значений из ноуттегов по заданным правилам и сохранение их в содержимом объекта

ВВЕДЕНИЕ

Основная идея системы - автоматическое считывание и преобразование ноуттегов в значения, называемые параметрами, которые потом можно получить из объекта базы данных с помощью get_param

Параметры бывают четырёх видов:

  • Значения (Value) - просто одно значение некоторого типа, например, целое число
  • Массивы (Array) - собственно, массив значений
  • Хеши (Hash) - набор пар ключ-значение
  • Трейты (Trait) - значение булевского типа. Наличие соответствующего ноуттега в объекте присваивает трейту значение true, отсутствие - false



Чтобы система могла распознавать параметры, требуется создать расширение системы, в котором происходит задание стиля и регистрация схем параметров (правил распознавания) для конкретных классов базы данных. Для этого используется простой DSL.

Расширение выглядит примерно так
Код:
LJ::NOTETAGS.extension do

  # Задание стиля расширения
  trait_parser create_parser.add_anon_matcher("[%s]"){|x| true}

  # Регистрация схем параметров

  declare_feature do
    register :power, hash(:percent).limit(:fire, :ice, :lightning)
    # Регистрирует ноуттеги вида <power fire 150%> - хешевый параметр. После 
    # загрузки будет истинно obj.power[:fire] == 1.5
    # Другой способ:
    # hash(:percent).set_limit(:fire, :ice, :lightning).register(:power)
  end

  declare_skill do
    register :piercing, trait
  end

  declare(RPG::Actor, RPG::Enemy) do
    register :undead, trait
  end
end
Чтобы получить значение параметра, нужно использовать obj.get_param(:name) или просто obj.name, где obj - объект класса базы данных

Параметры могут быть использованы как features из RPG Maker VXA - то есть, параметры на экипировке и статусном эффекте переходят на персонажа или врага. Для получения значения параметров можно использовать battler.get_feature(:feature_name) или просто battler.feature_name, где battler - это Game_Battler

ЗАДАНИЕ СТИЛЯ
Стиль расширения применяется ко всем параметрам, объявленным в этом расширении.

Например, в примере выше задаётся вид трейтов [name] вместо <<name>>. Задание стиля выполняется при помощи следующих методов

  • param_parser - задание с помощью парсера (см. ниже) регэксов для распознавания параметров значений, хешей и массивов. По умолчанию <name value> и <name>\n value \n</name>
  • trait_parser - задание с помощью парсера регэксов для распознавания трейтов.По умолчанию <<name>>
  • arg_selector - регэкс, использующийся схемами хешей и массивов для выделения из ноуттега аргументов. Содержит одну группу, которая захватывает аргумент. По умолчанию, аргумент - это всё, кроме запятых и перевода строки: селектор выделит из <name val1, val2, val3> аргументы "val1", "val2" и "val3"[/li]
  • hash_splitter - регэкс, использующийся хешами для того, чтобы в аргументе, выделенном селектором, выбрать ключ и значение. Содержит две группы, первая захватывает ключ, вторая - значение. По умолчанию деление происходит на первом пробеле: ab cde fgh создаст пару :ab => "cde fgh"



Пояснение:
Пусть распознаётся хеш-параметр <hash a aaa, bb bb b, c cccc cccc>. Сначала он находится в заметке. После чего из строки "a aaa, bb bb b, c cccc cccc" выделяются аргументы "a aaa", "bb bb b" и "c cccc cccc". А затем с помощью сплиттера из каждого аргумента выделяется ключ и значение: "a" -> "aaa", "bb" -> "bb b", "c" -> "cccc cccc". После этого ключ и значение обрабатываются конвертерами и складываются аккумуляторами (см. ниже), из чего мы получаем {:a -> "aaa", :bb -> "bbb", :c "cccc cccc"}

Для выделения параметров из заметки используются парсеры. Парсер - это набор регэксов и кода, выделяющего из MatchData регэкса строку значения. Свой парсер можно делать с помощью create_parser, после чего к нему добавлять регэксы с помощью следующих методов

  • parser.add_matcher(regex){matcher} просто добавляет распознавание для фиксированного регэкса. Matcher принимает на вход MatchData и возвращает строку со значением
  • parser.add_anon_regex(regex_str){matcher} добавляет распознавание для регэкса с распознаванием имени. regex_str - это строка, в которой первый %s будет заменён на имя параметра, прежде чем она будет преобразована в регэкс. Оба метода возвращают self, поэтому их можно вызывать цепочкой


Пример задания стиля

Код:
trait_parser create_parser.add_anon_matcher("[%s]"){|x| true}.add_anon_matcher(""%s"")
# Такой парсер будет распознавать трейты [name] и "name"

hash_splitter /^([^\s]+)\s*=>\s*(.*?)&/
# Хеши будут иметь вид <power fire => 150%>

ЗАДАНИЕ КЛАССОВ

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

Код:
declare(*classes) do 
 # Регистрация схем
end
*classes - перечень классов, в которых будет проводиться поиск параметров по схемам. Для работы требуется, чтобы в классе был метод note.

Также для классов базы данных есть специальные методы: declare_actor, declare_class, declare_item и так далее. Методы declare_usableitem, declare_equipitem и declare_baseitem регистрируют параметры в нескольких классах. Метод declare_features позволяет зарегистрировать параметры, которые будут вести себя как стандартные features/traits/особенности в RPG Maker VXA - то есть, например, параметры героя зависят от его экипировки


РЕГИСТРАЦИЯ СХЕМ

Схемы регистрируются так
register :name, scheme
или так
scheme.register(:name)

Схема - это правила, по которым будет распознаваться тег. Для создания схемы, нужно вызвать метод value, array, hash или trait, после чего настроить схему. У value, array и hash можно задать шаблон параметра - value(:int), чтобы получить уже частично настроенную схему.
При этом имя может содержать символ подчёркивания. В заметках оно будет распознаваться и как подчёркивание, и как пробел
Также можно создать свой тип параметра. Для этого нужно отнаследовать класс LJ::NOTETAGS::SchemeBase или LJ::NOTETAGS::ParamScheme.
  • В SchemeBase нужно перегрузить методы load(note) - принимает текст заметки и возвращает значение и shared_accumulator(a,b) - метод, который принимает два объекта, полученые из load, и возвращает новый объект, который является их "суммой". Если схема используется только в одном классе, можно опустить
  • ParamScheme в конструкторе принимает загрузчик (self), парсер, значение по умолчанию и значение, которое имеет параметр до начала присваивания (т.е., которое передаётся в качестве acc при первом вызове). Нужно перегрузить методы shared_accumulator(a, b) и accumulate(acc, val) - метод, который принимает объект и результат парсера и возвращает объект, являющийся результатом добавления значения в объект


Также, помимо схем, можно зарегистрировать в системе регэкс и действие, которое нужно выполнять, когда он будет найден. Делается это при помощи register_regex, в параметры которого передаётся регэкс и блок действий, который принимает MatchData и текущий объект

НАСТРОЙКА СХЕМ

Конвертер - это функция, которая принимает строку и возвращает значение параметра
Аккумулятор - это функция, которая принимает существующее значение параметра и новое значение и возвращает изменённое значение параметра. Используется, когда встречается несколько ноуттегов для одного параметра в одном объекте

Для настройки стандартных схем применяются следующие методы, свои для каждого типа схемы. Методы возвращают self и могут вызываться цепочкой

Value:

  • set_converter - задать конвертер. Конвертер по умолчанию оставляет значение строкой
  • set_accumulator - задать аккумулятор. Аккумулятор по умолчанию заменяет текущее значение новым
  • set_method_accumulator - задать аккумулятор вида {|acc, val| acc.m(val)}, где m передаётся в качестве аргумента
  • set_default - задать значение, которое будет сохранено, когда в заметке не встречено ноуттегов с соответствующим именем
  • set_startval - задать значение, которое аккумулятор будет считать текущим перед первым присваиванием. Например, целочисленный параметр с startval=1, default = 0 добавит единицу к итоговому значению, но вернёт 0, если тегов найдено не было. При startval = nil (по умолчанию), первый встреченный ноуттег просто сохраняет значение в параметр без участия аккумулятора
  • set_limit - задать список значений, которые будут приниматься при парсинге. Когда лимит - nil (по умолчанию) - ограничение снимается



Пример: value.set_default(0).set_converter{|x| x.to_i}.set_method_accumulator(:+)
Результатом будет суммируемый целочисленный параметр. Аналогично value(:int)

Array:
  • set_converter - задать конвертер для элементов массива
  • set_unique - если true, то повторяющиеся значения не будут добавлены в параметр. По умолчанию true
  • set_limit - задать список значений, которые будут приниматься при парсинге. Когда лимит - nil (по умолчанию) - ограничение снимается

Пример: array.set_converter{|x| x.to_sym}
Это массив неповторяющихся символов

Hash:
  • set_key_limit - задать список значений, которыми может быть ключ. Если nil, ограничение снимается
  • set_key_converter - задать конвертер для ключей. По умолчанию ключ конвертируется в символ
  • Значение, возвращённое через hash[key] ведёт себя как значение-параметр, возвращённый get_param, и настраивается теми же методами:
  • set_converter
  • set_accumulator
  • set_method_accumulator
  • set_default
  • set_startval
  • set_limit



Пример: hash.set_key_limit(:fire :ice, :lightning).set_val_default(1).
set_val_converter{|x| x.chomp("%").to_i/100.0}.set_val_method_accumulator(:*)
Эквивалентно :percent, но с ограничением на ключ

Trait:
Трейты не настраиваются

ШАБЛОНЫ ПАРАМЕТРОВ
Параметры-значения, массивы и хеши можно задать при помощи шаблонов и получить уже преднастроенную схему, с готовыми конвертерами и аккумуляторами. Для создания схемы по шаблону требуется указать тип шаблона

  • :int - целочисленные значения. Значение по умолчанию 0, аккумулятор складывает значения
  • :str - строковые значения. Аккумулятор складывает значения, разделяя их пробелом
  • :sym - символьные значения. Аккумулятор заменяет старое значение новым.
  • :percent - значения в процентах. Конвертер обрубает знак % при необходимости и делит на 100.0. Значение по умолчанию 1, аккумулятор умножает значения
  • :pluspercent - значения в процентах. Вместо умножения аккумулятор их складывает. Так, два +50% дадут значение 2.0, а не 2.25.