Спецификация шаблонов

Содержание:

Немного теории

Для начала разберемся что же из себя представляет шаблон в контексте данной утилиты. Это специальная конструкция в коде или текстовом описании, которая распознается библиотекой FreeMarker, после чего при необходимости выполняется преобразование текста и подстановка конкретных значений.
Можно выделить два вида шаблонов - выражения и директивы.

Выражения

Шаблоны, относящиеся к этому виду выглядят так:
${выражение}
Где в качестве составляющих выражения могут использоваться константы, арифметические операции, обращения к переменным и вызовы функций. Все арифметические операции будут выполнены, значения переменных подставлены, а функции вызваны.
Основное правило:
Результатом обработки выражения должно быть одно и только одно значение!
Использоваться выражения могут в любом месте кода - все что не является шаблоном, воспринимается библиотекой FreeMarker как обычный текст - он ничего не знает о синтаксисе jass, vjass, cjass, ему будет все равно даже если там будет html или голая баба псевдографикой.
Для выражений в текстовых описаниях введен специальный синтаксис #[выражение#] или #[выражение]# в связи с багом отображения фигурных скобок в РО.

Директивы

Эта разновидность шаблонов сложнее чем выражения и предназначена на для банального получения одного значения, а для трансформации целого блока текста.
Директивы в общем виде выглядят примерно так:
<директива параметры>
   трансформируемый блок текста
</директива>
Допускается вложенность директив, а также использование выражений внутри блока текста, принадлежащего директиве.
Основное правило:
У каждой открытой директивы должен быть закрывающий тег!
Теперь подробнее рассмотрим какие директивы доступны для использования

директива if

<if условие>
  этот блок текста будет удален, если условие не будет выполнено
</if>
В качестве условия может быть использовано любое выражение, не только логическое. При этом null расценивается как false, а любое другое значение как true. Также существуют специальные конструкции, предназначенные для использования в качестве условий этой директивы. Например, конструкция "категория.объект" выполнит проверку на принадлежность объекта к указанной категории, причем обращение к объекту может быть как прямым, так и через переменную.
Важно:
Логические выражения, использующие операторы < , > , <= или >= следует заключать в круглые скобки
Список логических операторов:
  • <, >, <=, >=
  • ==, !=
  • !. &&, ||
Также у данной директивы есть расширенная форма:
<if условие>
   этот блок текста будет удален, если условие не будет выполнено
<else>
   этот блок текста будет удален, если условие будет выполнено
</if>
И еще более расширенная:
<if условие1>
<elseif условие2>
<else>
</if>

директива switch-case

<switch выражение>
    <case значение1>
        блок текста, который будет выведен если выражение соответствует значению1
    <break>
    <case значение2>
                блок текста, который будет выведен если выражение соответствует значению2
    <break>
    <default>
                блок текста, который будет выведен если выражение не соответствует ни одному из значений
    <break>
</switch>
Блок <default> не является обязательным. Если не использовать директиву <break>, то будут выведены все блоки начиная с того, значение которого соответствует выражению, и заканчивая блоком, содержащим директиву <break>.

директива list

<list коллекция as переменная>
этот блок будет повторен столько раз, сколько элементов в коллекции, также будет создана локальная переменная с указанным именем, видимая только в пределах этого блока и поочередно принимающая значения элементов коллекции.
</list>
Существует альтернативный синтаксис для этой директивы:
<foreach переменная in коллекция>
этот блок будет повторен столько раз, сколько элементов в коллекции, также будет создана локальная переменная с указанным именем, видимая только в пределах этого блока и поочередно принимающая значения элементов коллекции.
</foreach>
Помимо итерационной переменной также будут созданы две специальные переменные, обладающие той-же областью видимости. Название этих переменных начинается с названия итерационной переменной.
переменная_index - счетчик итераций
переменная_has_next - флаг наличия в коллекции следующего элемента, принимает значение false на последней итерации и true все остальное время
Выполнение директивы <list> можно прервать директивой <break>

Коллекции

В качестве коллекции может быть использована коллекция целых чисел, записываемая в виде a..b, где a и b первый и последний элементы коллекции, соответственно. Также доступно несколько стандартных коллекций, соответствующих типам объектов:
  • units войска
  • abilities способности
  • items предметы
  • buffs бафы и эффекты (временно отключены из соображений оптимизации)
  • upgrades улучшения
  • destructables разрушаемые объекты
  • decorations декорации (временно отключены из соображений оптимизации)
Каждой их этих коллекций соответствует категория, что позволяет использовать коллекции, как категории и наоборот.
Создание пользовательских категорий, в свою очередь, также приводит к возникновению коллекции с соответствующим названием.

Пользовательские категории

Практически любому объекту из редактора объектов может быть присвоен набор пользовательских тегов, позволяющих отнести объект к той или иной категории. Фактически, на данный момент, каждый тег соответствует категории и новые категории автоматически создаются при обнаружении новых тегов.
Задаются теги через поле "описание редактора" (или "editor suffix") следующим образом:
  • символом @ обозначается конец текстовой части и начало списка тегов
  • каждый тег обязательно заключается в квадратные скобки [ ], других разделителей не требуется
-допускается использование пробела как разделителя тегов (вместо квадратных скобок)
  • в теге допускается только латиница и цифры
Недавно были введены параметризованные категории, теги для которых отличаются от обычного использованием двоеточия для разделения имени категории и параметра. При этом параметризованная категория работает точно так-же как и обычная, за исключением того, что у объекта фактически появляется дополнительное поле, соответствующее названию категории и содержащее значение параметра. Этот инструмент может быть использован для хранения небольшого количества метаданных. Например, там можно записать стоимость в нестандартных ресурсах, массу или высоту объекта.
С помощью тегов можно отнести объект не только к пользовательской категории, но и к одной из стандартных. Для этого достаточно указать соответствующее название. Также следует учитывать что к одной категории могут относиться объекты разных типов.

Доступ к данным

Ну и теперь о самом интересном - как же добраться до нужных нам данных?
На данный момент доступны только данные, отличающиеся от стандартных (ведется поиск способов исправить этот недочет без серьезного падения производительности). Обращение к данным можно разделить на прямое и через переменные.

прямое обращение к данным

Для прямого обращения к данным требуется знать равкод объекта и равкод поля, к которому мы обращаемся. Форма записи такого обращения стандартна: объект.поле

доступ через переменные

Это способ получения данных отличается тем, что знать для этого необходимо только равкод поля, а объект должен содержаться в переменной. Форма записи та-же что и для прямого обращения: объект.поле, с той только разницей, что вместо равкода объекта используется содержащая его переменная.
Данный способ используется при перечислении всех объектов в коллекции с помощью директивы list, или, другими словами, всех объектов, относящихся к определенной категории.

alias-ы

Для упрощения доступа к данным используется механизм alias-ов, позволяющий использовать не только равкоды полей, но и их синонимы. Управление синонимами производится через файл Alias.txt в папке Fly. Примером может быть объединение равкодов anam, bnam и unam под синонимом name или Name.

Примеры

шаблон ${2+2} будет заменен 4
${A000.anam} превратится в название способности A000 (на данный момент вместо конкретного названия будет использовано TRIGSTR_ с соответствующим индексом, возможно позже это будет исправлено для текстовых описаний, для кода и так сойдет по идее)
${2 2} вызовет ошибку
<if abilities.A000>
этот текст сохранится
<if units.A000>а этот нет, если вручную не отнести способность A000 к юнитам</if>
</if>
следующий шаблон перечислит названия всех способностей, максимальный уровень которых больше 1
<list abilities as a >
  <if (a.alev > 1) >${a.anam}</if>
</list>
следующий шаблон перечислит ID всех способностей, относящихся к пользовательской категории holyCow и значение параметра категории rage для тех способностей, которые относятся к этой категории.
<list abilities as a >
  <if holyCow.a >${a} <if rage.a >rage: ${a.rage}</if></if>
</list>
local integer n = 0
<list 1..5 as n >
call DisplayTextToPlayer(Player(${n-1}),0,0,"теперь мы знаем что 2+2 = ${2+2}")
</list>
в коде этот фрагмент будет выглядеть так:
local integer n = 0
call DisplayTextToPlayer(Player(0),0,0,"теперь мы знаем что 2+2 = 4")
call DisplayTextToPlayer(Player(1),0,0,"теперь мы знаем что 2+2 = 4")
call DisplayTextToPlayer(Player(2),0,0,"теперь мы знаем что 2+2 = 4")
call DisplayTextToPlayer(Player(3),0,0,"теперь мы знаем что 2+2 = 4")
call DisplayTextToPlayer(Player(4),0,0,"теперь мы знаем что 2+2 = 4")


Views: 3 400

Shown only a small set of comments around the pointed one. Go to actual.

prog #2 - 10 years ago 0
Голосов: +0 / -0
Дык глава то посвящена именно препроцессору) практика будет в следующих двух главах, в основном в последней. В демонстрационной карте точно будет способность на основе БД, описанная во вступлении к руководству, ну и всякой другой фигни по мелочи.
С шаблонами в описании особо заморачиваться не буду пока - там есть несколько проблем, не только потеря шаблонов при импорте обработанного файла строк. Если эти проблемы будут решены, то для шаблонов в описаниях появятся дополнительные возможности и глава, посвященная этим возможностям. Например я хочу ввести локальные переменные, видимые только в описаниях и принимающие значения, актуальные для текущего описания. Это, как минимум, ${this} и ${level}.
ScorpioT1000 #3 - 10 years ago 0
Голосов: +0 / -0
Кароче такое предложение - как выйдет более менее рабочая бета, напиши мне, мы пересоберем jngp experimental и зальем новый =)
prog #4 - 10 years ago 0
Голосов: +0 / -0
Заманчивое предложение. Но это не раньше чем я осилю добавление менюшек через JNGP - у рядовых пользователей должна быть возможность без проблем отключить мою утилиту, не редактируя файлы JNGP вручную. Это не сложно, как мне кажется, но требует времени, которого мне и так не хватает.
ScorpioT1000 #5 - 10 years ago 0
Голосов: +0 / -0
посмотри в scExp.lua там сразу все ясно дб) они если что работают с реестром (состояния)
prog #6 - 10 years ago 0
Голосов: +0 / -0
Ключевой фактор тут время, а не сложность)
Темак #7 - 9 years ago 0
Голосов: +0 / -0
а как передать рав-код юнита?
эта программа по прежнему позволяет передавать только измененные поля?

Shown only a small set of comments around the pointed one. Go to actual.