Настройка окружения для AS3-мода (с графической частью)
Моды с графической частью пишутся на AS3 (ActionScript 3) и компилируются в единый SWF‑файл, в одном таком файле может находиться несколько скриптов, картинки, анимации и шрифты. У одного мода может быть несколько SWF‑файлов. Например, один SWF отвечает за всплывающее окно, а другой — за индикатор на экране.
Чисто AS3‑моды возможны, однако в большинстве случаев вам понадобится вспомогательный Python‑скрипт, который будет взаимодействовать с игрой и управлять графической частью мода.
Поэтому подразумевается, что у вас уже настроено окружение для Python‑модов. Если это не так, сначала настройте его, следуя инструкции по настройке окружения для Python.
Необходимые инструменты
- Полностью настроенное окружение для
Python‑модов (см. инструкцию по настройке окружения для Python) - ActionScript & MXML – расширение для VSCode, которое добавляет поддержку ActionScript
- Java JDK 11+ – последняя версия
JDK, необходима для работы расширения AIRSDK– набор инструментов для компиляцииAS3, необходим для работы расширения. Устанавливается через AIR SDK Manager
- Java JDK 11+ – последняя версия
- Apache Royale – компилятор
AS3вSWF. Нужно скачать архивAPACHE ROYALE JS/SWFс официального сайта и распаковать его в удобное место на диске, напримерC:\apache-royale.
Важно
При загрузке Apache Royale не перепутайте версии JS-ONLY и JS/SWF, необходима именно версия с JS/SWF.
Организация проекта
Мы расширим структуру проекта, описанную в инструкции по настройке окружения для Python. AS3‑часть мода полностью независима от Python‑части, поэтому её исходный код не нужно помещать в папку res. Создайте в корне проекта папку as3, в которой разместим папки:
src/my/first_mod– корневая папка вашегоAS3‑мода, в которой будет находиться весь исходный код.libs– здесь будут находиться сторонние библиотеки, которые понадобятся для компиляцииbin– здесь будет находиться скомпилированный файлSWF
Также скачайте конфигурационный файл asconfig.json, в котором указаны настройки для расширения, и build-config.xml с настройками компиляции SWF.
Создайте пустой файл build.bat, который будет запускать компиляцию, его мы заполним позже.
my-first-mod/
└── as3/
├── bin/
├── libs/
│ └── ... (сторонние библиотеки)
├── src/
│ └── my/
│ └── first_mod/
│ └── ... (исходный код AS3 мода)
├── build-config.xml
├── asconfig.json
└── build.batБиблиотеки игры SWC
Для того, чтобы мод мог взаимодействовать с компонентами игры, необходимо подключить к проекту внешние библиотеки игры в формате SWC.
Эти библиотеки поставляются вместе с игрой и находятся в пакетах res/packages/gui-part.pkg/gui/flash/swc относительно корня игры. Формат .pkg нужно открыть с помощью архиватора, например 7-Zip.
Важно
Пакет gui-part разбит на два отдельных архива: gui-part1.pkg и gui-part2.pkg; часть нужных библиотек находится в первом, часть — во втором.
Перенесите эти SWC‑файлы в папку с модом as3/libs/. Должно получиться 11 файлов:
base_app-1.0-SNAPSHOT.swcbattle.swccommon_i18n_library-1.0-SNAPSHOT.swccommon-1.0-SNAPSHOT.swcgui_base-1.0-SNAPSHOT.swcgui_battle-1.0-SNAPSHOT.swcgui_lobby-1.0-SNAPSHOT.swclobby.swcdamageIndicator.swc(на самом деле не используется, можно не добавлять)directionIndicator.swc(на самом деле не используется, можно не добавлять)predictionIndicator.swc(на самом деле не используется, можно не добавлять)
В дополнение к игровым библиотекам вам необходима ещё основная библиотека playerglobal.swc. Скачайте её и поместите в папку as3/libs/.
Если вы добавляете
damageIndicator.swc,directionIndicator.swcилиpredictionIndicator.swc, не забудьте добавить их в конфигурационные файлыbuild-config.xmlиasconfig.jsonпо аналогии с другими библиотеками.
Скрипт сборки
Заполните файл as3/build.bat следующим содержимым:
@echo off
rem ==== настройки ====
set "MXML_PATH=C:\apache-royale"
rem ==== компиляция ====
set "MXMLC=%MXML_PATH%\royale-asjs\bin\mxmlc"
call "%MXMLC%" -load-config+=build-config.xml --output=bin/my.first_mod.HelloWorldWindow.swf src/my/first_mod/HelloWorldWindow.asНа 4-й строке укажите путь к папке, в которую распаковали Apache Royale.
На 9-й строке команда, с помощью которой мы компилируем SWF:
-load-config+=build-config.xml– указывает файл с настройками компиляции--output=bin/my.first_mod.swf– путь к выходномуSWF‑файлуsrc/my/first_mod/HelloWorldWindow.as– файл с исходным кодом, с которого начинается компиляция (точка входа)
Если вам в модификации понадобится несколько SWF‑файлов, просто добавьте в build.bat ещё одну команду для компиляции с другими параметрами.
Обновление основного скрипта сборки
Обновление основного скрипта не требуется, если вы настроили по инструкции окружение для Python, то можете убедиться, что там есть блок, который запускает as3/build.bat, если он присутствует в проекте:
if exist ".\as3\build.bat" (
pushd ".\as3"
del /Q /F ".\bin\*.swf"
call build.bat
xcopy ".\bin\*.swf" "..\build\res\gui\flash\" /Y /I >nul
popd
)Подготовка тестового мода
Для проверки работоспособности отобразим в ангаре игровое окно.
Создадим в папке as3/src/my/first_mod/ файл HelloWorldWindow.as со следующим содержимым:
package my.first_mod
{
import net.wg.infrastructure.base.AbstractWindowView;
import flash.text.TextField;
public class HelloWorldWindow extends AbstractWindowView
{
public function HelloWorldWindow()
{
super();
}
override protected function onPopulate():void
{
super.onPopulate();
width = 400;
height = 100;
window.title = 'My First Mod Window';
window.useBottomBtns = false;
var text:TextField = new TextField();
text.width = 384;
text.height = 84;
text.x = 8;
text.y = 8;
text.htmlText = "<font face='$FieldFont' size='14' color='#8C8C7E'>Мод работает! Ура!</font>";
addChild(text);
}
}
}Аналогично с Python у вас должны работать всплывающие подсказки по наведению мыши: 
И автодополнение по нажатию . (точка): 
Если расширение
ActionScript & MXMLне работает и вызывает ошибкуas3mxml.java.path in settings does not point to a valid executable, то необходимо проверить правильность установкиJava JDK, и убедиться, что он указан вPATH.
Отображение окна из Python
Чтобы окно появилось в игре, нужно из Python‑скрипта добавить его на экран. Для этого создадим управляющий Python‑класс (подробнее в теории AS3).
Создайте файл res/scripts/client/gui/mods/my_first_mod/HelloWorldWindow.py со следующим содержимым:
from frameworks.wulf.gui_constants import WindowLayer
from gui.Scaleform.framework.entities.abstract.AbstractWindowView import AbstractWindowView
from gui.Scaleform.framework import g_entitiesFactories, ScopeTemplates, ViewSettings
from gui.Scaleform.framework.managers.loaders import SFViewLoadParams
from helpers import dependency
from skeletons.gui.app_loader import IAppLoader
from gui.Scaleform.framework.application import AppEntry
class HelloWorldWindow(AbstractWindowView):
def onWindowClose(self):
self.destroy()
HELLO_WORLD_WINDOW = "MY_MOD_HELLO_WORLD_WINDOW"
def setup():
settingsViewSettings = ViewSettings(
HELLO_WORLD_WINDOW,
HelloWorldWindow,
"my.first_mod.HelloWorldWindow.swf",
WindowLayer.TOP_WINDOW,
None,
ScopeTemplates.VIEW_SCOPE,
)
g_entitiesFactories.addSettings(settingsViewSettings)
def show():
appLoader = dependency.instance(IAppLoader) # type: IAppLoader
app = appLoader.getApp() # type: AppEntry
app.loadView(SFViewLoadParams(HELLO_WORLD_WINDOW))Функция setup() регистрирует SWF‑файл в системе, а функция show() отображает окно в интерфейсе.
В основном файле вашего мода (res/scripts/client/gui/mods/mod_myFirstMod.py) добавьте следующий код:
from gui import SystemMessages
from helpers import dependency
from skeletons.gui.shared.utils import IHangarSpace
from .my_first_mod.HelloWorldWindow import setup, show
MOD_VERSION = '{{VERSION}}'
# получаем ссылку на IHangarSpace
hangarSpace = dependency.instance(IHangarSpace) # type: IHangarSpace
# Мод загрузился
def init():
print("[MY_FIRST_MOD] Hello, World! Mod version is %s" % MOD_VERSION)
# Регистрируем SWF файл
setup()
# Подписываемся на загрузку ангара
hangarSpace.onSpaceCreate += onHangarSpaceCreate
def onHangarSpaceCreate():
# Отписываемся от загрузки ангара
hangarSpace.onSpaceCreate -= onHangarSpaceCreate
# Выводим уведомление в ангаре
SystemMessages.pushMessage(
text='Привет мир! Версия мода: %s' % MOD_VERSION,
type=SystemMessages.SM_TYPE.InformationHeader,
messageData={ 'header': 'MY_FIRST_MOD' }
)
# Отображаем окно в интерфейсе
show() Проверочный запуск
Скомпилируйте мод с помощью build.bat из корня проекта:
build.bat -v 1.1.0Обратите внимание
Должна использоваться оболочка CMD. Если у вас используется PowerShell, переключитесь на CMD, нажав на стрелочку рядом с кнопкой + в окне терминала и выбрав Command Prompt.
В случае успешной компиляции вы увидите следующий вывод: 
А так же файл мода my.first-mod_1.1.0.mtmod, перенесите его в папку с игрой /mods/<актуальная версия игры>/. И запустите игру.
После загрузки ангара вы увидите своё первое графическое окно 🎉

Итоговая структура проекта
В результате, после выполнения всех шагов, структура вашего проекта должна выглядеть так:
my-first-mod/
├── .vscode
│ └── settings.json
├── wot-src
│ └── ... (исходный код игры)
├── build.bat
├── meta.xml
├── as3/
│ ├── bin/
│ ├── libs/
│ │ └── ... (.swc библиотеки игры 11 штук + playerglobal.swc)
│ ├── src/
│ │ └── my/
│ │ └── first_mod/
│ │ └── HelloWorldWindow.as
│ ├── build-config.xml
│ ├── asconfig.json
│ └── build.bat
└── res
└── scripts
└── client
└── gui
└── mods
├── mod_myFirstMod.py
└── my_first_mod
├── __init__.py
└── HelloWorldWindow.pyТеперь на основе этого тестового проекта вы можете создавать свои моды как с графической частью, так и без.
Советы
- У ActionScript есть автоформатирование, рекомендуется включить в настройках VSCode опцию
Editor: Format On Save(Форматировать при сохранении)
Andrei Soprachev
Yuratos
Kurzdor