XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Желтая пресса: обучающие статьи
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

 
NCrashed

offline
Опыт: 13,553
Активность:
Изменение реадктора триггеров
Эта статья является вольным переводом оригинальной статьи с www.wc3jass.com автора Sevion. Очень полезная статья для всех, кто хочет перевести свои системы на GUI.

Введение


World Editor изначально создавался так, чтобы его можно было легко редактировать. Сегодня я расскажу и покажу как добавлять свои команды в редактор триггеров (дальше GUI). Теперь вы сможете использовать родные, вшитые в движок функции, которые называются native, а не богомерзкими функциями из blizzard.j (далее бж). Вместо функции DestroyEffectBJ, которая кроме того как вызывает DestroyEffect ничего не делает, вы сможете напрямую вызывать вторую функцию. Можно привести множество таких примеров, когда функции из бж только вызывают свои аналоги native. Это само по себе не очень опасно, но часто в бж функциях возникают утечки, которые загрязняют память и вызывают тормоза. Теперь вы сможете оптимизировать свой код, не использую jass напрямую! Больше не будет никакого Custom Script! Но однако jass все равно остается более мощным и удобным инструментом. Эта статья поможет вам сделать GUI более мощным для вас. Если вы любите использовать GUI и вам нужно использовать некоторые функции из jass, то это статья написана для вас!

Начало


Теперь, перво-наперво, надо знать где нужно редактировать. Создайте новую папку в директории игры и назовите ее “UI”.

Теперь нам необходимы 3 файла:
UI\TriggerData.txt
UI\TriggerStrings.txt
UI\WorldEditStrings.txt

Их можно вытащить из War3Patch.mpq, или смотри приложение к статье. Положите их в директорию UI. Чтобы изменения в этих файлах вступили в силу, нужно каждый раз после редактирования перезапускать редактор.

Структура TriggerData.txt


Теперь рассмотрим структуру файла TriggerData.txt. Его можно открыть обычным блокнотом.

Весь файл разбит на блоки, которые разделяются строками вида [NameOfBlock], где текст между скобками является именем блока. Рассмотрим назначение каждого блока:

[TriggerCategories] – Категории триггеров, это условное разделение команд на группы. Пример «Юнит», «Спецэффекты», «Отряд» и тп. Все это должно быть знакомо.

[TriggerTypes] – Все типы переменных объявлены здесь. Можно заметить, что здесь намного больше типов, чем мы можем найти в GUI. Это потому что некоторые типы являются служебными, и пользователь не может их создать.

[TriggerTypeDefaults] – Некоторые переменные имеют значения по умолчанию. Например, целочисленные переменные имеют значение 0. Некоторые переменные, вроде таймера, необходимо инициализировать функциями CreateXXX() для правильной работы. Вот здесь и происходит вызов этих функций.
[TriggerParams] - Это заранее заданные значения для переменных, константы, которые могут быть выбраны из выпадающего списка при определении переменной или при выборе аргумента для команды. Например, все способности в GUI и приказы (кроме строковых) являются этими константами.

[TriggerEvents] – Все события триггеров определяются здесь

[TriggerConditions] – Все условия триггеров описываются здесь

[TriggerActions] – Все действия триггеров находятся здесь

[TriggerCalls] – Функции, которые подставляются в аргумент команды. Например, Область – Центр области, Математика - Случайное число.

[DefaultTriggerCategories],[DefaultTriggers] – Всегда когда создается карта, категории триггеров и сами триггеры создаются по умолчанию. Обычно здесь расположен только триггер для инициализации melee карт.

В отличие от TriggerData.txt, который определяет структуру и команды редактора триггеров, остальные два файла, TriggerStrings.txt и WorldEditStrings.txt. Первый определяет весь текст, который вы видите, когда работаете в GUI. Второй является просто списком строк, которым пользуется редактор. Оба файла упрощают локализацию редактора под разные языки. Именно редактирование TriggerStrings.txt позволило некоторым создать “Русские триггеры”, из-за которых иногда очень сложно оказать помощь человеку, потому что некоторые команды неудачно переведены и привычка работать с английскими мешает быстро переориентироваться на русские.

Структура TriggerStrings.txt



[TriggerEventStrings] – Строки всех событий

[TriggerConditionStrings] – Строки всех условий

[TriggerActionStrings] – Строки всех действий

[TriggerCallStrings] – Строки всех функций

[AIFunctionStrings] – Строки для редактора ИИ (логичней было бы их держать в orldEditStrings.txt )

Добавление действий


С форматом данных мы разобрались, теперь самое вкусное: добавим свою функцию в GUI. Открываем файл TriggerData.txt, как мы уже знаем, он разбит на блоки. Мы собираемся добавить функцию удаления точки, так как эту очень нужную функцию близзы нам не дали в GUI. Ищем блок [TriggerActions], дальше ищите записи с DestroyEffect, так как наша и эта функция похожи.

Код:
DestroyEffectBJ=0,effect
_DestroyEffectBJ_Defaults=GetLastCreatedEffectBJ
_DestroyEffectBJ_Category=TC_SPECIALEFFECT


DestroyEffectBJ – это имя нашей функции. (Потом оптимизируем эту функцию, заменив ее на native аналог)

Первое число после равно отвечает за совместимость с дополнением TFT (0-совместима со всеми)

Запятая разделяет параметры.

“effect” – это то что функция берет, аргумент функции. Когда мы уничтожаем спецэффект нам надо указать какой именно мы уничтожаем.

“_DestroyEffectBJ_Defaults=GetLastCreatedEffectBJ” - Эта строка отвечает за значение аргумента по умолчанию, то есть это то что вы увидите только выбрав функцию. Нам не надо добавлять это для нашей функции, так как в GUI нет функции GetLastCreatedLocation.

“_DestroyEffectBJ_Category=TC_SPECIALEFFECT” - Эта строка указывает редактору в какой категории должна находиться функция. Как на этой картинке:

DEAD URL

Теперь по образу и подобию создаем свою функцию:

Код:
RemoveLocation=0,location
_RemoveLocation_Defaults=_
_RemoveLocation_Category=TC_My_Functions

Однако тут есть 1 ошибка. Категории My_Functions не существует. Значит, ищем блок категорий. Каждая категория начинается с “TC_”, сейчас добавим нашу категорию. Ищем строку
Код:
TC_AI=WESTRING_TRIGCAT_AI,ReplaceableTextures\WorldEditUI\Actions-AI

Мы хотим, чтобы наша категория была под категорией искусственного интеллекта, значит добавляем свою категорию сразу после этой.
Код:
TC_My_Functions=WESTRING_TRIGCAT_My_Functions,ReplaceableTextures\WorldEditUI\Ac  tions-SetVariables

После знака равно идет название строки, которую мы должны потом создать в TriggerStrings.txt и которая будет отображаться как название категории, второй параметр является путем к иконке, которая будет отображаться около каждого действия категории.
Теперь отредактируем TriggerStrings.txt.

Ищем блок “[TriggerActionStrings]”. В нем ищем DestroyEffectBJ:
Код:
DestroyEffectBJ="Destroy Special Effect"
DestroyEffectBJ="Destroy ",~Special Effect
DestroyEffectBJHint=

Первая строка – это то что будет отображаться в выпадающем списке после названия категории, то есть название функции. "Special Effect - Destroy Special Effect"
Далее идет DestroyEffectBJ="Destroy ",~Special Effect . Это будет показываться в сером окошке под выпадающем списком. Знак ~ означает, что дальше идет название переменной. Здесь не проверяется ни тип ни существование этой переменной для функции, но редактор при загрузке карты вам об этом с радостью сообщит. Что-то вроде “Ошибка базы данных триггеров, название функции требовалось 3 аргумента, а сообщено 4”. Поэтому советую соблюдать количество аргументов такое, какое оно есть в TriggerData.txt.

Следующая строка отвечает за серую подсказку под основным текстом функции. Например:
Код:
DisableTrigger="Turn Off"
DisableTrigger="Turn off ",~Trigger
DisableTriggerHint="Does not interrupt existing executions of the trigger, but prevents future executions."

DEAD URL

Теперь добавьте где хотите в этом блоке текст:
Код:
RemoveLocatoin="Remove Location"
RemoveLocation="Remove "~Location
RemoveLocationHint=

Отлично! Мы добавили свою функцию!

Создание условия



Теперь ищем блок [TriggerConditions]. Его типичный представитель:
Код:
OperatorCompareAbilityId=1,abilcode,EqualNotEqualOperator,abilcode
_OperatorCompareAbilityId_Defaults=GetSpellAbilityId,OperatorEqualENE,AUan
_OperatorCompareAbilityId_Category=TC_CONDITION

По образу и подобию нашей функции мы разбираем по кусочкам это условие:
В функцию передаются равкод способности, некая переменная, определяющая тип сравнения, и равкод второй способности.
Дальше идут значения по умолчанию и потом категория.
Теперь вставьте в блок наше условие:
Код:
OperatorCompareTrackable=1,trackable,EqualNotEqualOperator,trackable
_OperatorCompareTrackable_Default=_,OperatorEqualENE,_
_OperatorCompareTrackable_Category=TC_CONDITON

И в TriggerStrings в нужном блоке вставляем:

Код:
OperatorCompareTrackable="Trackable Comparison"
OperatorCompareTrackable=~trackable," ",~Operator," ",~trackable
OperatorCompareTrackableHint=


Но опять тут есть ошибка! В GUI нету переменно trackable! Ну так создадим ее.
Ищем в TriggerData.txt “// Trigger Variable Types”
Теперь по образу и подобию остальных переменных создаем свою:
Код:
trackable=1,1,1,WESTRING_TRIGTYPE_trackable

Теперь в WorldEditStrings.txt добавляем:
Код:
WESTRING_TRIGTYPE_trackable="Trackable"


Добавление событий


Также можно обнаружить, что в GUI нет вот таких событий для работы с trackable:
Код:
native TriggerRegisterTrackableHitEvent takes trigger whichTrigger, trackable t returns event
native TriggerRegisterTrackableTrackEvent takes trigger whichTrigger, trackable t returns event

Hit, когда нажимаем на trackable, Track, когда поводим мышкой над ним. Подробнее о trackable вы можете прочитать в соответствующей статье.
Теперь посмотрим на определения событий:
Код:
// Destructible events
TriggerRegisterDeathEvent=0,destructable
_TriggerRegisterDeathEvent_Defaults=_
_TriggerRegisterDeathEvent_Category=TC_DESTRUCT

Первая строка – комментарий, она нам не интересна. Следующая: 0 означает, что это ROC событие; destructable – декорация, которая должна умереть, чтобы вызвать событие.
_TriggerRegisterDeathEvent_Defaults=_ - эта отвечает за значения переменных по умолчанию. Как видно, по умолчанию ничего не стоит.
“_TriggerRegisterDeathEvent_Category=TC_DESTRUCT” Эта строка говорит редактору в какой категории событий разместить это событие.
Теперь мы можем составить наше событие:
Код:
// Trackable events
TriggerRegisterTrackableHitEvent=1,trackable
_TriggerRegisterTrackableHitEvent_Defaults=_
_TriggerRegisterTrackableHitEvent_Category=TC_My_Functions


Теперь экзамен, сделай то же самое для Track события.

Добавление функции


Вроде все есть, действия, событие, переменная. Но нет такой нужной вещи как TriggeringTrackable! Ищем:
Код:
GetTriggerUnit=0,0,unit
_GetTriggerUnit_Defaults=
_GetTriggerUnit_Category=TC_EVENTRESPONSE

Первый нуль отвечает за совместимость
Второе число за использование в событиях: 0-нельзя, 1-можно.
Третий параметр отвечает за возвращаемый тип переменной.
Остальные 2 строки должны быть понятны.
Вот наша функция:
Код:
GetTriggerTrackable=1,0,trackable
_GetTriggerTrackable_Defaults=
_GetTriggerTrackable_Category=TC_EVENTRESPONSE


Немного практики


Теперь добавим действие создания trackable. Используя определение native функции:
Код:
native CreateTrackable takes string trackableModelPath, real x, real y, real facing returns trackable

Получаем:
Код:
CreateTrackable=1,modelfile,real,real,real
_CreateTrackable_Defaults=_,_,_,_,
_CreateTrackable_Category=TC_TRACKABLE


!! Не забывайте добавлять описания функций в TriggerString.txt !!

Теперь, чтобы можно было присвоить переменной значение созданного trackable, скопируйте этот текст в блок [TriggerCalls]:

Код:
CreateTrackable=1,modelfile,real,real,real
_CreateTrackable_Defaults="Abilities\Spells\Other\TalkToMe\TalkToMe.mdl",0,0,RealUnitFacing
_CreateTrackable_Limits=_,_,_,_,_,_,0,360
_CreateTrackable_Category=TC_TRACKABLE

Теперь можно сделать вот так: Set My_Var = CreateTrackable()

ScriptName


У действий есть еще одно очень полезное поле (только у действий, к сожалению): ScriptName. Оно позволяет вам разделить имя jass функции от имени GUI действия. На практике оно оказывается очень полезным по следующим причинам.

Первое преимущество – вы можете давать множество GUI имен для одной и той же функции. Может быть, вы хотите одну функцию, которая обрабатывала как целочисленный тип переменной, так и “unitcode” (далее равкод). В jass, конечно, это сработает без проблем, так как равкод представляет собой целое число, но в GUI это уже не так. Однако с использованием ScriptName вы сможете сделать так, чтобы обе GUI функции ссылались на одну jass функцию.

И самое большое преимущество – это то, что это поле разделяет GUI реализацию скрипта от jass реализации. В GUI вы видите две различные функции, но когда вы сохраняете карту…, вместо них подставляются другие jass функции. Полезно знать, что происходит во время сохранения карты. Сначала все триггеры и остальные GUI структуры сохраняются в отдельный файл внутри карты. Этот файл необходим только редактору, для движка он не нужен (поэтому все протекторы вырезают его). В то же время все триггеры конвертятся в jass-код и сохраняются в главный скрипт карты. Этот файл уже как воздух нужен для нормальной игры, так как помимо всех триггеров там сохраняется информация о всех юнитах, которые должны быть созданы при инициализации карты (это все юниты которые поставили на карту через панель юнитов и тп), о всех регионах, инициализации переменных и стартовых позиций игроков.

Когда вы меняете поле ScriptName, то меняется только jass код, сами GUI триггеры остаются без изменений. Таким образом можно оптимизировать карты даже ни разу не взглянув на их триггеры, просто карта будет скомпилирована по-другому, чем в других экземплярах редактора.

Вот вам самый простой и полезный пример использования. Как я обещал мы оптимизируем функцию DestroyEffectBJ, так как она только вызывает jass функцию DestroyEffect. Изначально она выглядит так:

Код:
DestroyEffectBJ=0,effect
_DestroyEffectBJ_Defaults=GetLastCreatedEffectBJ
_DestroyEffectBJ_Category=TC_SPECIALEFFECT


Теперь нашим хитрым приемом сделаем так, чтобы эта GUI функция сразу вызывала правильный jass аналог:

Код:
DestroyEffectBJ=0,effect
_DestroyEffectBJ_Defaults=GetLastCreatedEffectBJ
_DestroyEffectBJ_Category=TC_SPECIALEFFECT
_DestroyEffectBJ_ScriptName=DestroyEffect

Теперь при сохранении карты вместо DestroyEffectBJ будет стоять DestroyEffect. Причем ваша карта будет открываться в других редакторах, но при сохранении в них бж функция вернется обратно. Одно из главный ограничений ScriptName –можно использовать только те функции, которые имеют то же количество аргументов и их типы, что и оригинал. По загадочной причине порядок аргументов в некоторых бж функциях перевернут относительно оригинала, что не может быть просто устранено ScriptName.

Упражнения



Вот несколько направлений для совершенствования своего редактора триггеров:
  • Добавить region тип и создать GUI функции для работы с ним.
  • Заменить функции, требующие точку как аргумент, на аналогичные с координатами.
  • Найти бж функции-пустышки и оптимизировать их с помощью ScriptName.
  • Порыться в библиотеке функций и добавить полезные к себе.
  • Сделать для своих больших систем GUI оболочку.

На этом я заканчиваю. Надеюсь, что вы увидели как легко изменять редактор триггеров под свои нужды и, если вы это еще не осознали, то, надеюсь, что в один прекрасный день вы поймете, что спор “GUI vs Jass” в корне пропитан идиотизмом.
Прикрепленные файлы
Тип файла: rar TriggerStrings1.24.rar (91.0 Кбайт, 177 просмотров )

Отредактировано NCrashed, 09.11.2009 в 10:21.
Старый 09.11.2009, 00:58
Van Damm
wait... what?
offline
Опыт: 22,268
Активность:
Van Damm добавил:
Плюс к тому, слишком большая картинка
Van Damm добавил:
Не знал только про ScriptName
Старый 09.11.2009, 01:16
NCrashed

offline
Опыт: 13,553
Активность:
Перевод бесполезен, если он пылится на винте. Я их делал много, теперь нахожу и выкладываю. ScriptName очень полезная штука, так как можно написать свой blizzard.j без утечек и прочего уг, а потом только пересохранить карту.

NCrashed добавил:
Картинку вырежу, не информативна
Старый 09.11.2009, 10:20
XOR

offline
Опыт: 38,159
Активность:
Переведено хорошо, но такая статья была.
Старый 09.11.2009, 19:19
KotoBog
Meow
offline
Опыт: 36,046
Активность:
NCrashed:
реадктора триггеров
Реактора триггеров? Прям Чернобыль, блин)
Старый 10.11.2009, 00:04
bee
vjass.optimizer
offline
Опыт: 16,615
Активность:
NCrashed, у меня вопросик, хоть и глупый.
А если я так изменю свой редактор триггеров и с помощью него напису какойнибудь GUI спелл (аш както противно говорить "напишу GUI спелл" XD) и ктото скачает и начнет открывать, то WE не будет кричать на нововведенные фенечьки?
Bee добавил:
+ опечатка в названии темы
Старый 21.11.2009, 06:39
FaB0SS

offline
Опыт: 2,504
Активность:
Bee,
Если пропишешь только ScriptName, то откроется, а если будешь добавлять функции, которые отсутствуют в обычном ВЕ, то будет ругаться.
FaB0SS добавил:
NCrashed,
Спасибо за статью, впервые слышу про ScriptName остальное знал и использовал)
Старый 22.01.2010, 22:38
Kemodonn

offline
Опыт: 1,665
Активность:
NCrashed, спасибо, кое что знал, но массу интересных вещей я узнал.
Старый 27.01.2010, 21:40
Sergant1000

offline
Опыт: 11,308
Активность:
NCrashed, а что дает добавление своих тригеров?
Старый 20.02.2010, 21:11
Nekit1234007

offline
Опыт: 11,916
Активность:
См. Введение Т_Т
Старый 20.02.2010, 21:13
Sergant1000

offline
Опыт: 11,308
Активность:
Nekit1234007, для меня это как жестами обьяснить слепому что это пролетело мимо. Можно в боле нубском варианте.
Старый 21.02.2010, 01:25
Nekit1234007

offline
Опыт: 11,916
Активность:
Что именно не ясно?
Старый 21.02.2010, 01:27
Sergant1000

offline
Опыт: 11,308
Активность:
что это дает?
Старый 21.02.2010, 03:38
bee
vjass.optimizer
offline
Опыт: 16,615
Активность:
вместо того чтобы прописывать все время самому код
можно выбирать из списка грубо говоря

Bee добавил:
прибавляет удобств
Старый 21.02.2010, 20:57
Sergant1000

offline
Опыт: 11,308
Активность:
А можно пример кода, и что он делает или для чего он нужен. Просто думаю стоит его включать в проект или нет.
Старый 21.02.2010, 22:14
St John

offline
Опыт: 156
Активность:
Полезная статья.
Скоро появятся всевозможные навороты и оптимизации гуи.
Sergant1000 код ты пишешь сам, это для ускорения работы в гуи, чтобы не писать однотипные блоки, ты просто их переводишь в гуи команды следуя статье.
Старый 21.02.2010, 22:44
bee
vjass.optimizer
offline
Опыт: 16,615
Активность:
Цитата:
А можно пример кода, и что он делает или для чего он нужен. Просто думаю стоит его включать в проект или нет.

первый пост полностью прочитай и отпадет желание флудить.
на проект это никак не повлиет. т.к. это изменяет всеголиш настройки WE.
игру это не изменит.
Старый 21.02.2010, 23:00
XOR

offline
Опыт: 38,159
Активность:
В любом случае сами системы делаются сразу, а лишь потом добавляются специяльно для него действия в гуи что очень не удобно да и нужно лишь нубам новичкам
Старый 21.02.2010, 23:06
Death Master

offline
Опыт: 782
Активность:
Открыл америку, я это уже год знаю, но для новичков пригодится.
Старый 22.02.2010, 02:10

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 04:36.