Эта статья будет посвящена, не столь распространенной, теме - Пользовательских подфункций (Sub-Functions), и возможно вы вообще о такой возможности редактора и не слышали. Да что уж там, я сам об этом не так давно узнал и был мягко говоря приятно удивлен этому.
Подфункции - это
продвинутый механизм в редакторе карт StarCraft 2, позволяющий создавать пользовательские конструкции управления потоком выполнения кода. По сути, это инструмент для определения собственных управляющих структур, аналогичных встроенным циклам и условным операторам (таких как If Then Else, Switch и прочих).
Как создать свою собственную подфункцию?
Описание примера
Мы создадим конструктор, который будет перебирать слова в строке подобно тому как работает Pick Each Integer, с возможностью на каждой итерации получить перебираемое слово
Подфункция это обычная функция, но с флагом Sub-Functionв разделе Options. После активации этого флага, вы заметите что строка Actions, в которой добавляются действия заменится на что-то непонятное. Там вы сможете добавлять свои подобные разделы, в которых уже из триггера (или другой функции) сможете назначить разные другие действия или условия.
- Создадим действие For Each Word In Strings
- Далее добавим параметр String (Просто нажмите по полю выделив его и нажмите Ctrl - W), А также добавим новую подфункцию, выбрав поле Sub-Function Types и нажав на Ctrl - W
- Теперь нужно слегка поработать с кодом Galaxy в Custom Script Code.
Вставьте этот код в поле - Custom Script Code
Что делает каждая строка?
#AUTOVAR(s,string) = #PARAM(string);
Создаёт автоматическую переменную со стартовым значением заданным в нашем параметре строки
#PARAM(string)
Получение значения из, переданного в функцию, параметра по его идентификатору.
#AUTOVAR(len) = StringLength(#PARAM(string));
Создает авто-переменную с информацией о длине нашей строки
for (;;#AUTOVAR(len) -= 1)
{
. . .
}
Цикл, итерирующийся столько раз, сколько длина строки
#AUTOVAR(word,string) = StringWord(#PARAM(string),#AUTOVAR(curIndex));
Получаем текущее перебираемое слово
#SUBFUNCS(Actions)
Стартуем действия, которые будут добавлены для нашего цикла в самом триггере
Первый итог
Теперь мы уже сможем добавить наш собственный цикл в любой триггер! и даже сможем добавить в него некоторые действия, которые он выполнит на каждое слово строки
Так а как же получить то перебираемое слово?
Если мы посмотрим на существующих примерах таких как встроенных Picked Integer, Picked Unit, Picked Player. То увидим следующую подобную строку
Код из картинки
#INITAUTOVAR(ae,e)
#AUTOVAR(var) = #PARAM(s);
for ( ; #AUTOVAR(var) <= #AUTOVAR(ae); #AUTOVAR(var) += 1 ) {
#SUBFUNCS(actions)
}
Стандартный цикл "Pick Each Integer", в котором объявляется счётчик
#AUTOVAR(var,ancestor:PickEachInteger)
Получение доступа к счётчику из цикла с помощью функции Picked Integer
Но похоже это нормально не работает. По крайней мере ни один моддер так и не сумел заставить это работать, а если кто-то и сумел, то никому не рассказал как это сделать.
Что же делать?
Есть и другой вариант. Можно использовать "Локальные Таблицы данных" Data Table.
Что такое локальные таблицы данных?
Таблица данных - это структура для хранения данных в формате ключ-значение и существует глобально на всё время игры. Локальная таблица данных в свою очередь может создаваться для каждого триггера отдельно и очищаться после окончания действия триггера,
Добавим эту функцию под присваивание текущего слова в переменную #AUTOVAR(word)
DataTableSetString(false,"ForEachWordInStrings",#AUTOVAR(word));
for (;;#AUTOVAR(len) -= 1)
{
#AUTOVAR(word,string) = StringWord(#PARAM(string),#AUTOVAR(curIndex));
DataTableSetString(false,"ForEachWordInStrings",#AUTOVAR(word)); // Вот она
#AUTOVAR(curIndex) += 1;
if (#AUTOVAR(word) == "") { break; }
#SUBFUNCS(Actions)
}
Эта функция сохранит в локальную таблицу данных текущее перебираемое слово по ключу ForEachWordInStrings (Не обязательно должен быть именно такой ключ, главное чтобы в будущей функции получения слова был такой же ключ что указан здесь).
ВАЖНО. Лучше подбирайте такой ключ, который будет наименее используемым, чтобы не возникало конфликтов на случай если в триггере вдруг будет использоваться данное название ключа для чего-то ещё.
ВАЖНО. Лучше подбирайте такой ключ, который будет наименее используемым, чтобы не возникало конфликтов на случай если в триггере вдруг будет использоваться данное название ключа для чего-то ещё.
Зачем нам сохранять слово по ключу?
Ключ для таблицы данных нужен для того, чтобы потом по нему можно было получить нужное нам ранее записанное значение, с помощью другой функции
Теперь создадим функцию получения слова
Добавим новую функцию кликнув ПКМ по пустому месту списка триггеров и выбрав в меню New - New Function. Назовём его Picked Word
В качестве Возвращаемого значения Return Type, укажем String.
И после добавим ровно одно действие Return. В его значение укажем функцию Value From Data Table (String), она то нам как раз и вернёт слово записанное в локальной таблице данных по ключу.
И после добавим ровно одно действие Return. В его значение укажем функцию Value From Data Table (String), она то нам как раз и вернёт слово записанное в локальной таблице данных по ключу.
У него есть два поля:
- Name - Строковый параметр, определяющий ключ таблицы данных. В него мы должны вписать тот же ключ что и ранее, например ForEachWordInStrings
- Scope - Это область видимости таблицы данных Глобальная/локальная. Нам нужно выбрать локальная.
Финал
Осталось проверить.
В уже имеющимся триггере у нас есть наш добавленный цикл и создана локальная переменная.
Переменную можно убрать как и действие Modify Variable (Integer). А в текстовый параметр действия Text Message, можно выбрать функцию конвертации строки в текст Convert String To Text и в нём в качестве строки указать нашу функцию Picked Word
В уже имеющимся триггере у нас есть наш добавленный цикл и создана локальная переменная.
Переменную можно убрать как и действие Modify Variable (Integer). А в текстовый параметр действия Text Message, можно выбрать функцию конвертации строки в текст Convert String To Text и в нём в качестве строки указать нашу функцию Picked Word