GitHub — HuntezWOTB/WWISE-VOICE-WOT-BLITZ: Исходник проекта WWISE для создания озвучки экипажа к игре World of Tanks Blitz

Почему и зачем: длинная и необязательная преамбула

Хорошо, что опыта игрового модостроительства у меня было немного — так, пару кастомных прицелов для Deer Hunter 2005 и «нелицензионный» недоклиент

с сопутствущим «взломом» протокола последнего. Ещё лучше, что ни разу не приходилось с головой погружаться в сколь-нибудь трудоёмкую и длительную отладку и дизассемблирование. То есть, с IDA и OllyDBG я поверхностно знаком, но не как с ежедневными рабочими инструментами.

В WOT играю с начала 2022 года. Не запоем, а, скорее, набегами — по 5-6 боёв вечером. Было время 2 года назад, наш клан состоял в Красном Альянсе, ходил на глобалку по ночам, выполнял какие-то тактические задачи на европейском ТВД, устраивал тренировки и спарринги, вовсю бурлили внутриигровые политические страсти, отпочковывались учебные кланы. Сейчас всего этого уже нет, и наш золотой ёжик превратился в табличку над «Домом Ветеранов».

Впадать в ересь сравнения танков с другими MMO не буду, так как хорошо знаком только с танками. Тем более не знаком ни с одним другим проектом, использующим BigWorld, поэтому искренне верю WarGaming’у на слово, что существуют и (не)тривиально (не)преодолеваются различные техномагические ограничения движка — на размер карты, на максимальную скорость юнита, на численность команд и прочее.

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

Итак, я уверен, что в обозримом будущем никаких планов по введению полноценного режима спектатора в WOT нет и не будет. Под полноценным режимом спектатора я понимаю множественные подключения игроков в сеанс боя изначально как невзаимодействующих на игру «привидений»-наблюдателей, а не на технике.

Это тот самый режим, из-за отсутствия которого комментаторы на чемпионатах WOT вынуждены заходить в бой 15-м танком, убиваемым своими на базе. Это тот самый режим, из-за которого появились моды «командирского zoom» и «кинематографической камеры» — по сути, просто костыли.

А нужен такой режим затем, чтобы командир роты занимался командованием, а не скакал впереди на лихом танке по-чапаевски, чтобы он видел ситуацию на карте в целом непрерывно, а не отвлекался на неё в пылу нападения из засады. В идеале, командиру даже не нужны красоты трёхмерного мира — достаточно одной большой карты на весь монитор с игровой ситуацией в реальном времени — HP, повреждениями модулей, членов экипажа, направлениями стволов и прицелов союзной техники, засвеченных в каждый момент вражеских юнитов и прочей вспомогательной информации.

WOT предоставляет широкие возможности модостроительства, но такая идея выходит за рамки классического «заменить пару swf-файлов на свои». Потребуется перехват и разбор самого игрового протокола для того, чтобы иметь возможность передать на командирский планшет своё видение игровой ситуации.

Про WoT:  Как купить золото World of Tanks - альтернативные способы

Что же там внутри?

Здесь матёрые гуру реверс-инжиниринга, в духе

подумают: «ага, ну теперь можно написать на питонеэзотерическом языке вот такой скриптплагин для олькииды, который будет делать с этими данными всё что хочешь и даже за пивом сбегает». Но мы пойдём другим путём. Я хочу сразу ориентироваться на то, что ещё до того, как дело дойдёт до разработки командирского планшета, то есть даже для самого полноценного разбора протокола WOT мне понадобятся помощники и тестировщики, далёкие от мира программирования. Им нужен будет простой инструмент с понятным интерфейсом, выдающий легко читаемые данные.

Так что предвидя скептические ухмылки, я засел за Lazarus и набросал в нём специализированный win32-отладчик, основной функцией которого является поставить два INT3-брекпоинта в нужных местах и по их срабатыванию вытаскивать данные по адресу и длине буфера, лежащим на стеке по известным смещениям.

А вот так он себя ведёт уже находясь в ангаре.

Какие выводы можно сделать, даже не смотря на пояснения к пакетам, которые я поленился убрать для этих скриншотов? Сразу несколько.

Во-первых, видно, что все пакеты начинаются либо с 0x48, либо с 0x58, либо с 0x78; какой-нибудь закономерности на этот счёт я ещё не уловил, кроме того, что пакеты с уже известной функцией свой значащий байт не меняют.

Во-вторых, почти в каждом пакете есть один или несколько счётчиков сообщений; например, в keep-alive и ответах на них этим занимается третий и четвёртый байт в заголовке, кроме того сам пакет содержит ещё счётчик сообщений общий (включая keep-alive) и какой-то специфический (считающий пакеты без учёта количества keep-alive); всё это имеет отношение к контролю доставки пакетов, который пришлось прикрутить к UDP, вероятно, для оценки потерь и пересылки BLOBов (об этом позже).

Размеры всех пакетов выравнены по границам 8 байт, что ненавязчиво указывает нам на размер блока всё того же BlowFish; пока я до этого догадался, прошло немало времени в попытках обьяснить странную «контрольную сумму» в конце, да ещё и переменной длины. В конце концов, получив в этом паддинге вместо простого мусора слово «Flags» я, наконец, прозрел.

Ну и в лучших хакерских традициях, в конце каждого пакета находится сигнатура мёртвой говядины; кто бы мог подумать где мы её найдём 🙂

После получения Session ID от сервера приезжает пакет, содержащий номер игрока в неожиданно текстовом формате (792067). А вот пакет, который начинается на 0x78 0x00 на первом скриншоте — особо интересен. Сочетание сигнатуры 0x80 0x20 вкупе с тем, что перед каждым строковым литералом в нём стоит 0x55 и байт длины строки, а после каждого 0x71 находится возрастающий номер, должно насторожить опытных питонщиков — это же, чёрт побери, Python Pickle со своим запихиванием всего подряд в мемо! Вот он такой:

Pickle
Dct[15]:(xmpp_host = wot-ru.loc
captchaKey = 6Lc8GcASAAAAAKffZdxeZZvOvmSTNXbZvsy6CgBR
voipDomain = www.wotp.vivox.com
file_server = Dct[6]:(clan_emblems_small = Dct[1]:(url_template = http://ce.worldoftanks.ru/dcont/clans/emblems/%d/emblem_32x32.png)
clan_emblems_big = Dct[1]:(url_template = http://ce.worldoftanks.ru/dcont/clans/emblems/%d/emblem_64x64.png)
rare_achievements_images_big = Dct[1]:(url_template = http://ce.worldoftanks.ru/dcont/achievements/medals/180x180/%d.png)
clan_emblems = Dct[1]:(url_template = http://ce.worldoftanks.ru/dcont/clans/emblems/%d/emblem_64x64_tank.png)
rare_achievements_images = Dct[1]:(url_template = http://ce.worldoftanks.ru/dcont/achievements/medals/67x71/%d.png)
rare_achievements_texts = Dct[1]:(url_template = http://ce.worldoftanks.ru/dcont/achievements/medals/medals_%s.xml))
newbieBattlesCount = 100
roaming = Lst[4]:(1,1,Lst[3]:(Lst[4]:(1,1,499999999,RU),Lst[4]:(2,500000000,999999999,EU),Lst[4]:(3,1000000000,1499999999,NA)),Lst[0]:())
xmpp_enabled = True
jdCutouts = 0
xmpp_port = 5222
isTutorialEnabled = True
wallet = Lst[2]:(True,True)
xmpp_connections = Lst[1]:(Lst[2]:(xmppcs.worldoftanks.net,5222))
xmpp_resource = wot
regional_settings = Dct[2]:(starting_day_of_a_new_week = 0
starting_time_of_a_new_day = 0)
reCaptchaParser = )

Про WoT:  Протанки облегченная версия и облегченная версия модпака Протанки для WoT

В следующей части, если она заинтересует уважаемых обитателей Хабра, я расскажу о том, как в протоколе WOT передаются файлы, размеры которых намного больше реалистичного размера UDP пакета и MTU. И о том, что эти файлы оказывается сжатыми zlib’ом а внутри у них всё тот же Python Pickle с разными неожиданными вещами.

Спасибо за внимание!

UPD. Свежие новости! По агентурным данным из самого сердца КВГ, мой лёгкий намёк на потенциал коммерческого использования командирского планшета поднял «небольшой бугурт» (дословно), в результате чего кровавые модераторы в полнейшей панике наконец заметили и слили в мусорник тему проекта на официальном форуме танков, а мне было доверительным шёпотом посоветовано замылить данные своего аккаунта на скриншотах.

Я, имярек, находясь в здравом уме и трезвой памяти, торжественно клянусь, что разработка эта имеет исключительно академический характер, клянусь никогда в жизни не покупать компанию WarGaming.net за несметные миллиарды, вырученные от продажи ещё даже не существующей разработки либо иным способом покушаться на финансовое благополучие любимой фирмы! Аминь.

UPD2.

=========================

Я думаю, вам это не составит труда. В проекте настроено всё (от задержки, до расстановки фраз в контейнеры[По ивентам] и привязки фраз к громкости игры)После этой долго проделанной работы открываем пункт SoundBanks, в нём открываем Default Work Unit, в нём нажимаем правой кнопкой мыши по voiceover_crewи нажимаем на пункт Generate Soundbank(s) for current platformПосле завершения генерации будет результат Completed with error(s) с красным цветом текста, мы не обращаем на это вниманияДальше мы открываем папку с проектом(куда вы её распаковали) и в нём открываем папку GeneratedSoundBanks дальше открываем Windows и в нём открываем English(US)

Для установки озвучки на стим клиент:

  1. Узнаём, куда была установлена игра
  2. Открываем папки: Data; WwiseSound; (Выбираем нужный нам язык, я выбираю папку ru) ru
  3. В эту папку мы вставляем нашу озвучку (уже в формате dvpl) и подтверждаем замену файлов
    Озвучка установлена!

Для установки на андроид:

  1. Настройка в игре
    1.1) Заходим в игру
    1.2) После авторизации заходим в настройки
    1.3) Выбираем раздел Другое
    1.4) Включаем пункт «Загрузить все ресурсы игры» (если доступен)
  2. Установка озвучки в файловом менеджере
    2.1) (Необязательно)Если захотите вернуть озвучку, сделайте бэкап кэша
    2.2) Копируем voiceover_crew.bnk.dvpl по пути:
    (Копируем туда, куда были загружены файлы игры)
    Android/data/net.wargaming.wot.blitz/files/packs/WwiseSound/(Выбираем нужный нам язык, я выбираю папку ru)ru
    Именно в папку ru(на нужный нам язык) мы вставляем озвучку
    Подтверждаем замену файлов
    Озвучка установлена!

Ally_killed_by_player

Уничтожение союзника вами

  • ally_killed_by_player_01.wav
  • ally_killed_by_player_02.wav

Ammo_bay_damaged

Повреждение боеукладки

  • ammo_bay_damaged_01.wav
  • ammo_bay_damaged_02.wav
  • ammo_bay_damaged_03.wav

Armor_not_pierced_by_player

Броня не пробита

  • armor_not_pierced_by_player_01.wav
  • armor_not_pierced_by_player_02.wav
  • armor_not_pierced_by_player_03.wav
  • armor_not_pierced_by_player_04.wav
  • armor_not_pierced_by_player_05.wav

Armor_pierced_by_player

Пробитие

  • armor_pierced_by_player_01.wav
  • armor_pierced_by_player_02.wav
  • armor_pierced_by_player_03.wav
  • armor_pierced_by_player_04.wav
  • armor_pierced_by_player_05.wav
  • armor_pierced_by_player_06.wav
  • armor_pierced_by_player_07.wav
  • armor_pierced_by_player_08.wav
  • armor_pierced_by_player_09.wav
  • armor_pierced_by_player_10.wav
  • armor_pierced_by_player_11.wav
  • armor_pierced_by_player_12.wav

Armor_pierced_crit_by_player

Попадание

  • armor_pierced_crit_by_player_01.wav
  • armor_pierced_crit_by_player_02.wav
  • armor_pierced_crit_by_player_03.wav
  • armor_pierced_crit_by_player_04.wav
  • armor_pierced_crit_by_player_05.wav
  • armor_pierced_crit_by_player_06.wav
  • armor_pierced_crit_by_player_07.wav
  • armor_pierced_crit_by_player_08.wav
  • armor_pierced_crit_by_player_09.wav
Про WoT:  Мод «Круг разброса орудия» (DispersionCircle) для World of Tanks 1.17.1.0

Armor_ricochet_by_player

Рикошет

  • armor_ricochet_by_player_01.wav
  • armor_ricochet_by_player_02.wav
  • armor_ricochet_by_player_03.wav
  • armor_ricochet_by_player_04.wav
  • armor_ricochet_by_player_05.wav
  • armor_ricochet_by_player_06.wav
  • armor_ricochet_by_player_07.wav

Commander_killed

Командир ранен

  • commander_killed_01.wav
  • commander_killed_02.wav
  • commander_killed_03.wav

Driver_killed

Мех-Вод ранен

  • driver_killed_01.wav
  • driver_killed_02.wav
  • driver_killed_03.wav

Enemy_fire_started_by_player

Враг горит

  • enemy_fire_started_by_player_01.wav
  • enemy_fire_started_by_player_02.wav
  • enemy_fire_started_by_player_03.wav
  • enemy_fire_started_by_player_04.wav

Enemy_killed_by_player

Противник уничтожен

  • enemy_killed_by_player_01.wav
  • enemy_killed_by_player_02.wav
  • enemy_killed_by_player_03.wav
  • enemy_killed_by_player_04.wav
  • enemy_killed_by_player_05.wav
  • enemy_killed_by_player_06.wav
  • enemy_killed_by_player_07.wav
  • enemy_killed_by_player_08.wav
  • enemy_killed_by_player_09.wav

Engine_damaged

Двигатель повреждён

  • engine_damaged_01.wav
  • engine_damaged_02.wav
  • engine_damaged_03.wav
  • engine_damaged_04.wav
  • engine_damaged_05.wav

Engine_destroyed

Двигатель выведен из строя

  • engine_destroyed_01.wav
  • engine_destroyed_02.wav
  • engine_destroyed_03.wav

Engine_functional

Двигатель частично восстановлен, можно ехать

  • engine_functional_01.wav
  • engine_functional_02.wav

Fire_started

Танк горит

  • fire_started_01.wav
  • fire_started_02.wav

Fire_stopped

Пожар потушен

  • fire_stopped_01.wav
  • fire_stopped_02.wav
  • fire_stopped_03.wav

Fuel_tank_damaged

Бак повреждён

  • fuel_tank_damaged_01.wav
  • fuel_tank_damaged_02.wav
  • fuel_tank_damaged_03.wav
  • fuel_tank_damaged_04.wav

Gun_damaged

Орудие повреждено

  • gun_damaged_01.wav
  • gun_damaged_02.wav
  • gun_damaged_03.wav
  • gun_damaged_04.wav

Gun_destroyed

Орудие выведено из строя, стрельба невозможна

  • gun_destroyed_01.wav
  • gun_destroyed_02.wav
  • gun_destroyed_03.wav

Gun_functional

Орудие частично восстановлено, можно стрелять

  • gun_functional_01.wav
  • gun_functional_02.wav
  • gun_functional_03.wav
  • gun_functional_04.wav

Gunner_killed

Наводчик ранен

  • gunner_killed_01.wav
  • gunner_killed_02.wav
  • gunner_killed_03.wav

Loader_killed

Заряжающий ранен

  • loader_killed_01.wav
  • loader_killed_02.wav

Radio_damaged

Рация повреждена
(НЕ ЗАДЕЙСТВОВАНА В ИГРЕ)[МОЖНО ПРОПУСТИТЬ]

  • radio_damaged_01.wav
  • radio_damaged_02.wav
  • radio_damaged_03.wav
  • radio_damaged_04.wav
  • radio_damaged_05.wav

Radioman_killed

Радист ранен
(НЕ ЗАДЕЙСТВОВАНА В ИГРЕ)[МОЖНО ПРОПУСТИТЬ]

Start_battle

Бой начинается

  • start_battle_01.wav
  • start_battle_02.wav
  • start_battle_03.wav
  • start_battle_04.wav
  • start_battle_05.wav
  • start_battle_06.wav
  • start_battle_07.wav
  • start_battle_08.wav

Surveying_devices_damaged

Приборы наблюдения повреждены

  • surveying_devices_damaged_01.wav
  • surveying_devices_damaged_02.wav
  • surveying_devices_damaged_03.wav
  • surveying_devices_damaged_04.wav
  • surveying_devices_damaged_05.wav

Surveying_devices_destroyed

Приборы наблюдения выведены из строя

  • surveying_devices_destroyed_01.wav
  • surveying_devices_destroyed_02.wav
  • surveying_devices_destroyed_03.wav
  • surveying_devices_destroyed_04.wav
  • surveying_devices_destroyed_05.wav
  • surveying_devices_destroyed_06.wav

Surveying_devices_functional

Приборы наблюдения восстановлены

  • surveying_devices_functional_01.wav
  • surveying_devices_functional_02.wav
  • surveying_devices_functional_03.wav
  • surveying_devices_functional_04.wav
  • surveying_devices_functional_05.wav
  • surveying_devices_functional_06.wav

Track_cut

Гусеница сбита, можем откатиться

  • track_destroyed_cut_01.wav

Track_damaged

Повреждение гусеницы

  • track_damaged_01.wav
  • track_damaged_02.wav
  • track_damaged_03.wav
  • track_damaged_04.wav

Track_destroyed

Гусеница сбита, движение невозможно

  • track_destroyed_01.wav
  • track_destroyed_02.wav
  • track_destroyed_03.wav
  • track_destroyed_04.wav

Track_functional

Гусеница восстановлена

  • track_functional_01.wav
  • track_functional_02.wav
  • track_functional_03.wav
  • track_functional_04.wav

Track_functional_can_move

Гусеница восстановлена, можно ехать

  • track_functional_can_move_01.wav
  • track_functional_can_move_02.wav
  • track_functional_can_move_03.wav
  • track_functional_can_move_04.wav
  • track_functional_can_move_05.wav

Turret_rotator_damaged

Башня повреждена, скорость поворота башни снижена

  • turret_rotator_damaged_01.wav
  • turret_rotator_damaged_02.wav

Turret_rotator_destroyed

Башня выведена из строя, вращение невозможно

  • turret_rotator_destroyed_01.wav
  • turret_rotator_destroyed_02.wav

Turret_rotator_functional

Башня частично восстановлена, скорость вращения снижена

  • turret_rotator_functional_01.wav
  • turret_rotator_functional_02.wav

Vehicle_destroyed

Танк уничтожен

  • vehicle_destroyed_01.wav
  • vehicle_destroyed_02.wav
  • vehicle_destroyed_03.wav

Wwise-voice-wot-blitz

Исходный код проекта WWISE для создания озвучки экипажа к игре World of Tanks Blitz

Данный проект поможет сделать вам свою озвучку к игре World of Tanks Blitz с помощью программы Audiokinetic WWISE

Данный проект WWISE хорошо функционирует с версией: 2022.2.9.7459

Как создать свою озвучку:

  1. Скачиваем WWISE Launcher из официального сайта аудиодвижка
  2. Устанавливаем WWISE Launcher
  3. Запускаем WWISE Launcher
  4. В WWISE Launcher выбираем пункт WWISE (второй с левого ряда)
  5. В пункте INSTALL NEW VERSION из пункта Latest выбираем пункт All
  6. Справа от All меняем 2021.1 на 2022.2
  7. Справа от 2022.2 выбираем версию WWISE 2022.2.9.7459
  8. После выбранной версии нажимаем снизу на кнопку Install…
  9. После установки открываем Загрузки в Проводнике
  10. Распаковываем WWISE VOICE WOT BLITZ проект полностью (лучше в удобное место)
  11. Открываем двумя быстрыми кликами файл WOTB_WWISE_VOICE.wproj
  12. После открытия открываем пункт Audio
    и открываем Actor-Mixer Hierarchy
    Дальше открываем Default Work Unit
    Теперь открываем voice и тут много контейнеров, в них мы должны вставить аудиофайлы, вот их список:
    (К фразам идёт название аудиофайла и его формат, фразу сохраняем под нужным названием и форматом)
    (Просто перенесите аудиофайл из папки в программу под нужный контейнер, она сама настроит его(если под правильным названием и форматом))

Рентген мод (исходники) — библиотека читов world of tanks на

Оцените статью
TankMod's
Добавить комментарий