Глава 5.2: inputs.xml --- Пользовательские клавиши
Главная | << Предыдущая: stringtable.csv | inputs.xml | Следующая: Credits.json >>
Краткое описание: Файл
inputs.xmlпозволяет вашему моду регистрировать пользовательские назначения клавиш, которые отображаются в меню настроек управления игрока. Игроки могут просматривать, переназначать и переключать эти привязки так же, как и стандартные действия. Это стандартный механизм для добавления горячих клавиш в моды DayZ.
Содержание
- Обзор
- Расположение файла
- Полная структура XML
- Блок Actions
- Блок Sorting
- Блок Preset (привязки по умолчанию)
- Комбинации с модификаторами
- Скрытые привязки
- Несколько клавиш по умолчанию
- Доступ к привязкам из скрипта
- Справочник по методам ввода
- Подавление и отключение ввода
- Справочник имён клавиш
- Реальные примеры
- Распространённые ошибки
Обзор
Когда вашему моду нужно, чтобы игрок нажал клавишу --- открыть меню, переключить функцию, отдать команду AI-юниту --- вы регистрируете пользовательское действие ввода в inputs.xml. Движок считывает этот файл при запуске и интегрирует ваши действия в единую систему ввода. Игроки видят ваши назначения клавиш в игровом меню Настройки > Управление, сгруппированные под заголовком, который вы определяете.
Пользовательские привязки идентифицируются уникальным именем действия (по соглашению с префиксом UA от «User Action») и могут иметь привязки по умолчанию, которые игроки могут переназначить по желанию.
Расположение файла
Поместите inputs.xml в подпапку data вашей директории Scripts:
@MyMod/
Addons/
MyMod_Scripts.pbo
Scripts/
data/
inputs.xml <-- Здесь
3_Game/
4_World/
5_Mission/Некоторые моды размещают его прямо в папке Scripts/. Оба расположения работают. Движок обнаруживает файл автоматически --- регистрация в config.cpp не требуется.
Полная структура XML
Файл inputs.xml состоит из трёх секций, обёрнутых в корневой элемент <modded_inputs>:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<modded_inputs>
<inputs>
<actions>
<!-- Определения действий размещаются здесь -->
</actions>
<sorting name="mymod" loc="STR_MYMOD_INPUT_GROUP">
<!-- Порядок сортировки для меню настроек -->
</sorting>
</inputs>
<preset>
<!-- Назначения клавиш по умолчанию размещаются здесь -->
</preset>
</modded_inputs>Все три секции --- <actions>, <sorting> и <preset> --- работают вместе, но служат разным целям.
Блок Actions
Блок <actions> объявляет каждое действие ввода, которое предоставляет ваш мод. Каждое действие --- это один элемент <input>.
Синтаксис
<actions>
<input name="UAMyModOpenMenu" loc="STR_MYMOD_INPUT_OPEN_MENU" />
<input name="UAMyModToggleHUD" loc="STR_MYMOD_INPUT_TOGGLE_HUD" />
</actions>Атрибуты
| Атрибут | Обязателен | Описание |
|---|---|---|
name | Да | Уникальный идентификатор действия. Соглашение: префикс UA (User Action). Используется в скриптах для опроса этого ввода. |
loc | Нет | Ключ stringtable для отображаемого имени в меню Управление. Без префикса # --- система добавляет его сама. |
visible | Нет | Установите "false", чтобы скрыть из меню Управление. По умолчанию true. |
Соглашение об именовании
Имена действий должны быть глобально уникальными среди всех загруженных модов. Используйте префикс вашего мода:
<input name="UAMyModAdminPanel" loc="STR_MYMOD_INPUT_ADMIN_PANEL" />
<input name="UAExpansionBookToggle" loc="STR_EXPANSION_BOOK_TOGGLE" />
<input name="eAICommandMenu" loc="STR_EXPANSION_AI_COMMAND_MENU" />Префикс UA является соглашением, но не обязателен. Expansion AI использует eAI в качестве префикса, что тоже работает.
Блок Sorting
Блок <sorting> управляет тем, как ваши привязки отображаются в настройках Управления. Он определяет именованную группу (которая становится заголовком секции) и перечисляет привязки в порядке отображения.
Синтаксис
<sorting name="mymod" loc="STR_MYMOD_INPUT_GROUP">
<input name="UAMyModOpenMenu" />
<input name="UAMyModToggleHUD" />
<input name="UAMyModSpecialAction" />
</sorting>Атрибуты
| Атрибут | Обязателен | Описание |
|---|---|---|
name | Да | Внутренний идентификатор этой группы сортировки |
loc | Да | Ключ stringtable для заголовка группы, отображаемого в Настройки > Управление |
Как это выглядит
В настройках Управления игрок видит:
[MyMod] <-- из loc блока sorting
Open Menu .............. [Y] <-- из loc привязки + preset
Toggle HUD ............. [H] <-- из loc привязки + presetВ меню настроек отображаются только привязки, перечисленные в блоке <sorting>. Привязки, определённые в <actions>, но не указанные в <sorting>, молча регистрируются, но невидимы для игрока (даже если visible не установлен явно в false).
Блок Preset (привязки по умолчанию)
Блок <preset> назначает клавиши по умолчанию для ваших действий. Это клавиши, с которых игрок начинает до любой настройки.
Простая привязка клавиши
<preset>
<input name="UAMyModOpenMenu">
<btn name="kY"/>
</input>
</preset>Это привязывает клавишу Y по умолчанию для UAMyModOpenMenu.
Без клавиши по умолчанию
Если вы не включите действие в блок <preset>, у него не будет привязки по умолчанию. Игрок должен будет вручную назначить клавишу в Настройки > Управление. Это уместно для необязательных или продвинутых привязок.
Комбинации с модификаторами
Чтобы потребовать клавишу-модификатор (Ctrl, Shift, Alt), вложите элементы <btn>:
Ctrl + Левая кнопка мыши
<input name="eAISetWaypoint">
<btn name="kLControl">
<btn name="mBLeft"/>
</btn>
</input>Внешний <btn> --- это модификатор; внутренний <btn> --- это основная клавиша. Игрок должен удерживать модификатор и затем нажать основную клавишу.
Shift + Клавиша
<input name="UAMyModQuickAction">
<btn name="kLShift">
<btn name="kQ"/>
</btn>
</input>Правила вложенности
- Внешний
<btn>всегда является модификатором (удерживается) - Внутренний
<btn>является триггером (нажимается при удержании модификатора) - Обычно используется только один уровень вложенности; более глубокая вложенность не протестирована и не рекомендуется
Скрытые привязки
Используйте visible="false", чтобы зарегистрировать привязку, которую игрок не может видеть или переназначить в меню Управление. Это полезно для внутренних привязок, используемых кодом вашего мода, которые не должны настраиваться игроком.
<actions>
<input name="eAITestInput" visible="false" />
<input name="UAExpansionConfirm" loc="" visible="false" />
</actions>Скрытые привязки всё равно могут иметь назначения клавиш по умолчанию в блоке <preset>:
<preset>
<input name="eAITestInput">
<btn name="kY"/>
</input>
</preset>Несколько клавиш по умолчанию
Действие может иметь несколько клавиш по умолчанию. Перечислите несколько элементов <btn> как соседние:
<input name="UAExpansionConfirm">
<btn name="kReturn" />
<btn name="kNumpadEnter" />
</input>И Enter, и Numpad Enter будут вызывать UAExpansionConfirm. Это полезно для действий, где несколько физических клавиш должны соответствовать одному логическому действию.
Доступ к привязкам из скрипта
Получение API ввода
Весь доступ к вводу идёт через GetUApi(), который возвращает глобальный API пользовательских действий:
UAInput input = GetUApi().GetInputByName("UAMyModOpenMenu");Опрос в OnUpdate
Пользовательские привязки обычно опрашиваются в MissionGameplay.OnUpdate() или аналогичных покадровых обратных вызовах:
modded class MissionGameplay
{
override void OnUpdate(float timeslice)
{
super.OnUpdate(timeslice);
UAInput input = GetUApi().GetInputByName("UAMyModOpenMenu");
if (input.LocalPress())
{
// Клавиша была нажата в этом кадре
OpenMyModMenu();
}
}
}Альтернатива: использование имени привязки напрямую
Многие моды проверяют ввод инлайн, используя методы UAInputAPI со строковыми именами:
override void OnUpdate(float timeslice)
{
super.OnUpdate(timeslice);
Input input = GetGame().GetInput();
if (input.LocalPress("UAMyModOpenMenu", false))
{
OpenMyModMenu();
}
}Параметр false в LocalPress("name", false) указывает, что проверка не должна поглощать событие ввода.
Справочник по методам ввода
Получив ссылку на UAInput (через GetUApi().GetInputByName()) или используя класс Input напрямую, эти методы определяют различные состояния ввода:
| Метод | Возвращает | Когда true |
|---|---|---|
LocalPress() | bool | Клавиша была нажата в этом кадре (однократное срабатывание при нажатии) |
LocalRelease() | bool | Клавиша была отпущена в этом кадре (однократное срабатывание при отпускании) |
LocalClick() | bool | Клавиша была нажата и быстро отпущена (тап) |
LocalHold() | bool | Клавиша удерживается в течение пороговой длительности |
LocalDoubleClick() | bool | Клавиша была нажата дважды быстро |
LocalValue() | float | Текущее аналоговое значение (0.0 или 1.0 для цифровых клавиш; переменное для аналоговых осей) |
Паттерны использования
Переключение по нажатию:
if (input.LocalPress("UAMyModToggle", false))
{
m_IsEnabled = !m_IsEnabled;
}Удержание для активации, отпускание для деактивации:
if (input.LocalPress("eAICommandMenu", false))
{
ShowCommandWheel();
}
if (input.LocalRelease("eAICommandMenu", false) || input.LocalValue("eAICommandMenu", false) == 0)
{
HideCommandWheel();
}Действие по двойному нажатию:
if (input.LocalDoubleClick("UAMyModSpecial", false))
{
PerformSpecialAction();
}Удержание для длительного действия:
if (input.LocalHold("UAExpansionGPSToggle"))
{
ToggleGPSMode();
}Подавление и отключение ввода
ForceDisable
Временно отключает конкретную привязку. Обычно используется при открытии меню для предотвращения срабатывания игровых действий, пока активен UI:
// Отключить ввод, пока меню открыто
GetUApi().GetInputByName("UAMyModToggle").ForceDisable(true);
// Включить обратно при закрытии меню
GetUApi().GetInputByName("UAMyModToggle").ForceDisable(false);SupressNextFrame
Подавляет всю обработку ввода на следующий кадр. Используется при переходах контекста ввода (например, закрытие меню) для предотвращения однокадрового «пробоя» ввода:
GetUApi().SupressNextFrame(true);UpdateControls
После изменения состояний ввода вызовите UpdateControls(), чтобы применить изменения немедленно:
GetUApi().GetInputByName("UAExpansionBookToggle").ForceDisable(false);
GetUApi().UpdateControls();Исключения ввода
Стандартная система миссий предоставляет группы исключений. Когда меню активно, вы можете исключить категории ввода:
// Подавить игровой ввод, пока инвентарь открыт
AddActiveInputExcludes({"inventory"});
// Восстановить при закрытии
RemoveActiveInputExcludes({"inventory"});Справочник имён клавиш
Имена клавиш, используемые в атрибуте <btn name="">, следуют определённому соглашению об именовании. Ниже приведён полный справочник.
Клавиши клавиатуры
| Категория | Имена клавиш |
|---|---|
| Буквы | kA, kB, kC, kD, kE, kF, kG, kH, kI, kJ, kK, kL, kM, kN, kO, kP, kQ, kR, kS, kT, kU, kV, kW, kX, kY, kZ |
| Цифры (верхний ряд) | k0, k1, k2, k3, k4, k5, k6, k7, k8, k9 |
| Функциональные клавиши | kF1, kF2, kF3, kF4, kF5, kF6, kF7, kF8, kF9, kF10, kF11, kF12 |
| Модификаторы | kLControl, kRControl, kLShift, kRShift, kLAlt, kRAlt |
| Навигация | kUp, kDown, kLeft, kRight, kHome, kEnd, kPageUp, kPageDown |
| Редактирование | kReturn, kBackspace, kDelete, kInsert, kSpace, kTab, kEscape |
| Цифровая клавиатура | kNumpad0 ... kNumpad9, kNumpadEnter, kNumpadPlus, kNumpadMinus, kNumpadMultiply, kNumpadDivide, kNumpadDecimal |
| Пунктуация | kMinus, kEquals, kLBracket, kRBracket, kBackslash, kSemicolon, kApostrophe, kComma, kPeriod, kSlash, kGrave |
| Блокировки | kCapsLock, kNumLock, kScrollLock |
Кнопки мыши
| Имя | Кнопка |
|---|---|
mBLeft | Левая кнопка мыши |
mBRight | Правая кнопка мыши |
mBMiddle | Средняя кнопка мыши (нажатие колеса прокрутки) |
mBExtra1 | Кнопка мыши 4 (боковая кнопка назад) |
mBExtra2 | Кнопка мыши 5 (боковая кнопка вперёд) |
Оси мыши
| Имя | Ось |
|---|---|
mAxisX | Горизонтальное перемещение мыши |
mAxisY | Вертикальное перемещение мыши |
mWheelUp | Прокрутка колеса вверх |
mWheelDown | Прокрутка колеса вниз |
Паттерн именования
- Клавиатура: префикс
k+ имя клавиши (например,kT,kF5,kLControl) - Кнопки мыши: префикс
mB+ имя кнопки (например,mBLeft,mBRight) - Оси мыши: префикс
m+ имя оси (например,mAxisX,mWheelUp)
Реальные примеры
DayZ Expansion AI
Хорошо структурированный inputs.xml с видимыми назначениями клавиш, скрытыми отладочными привязками и комбинациями с модификаторами:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<modded_inputs>
<inputs>
<actions>
<input name="eAICommandMenu" loc="STR_EXPANSION_AI_COMMAND_MENU"/>
<input name="eAISetWaypoint" loc="STR_EXPANSION_AI_SET_WAYPOINT"/>
<input name="eAITestInput" visible="false" />
<input name="eAITestLRIncrease" visible="false" />
<input name="eAITestLRDecrease" visible="false" />
<input name="eAITestUDIncrease" visible="false" />
<input name="eAITestUDDecrease" visible="false" />
</actions>
<sorting name="expansion" loc="STR_EXPANSION_LABEL">
<input name="eAICommandMenu" />
<input name="eAISetWaypoint" />
<input name="eAITestInput" />
<input name="eAITestLRIncrease" />
<input name="eAITestLRDecrease" />
<input name="eAITestUDIncrease" />
<input name="eAITestUDDecrease" />
</sorting>
</inputs>
<preset>
<input name="eAICommandMenu">
<btn name="kT"/>
</input>
<input name="eAISetWaypoint">
<btn name="kLControl">
<btn name="mBLeft"/>
</btn>
</input>
<input name="eAITestInput">
<btn name="kY"/>
</input>
<input name="eAITestLRIncrease">
<btn name="kRight"/>
</input>
<input name="eAITestLRDecrease">
<btn name="kLeft"/>
</input>
<input name="eAITestUDIncrease">
<btn name="kUp"/>
</input>
<input name="eAITestUDDecrease">
<btn name="kDown"/>
</input>
</preset>
</modded_inputs>Ключевые наблюдения:
eAICommandMenuпривязан кT--- виден в настройках, игрок может переназначитьeAISetWaypointиспользует комбинацию Ctrl + Левый клик с модификатором- Тестовые привязки имеют
visible="false"--- скрыты от игроков, но доступны в коде
DayZ Expansion Market
Минимальный inputs.xml для скрытой служебной привязки с несколькими клавишами по умолчанию:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<modded_inputs>
<inputs>
<actions>
<input name="UAExpansionConfirm" loc="" visible="false" />
</actions>
</inputs>
<preset>
<input name="UAExpansionConfirm">
<btn name="kReturn" />
<btn name="kNumpadEnter" />
</input>
</preset>
</modded_inputs>Ключевые наблюдения:
- Скрытая привязка (
visible="false") с пустымloc--- никогда не показывается в настройках - Две клавиши по умолчанию: и Enter, и Numpad Enter вызывают одно и то же действие
- Блок
<sorting>отсутствует --- не нужен, поскольку привязка скрыта
Полный начальный шаблон
Минимальный, но полный шаблон для нового мода:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<modded_inputs>
<inputs>
<actions>
<input name="UAMyModOpenMenu" loc="STR_MYMOD_INPUT_OPEN_MENU" />
<input name="UAMyModQuickAction" loc="STR_MYMOD_INPUT_QUICK_ACTION" />
</actions>
<sorting name="mymod" loc="STR_MYMOD_INPUT_GROUP">
<input name="UAMyModOpenMenu" />
<input name="UAMyModQuickAction" />
</sorting>
</inputs>
<preset>
<input name="UAMyModOpenMenu">
<btn name="kF6"/>
</input>
<!-- UAMyModQuickAction не имеет клавиши по умолчанию; игрок должен назначить -->
</preset>
</modded_inputs>С соответствующим stringtable.csv:
"Language","original","english"
"STR_MYMOD_INPUT_GROUP","My Mod","My Mod"
"STR_MYMOD_INPUT_OPEN_MENU","Open Menu","Open Menu"
"STR_MYMOD_INPUT_QUICK_ACTION","Quick Action","Quick Action"Распространённые ошибки
Использование # в атрибуте loc
<!-- НЕПРАВИЛЬНО -->
<input name="UAMyAction" loc="#STR_MYMOD_ACTION" />
<!-- ПРАВИЛЬНО -->
<input name="UAMyAction" loc="STR_MYMOD_ACTION" />Система ввода автоматически добавляет # перед значением. Если вы добавите его сами, произойдёт двойной префикс, и поиск не найдёт строку.
Коллизии имён действий
Если два мода определят UAOpenMenu, работать будет только один. Всегда используйте префикс вашего мода:
<input name="UAMyModOpenMenu" /> <!-- Хорошо -->
<input name="UAOpenMenu" /> <!-- Рискованно -->Пропущенная запись в Sorting
Если вы определите действие в <actions>, но забудете перечислить его в <sorting>, действие будет работать в коде, но будет невидимо в меню Управление. У игрока не будет возможности переназначить его.
Забыли определить в Actions
Если вы укажете привязку в <sorting> или <preset>, но никогда не определите её в <actions>, движок молча проигнорирует её.
Конфликтующие клавиши
Выбор клавиш, конфликтующих со стандартными привязками (например, W, A, S, D, Tab, I), приводит к одновременному срабатыванию и вашего действия, и стандартного. Используйте менее распространённые клавиши (F5-F12, клавиши цифровой клавиатуры) или комбинации с модификаторами для безопасности.
Лучшие практики
- Всегда добавляйте к именам действий префикс
UA+ название вашего мода (например,UAMyModOpenMenu). Общие имена вродеUAOpenMenuбудут конфликтовать с другими модами. - Указывайте атрибут
locдля каждой видимой привязки и определяйте соответствующий ключ stringtable. Без этого в меню Управление отобразится сырое имя действия. - Выбирайте нераспространённые клавиши по умолчанию (F5-F12, цифровая клавиатура) или комбинации с модификаторами (Ctrl+клавиша), чтобы минимизировать конфликты со стандартными и популярными модовыми назначениями.
- Всегда перечисляйте видимые привязки в блоке
<sorting>. Привязка, определённая в<actions>, но отсутствующая в<sorting>, невидима для игрока и не может быть переназначена. - Кэшируйте ссылку
UAInputизGetUApi().GetInputByName()в переменной-члене вместо того, чтобы вызывать её каждый кадр вOnUpdate. Поиск по строке имеет накладные расходы.
Теория vs Практика
Что говорит документация и как на самом деле работает в рантайме.
| Концепция | Теория | Реальность |
|---|---|---|
visible="false" скрывает из меню Управление | Привязка зарегистрирована, но невидима | Скрытые привязки всё равно появляются в списке блока <sorting> в некоторых версиях DayZ. Отсутствие в <sorting> --- надёжный способ скрыть привязки |
LocalPress() срабатывает один раз при нажатии | Однократное срабатывание в кадре нажатия клавиши | Если игра «подтормаживает» (низкий FPS), LocalPress() может быть полностью пропущен. Для критических действий также проверяйте LocalValue() > 0 как запасной вариант |
Комбинации с модификаторами через вложенные <btn> | Внешний --- модификатор, внутренний --- триггер | Клавиша-модификатор сама по себе также регистрируется как нажатие на свою собственную привязку (например, kLControl --- это ещё и стандартное приседание). Игрок, удерживающий Ctrl+Клик, также присядет |
ForceDisable(true) подавляет ввод | Ввод полностью игнорируется | ForceDisable сохраняется до явного повторного включения. Если ваш мод вылетит или UI закроется без вызова ForceDisable(false), ввод останется отключённым до перезапуска игры |
Несколько соседних <btn> | Обе клавиши вызывают одно действие | Работает корректно, но меню Управление отображает только первую клавишу. Игрок может видеть и переназначить первую клавишу, но может не знать о существовании второй по умолчанию |
Совместимость и влияние
- Мульти-мод: Коллизии имён действий --- основной риск. Если два мода определят
UAOpenMenu, работать будет только один, и конфликт произойдёт молча. Движок не выдаёт предупреждений о дублировании имён действий между модами. - Производительность: Опрос ввода через
GetUApi().GetInputByName()включает поиск по хешу строки. Опрос 5-10 привязок за кадр ничтожен, но кэширование ссылкиUAInputвсё же рекомендуется для модов с большим количеством привязок. - Версия: Формат
inputs.xmlи структура<modded_inputs>стабильны с DayZ 1.0. Атрибутvisibleбыл добавлен позже (примерно в 1.08) --- в более ранних версиях все привязки всегда видны в меню Управление.
Наблюдения из реальных модов
| Паттерн | Мод | Подробности |
|---|---|---|
Комбинация с модификатором Ctrl+Click | Expansion AI | eAISetWaypoint использует вложенные <btn name="kLControl"><btn name="mBLeft"/> для Ctrl+Левый клик при размещении путевых точек AI |
| Скрытые служебные привязки | Expansion Market | UAExpansionConfirm имеет visible="false" с двумя клавишами (Enter + Numpad Enter) для внутренней логики подтверждения |
ForceDisable при открытии меню | COT, VPP | Админ-панели вызывают ForceDisable(true) на игровых привязках при открытии панели и ForceDisable(false) при закрытии, чтобы предотвратить движение персонажа при наборе текста |
Кэширование UAInput в переменной-члене | DabsFramework | Сохраняет результат GetUApi().GetInputByName() в поле класса при инициализации, опрашивает кэшированную ссылку в OnUpdate, чтобы избежать покадрового поиска по строке |
