Jump to content
Korean Random
kharlashkin

[Заказ] Обратная связь или ForceFeedback

Recommended Posts

Добрый день, уважаемые форумчане!

 

К сожалению, заказ мода на официальном форуме игры не привел ни к чему, публикую свои "хотелки" здесь.

 

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

 

jetpad_b.gif

 

Можно ли исправить этот модуль, находится вроде в папке World_of_Tanks\res\scripts\client\vibroeffects, для передачи данных не в вибронакидку а в контроллер от Xbox360? В нем так же два вибромотора.

 

P.S. Могу на данный момент заплатить 50$ хоть завтра, если будет правильное обоснование в сторону увеличения, можно увеличить бюджет. В принципе, довольно много есть интересующихся (кто играют на геймпадах), можно поднять вопрос и скинуться сообща.

 

P.P.S. Есть готовый мод, который берет данные для вибраций из файлов для вибронакидки .uwv, с помощью коэффициентов преобразовывает их и передает данные для двигателей xinput геймпада. Работают смешивание (одновременное воспроизведение нескольких эффектов), нет никаких задержек (все вибрации отрабатываются вовремя), я понял почему разработчики хвалятся тем, что эффекты делал звукорежиссер (пожар только чего стоит - как биение сердца), работают "ползунки" в настройках игры для вибронакидки (можно увеличить вибрации/уменьшить/отключить), настройки для передачи вибраций в геймпад вынесены в отдельный xml файл.

Теперь по порядку:
1. Необходимо установить Python версий 2.6.х (у меня стоит 2.6.1), в принципе можно перекомпилировать файлы под любую версию.
2. Установить Flask, качаем файл distribute_setup.py в папку "C:\temp" (например), запускаем консоль "Win+R" - cmd и выполняем команды:
C:\Python26\python.exe C:\temp\distribute_setup.py
C:\Python26\python.exe C:\Python26\Scripts\easy_install-2.6-script.py Flask
C:\Python26\python.exe C:\Python26\Scripts\easy_install-2.6-script.py Jinja2
C:\Python26\python.exe C:\Python26\Scripts\easy_install-2.6-script.py Werkzeug
C:\Python26\python.exe C:\Python26\Scripts\easy_install-2.6-script.py Virtualenv
3. Распаковать мод в нужную папку.
4. Играть.

В файле GPsettings.xml уже прописаны путь к системному python "c:/python26/pythonw.exe" со скрытым запуском, коэффициенты передачи эффекта, нужная dll ( для Windows 7/Vista), для XP нужно прописать xinput1_1, для 8-ки - XInput9_1_0.

post-19155-0-93867600-1389271658_thumb.jpg

Edited by kharlashkin
  • Upvote 2

Share this post


Link to post

Short link
Share on other sites

Покопав тему глубже, нашел следующие вводные данные:

1. На сайте производителей "виброжопки" есть SDK, т.е. очень просто понять что, как и почему работает.

2. Там же есть и стандартные эффекты для WoT, открывая которые обычным тестовым редактором понятно, как именно сделаны виброэффекты.

3. На сайте Microsoft, есть описание API для работы с геймпадом от Xbox 360.

 

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

 

Прошу совета у сообщества - реально это сделать?

 

Так же прикладываю ссылку на проект где уже есть открытый код с использованием библиотеки libusb, для контроллера Xbox 360. От себя могу подтвердить, что данная модификация работает с эмулятором xpadder и позволяет играть в WoT на геймпаде.

Edited by kharlashkin
  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

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

Edited by kharlashkin

Share this post


Link to post

Short link
Share on other sites

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

Edited by kharlashkin

Share this post


Link to post

Short link
Share on other sites

Прошло два дня - расскажу, что мне удалось, может кто-то меня подтолкнет к нужным мыслям.
Полазив в папках самой WoT нашел папку с скриптами, написанными на python, которые относятся именно к вибронакидке "X:\Games\World_of_Tanks\res\scripts\client\vibroeffects"
Декомпилировав файлы из папки, показал этот код программисту. Мне сказали - что так будет удобнее получить нужный мне функционал. Не подменой dll От вибронакидки, а непосредственным вызовом вибраций из игры.
Первое, что мне надо было сделать разобраться с вибрацией геймпада из python. В интернета нашелся нужный код. Из редактора IDLE все работает - то есть запуская этот модуль, геймпад действительно начинает вибрировать в зависимости от заданной скорости моторов.

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

Share this post


Link to post

Short link
Share on other sites

Направление правильное. Тебе необходимо переопределить метод VibroManager.launchQuickEffect(), это можно сделать, написав плагин к XPM.

Чтобы это сделать, необходимо иметь девайс для тестов, так что далеко не каждый сможет тебе помочь.

Share this post


Link to post

Short link
Share on other sites

Направление правильное. Тебе необходимо переопределить метод VibroManager.launchQuickEffect(), это можно сделать, написав плагин к XPM.

Чтобы это сделать, необходимо иметь девайс для тестов, так что далеко не каждый сможет тебе помочь.

Сразу прошу прощения - я не программист и для меня все темный лес. Мои навыки программирования остались на школьном уровне в Бейсике 20-летней давности.

Про какой именно девайс идет речь? Гемпадов у меня более чем достаточно, вибронакидку покупать не хочется.

В SDK вибронакидки есть очень много всего (включая исходники для тестовых программок).

Можно поподробнее что значит написать плагин к XPM?

Share this post


Link to post

Short link
Share on other sites

Подробно объяснять сложно. Я дал направление, может кто-то, и откликнется, кто сможет сделать.

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

Подробно объяснять сложно. Я дал направление, может кто-то, и откликнется, кто сможет сделать.

Код вроде нашел в фале vibromanager.pyc, геймпад готов подарить человеку. кто поможет. Дополнительно могу после выполнения работы заплатить обоснованную сумму денег. Под спойлером код, может закомментируете что откуда и куда. Я начал книгу читать по Python, но пока осилил треть, возможно к концу прочтения буду лучше понимать.

def launchQuickEffect(self, effectName, count = 1, gain = 100):

if not self.canWork():

return

elif count is None:

return

else:

sourceEffect = None

if effectName in self.__quickEffects:

effectsPool = self.__quickEffects[effectName]

for effect in effectsPool:

if not effect.isRunning():

effect.setRelativeGain(gain)

self.startEffect(effect, count)

return

sourceEffect = effect

 

if sourceEffect is None:

effectToLaunch = self.loadEffectFromFile(effectName)

self.__quickEffects[effectName] = [effectToLaunch]

else:

effectToLaunch = VibroEffect(effectName, self.__vibrationObject.cloneEffect(sourceEffect.handle), sourceEffect.getPriority(), self.__vibrationObject, sourceEffect.group)

self.__quickEffects[effectName].append(effectToLaunch)

effectToLaunch.setRelativeGain(gain)

self.startEffect(effectToLaunch, count)

return

Share this post


Link to post

Short link
Share on other sites

Скрин настроек из игры

0_56f26_efafc103_L.jpg

 

Если у кого есть вибронакидка объясните пожалуйста, каким образом игра понимает что накидка подключена? В саму игру вставлен модуль для работы накидки или же через ПО игра отправляет сигналы в неё.

Надо ли запускать ПО, идущее в комплекте с накидкой для определения её игрой?

Edited by kharlashkin

Share this post


Link to post

Short link
Share on other sites

Действительно, без геймпада для тестов такое сделать по-моему нереально.

Думаю связь с вибронакидкой на более низком уровне осуществляется через объект (экземпляр класса) BigWorld.WGVibration()

Код в инициализации класса:

class VibroManager:
   def __init__(self):
      self.__vibrationObject = BigWorld.WGVibration()

и далее методы:

__vibrationObject.connect()
__vibrationObject.setGain()
__vibrationObject.createEffect()
__vibrationObject.loadEffectFromFile()
__vibrationObject.setEffectGain()

наводят на мысль, что непосредственная связь с устройством осуществляется в BigWorld, т.е. в файле WorldOfTanks.exe, который просто так не поправить, и исходник не посмотреть.

 

Именно этот конкретный метод connect(), осуществляет подключение к накидке. Что это дает? Ничего хорошего, это обстоятельство сильно усложняет задачу. В идеале, все эти методы нужно переписать на новые, под геймпад, например на питоне с использованием той же Xinput. Реально ли это сделать? хз. Даже если реально, то это на это уйдет довольно много времени.

Share this post


Link to post

Short link
Share on other sites

Получилось с помощью вышеупомянутого скрипта на python задавать не только силу но и время работы вибрации в геймпаде (добавлением time.sleep ()). Соответственно можно теперь сопоставить необходимо время работы и силу двигателей для каждого эффекта (в документе от производителей их 24).

 

Подскажите куда их и каким образом вставлять эти скрипты.

import ctypes
import time

# Define necessary structures
class XINPUT_VIBRATION(ctypes.Structure):
 _fields_ = [("vibration.wLeftMotorSpeed", ctypes.c_ushort),
 ("vibration.wRightMotorSpeed", ctypes.c_ushort)]

xinput = ctypes.windll.xinput1_3 # Load Xinput.dll

# Set up function argument types and return type
XInputSetState = xinput.XInputSetState
XInputSetState.argtypes = [ctypes.c_uint, ctypes.POINTER(XINPUT_VIBRATION)]
XInputSetState.restype = ctypes.c_uint

# You can also create a helper function like this:
def set_vibration(controller, left_motor, right_motor):
 vibration = XINPUT_VIBRATION(int(left_motor * 65535), int(right_motor * 65535))
 XInputSetState(controller, ctypes.byref(vibration))

# ... and use it like so
set_vibration(0, 0.5, 1.0)
time.sleep(0.3)
set_vibration(0, 0, 0)


 

 

наводят на мысль, что непосредственная связь с устройством осуществляется в BigWorld, т.е. в файле WorldOfTanks.exe, который просто так не поправить, и исходник не посмотреть.

 

Я и не думал что будет просто ;) Вопрос вот в чем - каким образом игра понимает что накидка подключена? Думаю что с помощью вот этой библиотеки в папке игры uwApi.dll.

 

Если не взлетит переписанный скрипт vibroeffect.pyc, из-за того что BigWorld.WGVibration() не будет видеть наличие вибронакидки и не выполнять скрипты. Можно попробовать через proxy.dll подсунуть нужное значение основному объекту. Я правильно понимаю?

Edited by kharlashkin

Share this post


Link to post

Short link
Share on other sites

Ок ты нашёл что эти функции

__vibrationObject.connect()
__vibrationObject.setGain()
__vibrationObject.createEffect()
__vibrationObject.loadEffectFromFile()
__vibrationObject.setEffectGain()

лежат вuwApi.dll. Эта библиотека от gametrix. Есть ли ее исходник? Обычно производители выкладывают только заголовочные файлы.

 

Свой скрипт ты можешь вставить в игру без проблем. Самым лучшим вариантом будет создать отдельный, который будет подгружаться загрузчиком. Так твой скрипт будет работать не только в этой версии игры, но и в последующих. В твоем скрипте мне не нравится функция time.sleep() думаю надо как-то по-другому.

Share this post


Link to post

Short link
Share on other sites

Не совсем так... Вот тут есть о создании proxy.dll. исследовав библиотеку uwApi.dll на предмет экспортируемых функций с помощью утилиты dumpbin у меня получилось:

 

Dump of file c:\temp\uwApi.dll

File Type: DLL

Section contains the following exports for uwApi.dll

00000000 characteristics
4DDBD659 time date stamp Tue May 24 19:01:29 2011
0.00 version
1 ordinal base
4 number of functions
4 number of names

ordinal hint RVA name

1 0 000011D0 DllCanUnloadNow
2 1 00001320 DllGetClassObject
3 2 000011F0 DllRegisterServer
4 3 00001200 DllUnregisterServer

Summary

4000 .data
9000 .rdata
3000 .reloc
1000 .rsrc
25000 .text

То есть в библиотеке используется всего 4 функции и они никак не связаны с скриптами в игре. Я думаю что они просто сообщают игре о подключенной вибронакидке. Попробовав подменить 2-ю функцию может удастся обмануть WoT и запускать скрипты без наличия вибронакидки в системе.


 

 

Эта библиотека от gametrix. Есть ли ее исходник? Обычно производители выкладывают только заголовочные файлы.

 

Есть SDK полный на вибронакидку - ссылка выше. В архиве очень много всего (включая сырцы на С++ для тестовых программ отладчиков).


 

 

Так твой скрипт будет работать не только в этой версии игры, но и в последующих. В твоем скрипте мне не нравится функция time.sleep() думаю надо как-то по-другому.

 

Это понятно. надо сделать "файл.pyc" и просто класть его в нужную папку с игрой.

time.sleep() - Ничего более подходящего не нашел, если есть мысли - буду рад услышать. Зато можно делать циклические вибрации - 1 секунда максимум, 5 раз по 0,2 секунды на уменьшение, 1 секунда максимум и выключение вибраций на геймпаде.

 

set_vibration(0, 1.0, 1.0)
time.sleep(1)
set_vibration(0, 0.8, 0.8)
time.sleep(0.2)
set_vibration(0, 0.6, 0.6)
time.sleep(0.2)
set_vibration(0, 0.4, 0.4)
time.sleep(0.2)
set_vibration(0, 0.2, 0.2)
time.sleep(0.2)
set_vibration(0, 1.0, 1.0)
time.sleep(1)
set_vibration(0, 0, 0)

Edited by kharlashkin

Share this post


Link to post

Short link
Share on other sites

Я согласен, среди экспорт функций их нет. Но зачем тогда в этом файле такие строки:

UwGetStatus - connected
UwGetStatus - NOT connected
uwSetGain
uwCreateEffect
uwLoadEffectFromFile
uwSetEffectGain

Share this post


Link to post

Short link
Share on other sites

 

Я согласен, среди экспорт функций их нет. Но зачем тогда в этом файле такие строки:

UwGetStatus - connected
UwGetStatus - NOT connected
uwSetGain
uwCreateEffect
uwLoadEffectFromFile
uwSetEffectGain

 

Это уже непосредственно API вибронакидки.

Edited by kharlashkin

Share this post


Link to post

Short link
Share on other sites

В файле uwApi.dll.

Но без исходника ничего не выйдет. Думаю надо рыть в другом направлении. Будет ли работать этот твой скрипт

'скрипт'

import ctypes
import time

# Define necessary structures
class XINPUT_VIBRATION(ctypes.Structure):
_fields_ = [("vibration.wLeftMotorSpeed", ctypes.c_ushort),
("vibration.wRightMotorSpeed", ctypes.c_ushort)]

xinput = ctypes.windll.xinput1_3 # Load Xinput.dll

# Set up function argument types and return type
XInputSetState = xinput.XInputSetState
XInputSetState.argtypes = [ctypes.c_uint, ctypes.POINTER(XINPUT_VIBRATION)]
XInputSetState.restype = ctypes.c_uint

# You can also create a helper function like this:
def set_vibration(controller, left_motor, right_motor):
vibration = XINPUT_VIBRATION(int(left_motor * 65535), int(right_motor * 65535))
XInputSetState(controller, ctypes.byref(vibration))

# ... and use it like so
set_vibration(0, 0.5, 1.0)
time.sleep(0.3)
set_vibration(0, 0, 0)

во время работы эмулятора для геймпада. Проверь

Edited by inj3ct0r

Share this post


Link to post

Short link
Share on other sites

В файле uwApi.dll.

Но без исходника ничего не выйдет. Думаю надо рыть в другом направлении. Будет ли работать этот твой скрипт

'скрипт'

import ctypes

import time

 

# Define necessary structures

class XINPUT_VIBRATION(ctypes.Structure):

_fields_ = [("vibration.wLeftMotorSpeed", ctypes.c_ushort),

("vibration.wRightMotorSpeed", ctypes.c_ushort)]

 

xinput = ctypes.windll.xinput1_3 # Load Xinput.dll

 

# Set up function argument types and return type

XInputSetState = xinput.XInputSetState

XInputSetState.argtypes = [ctypes.c_uint, ctypes.POINTER(XINPUT_VIBRATION)]

XInputSetState.restype = ctypes.c_uint

 

# You can also create a helper function like this:

def set_vibration(controller, left_motor, right_motor):

vibration = XINPUT_VIBRATION(int(left_motor * 65535), int(right_motor * 65535))

XInputSetState(controller, ctypes.byref(vibration))

 

# ... and use it like so

set_vibration(0, 0.5, 1.0)

time.sleep(0.3)

set_vibration(0, 0, 0)

во время работы эмулятора для геймпада. Проверь

 

Если имеется ввиду работа xpadder, то да. Геймпад подключен к ПК, в xpadder настроен перехват геймпада, в IDLE запускаю скрипт - он отрабатывает нормально. При этом жмакаю на кнопки и прочее - xpadder перехватывает нажатия и эмулирует мышу/клаву.

Share this post


Link to post

Short link
Share on other sites

Это уже непосредственно API вибронакидки.

Эти строки есть вVibroManager.pyc, worldowftanks.exe иuwApi.dll. Думаю чтоworldowftanks.exe эти функции импортирует из uwApi.dll и создает класс vibrationObject с этими методами. А из VibroManager.pyc эти методы вызываются, или примерно так. Нобез исходника uwApi все равно ничего не выйдет. Поэтому я думаю нужно будет самому создавать все методы для работы с геймпадом на основе твоего скрипта. Но тут есть проблема как я говорил с time.sleep(). Что думаешь делать дальше?

Share this post


Link to post

Short link
Share on other sites
Эти строки есть вVibroManager.pyc, worldowftanks.exe иuwApi.dll. Думаю чтоworldowftanks.exe эти функции импортирует из uwApi.dll и создает класс vibrationObject с этими методами. А из VibroManager.pyc эти методы вызываются, или примерно так.

Наконец-то дельное объяснение работы этого всего "хозяйства".

 

 

Но без исходника uwApi все равно ничего не выйдет.

Так вот же исходники. Но думаю что полностью переписывать .dll нет необходимости. Надо только показать игре, что накидка подключена, VibroManager.pyc уже будет сам отрабатывать скрипты прямо на геймпад, когда BigWorld будет их вызывать для накидки. Может просто попробовать вырезать проверку подключения вибронакидки в VibroManager.pyc?

 

 

Но тут есть проблема как я говорил с time.sleep()

Ну это единственный аналог, для переписки подобного:

<uberwoorf_vibro_effect>
 <vibration_1 comment="" zones="2" looped="false">
 <vpoint_1 time="0" amplitude="0" time_relative="false"/>
 <vpoint_2 time="7200" amplitude="0" time_relative="false"/>
 </vibration_1>
 <vibration_2 comment="" zones="2" looped="true">
 <vpoint_1 time="0" amplitude="0" time_relative="false"/>
 <vpoint_2 time="80" amplitude="0" time_relative="true"/>
 <vpoint_3 time="80" amplitude="30" time_relative="true"/>
 <vpoint_4 time="140" amplitude="30" time_relative="true"/>
 <vpoint_5 time="140" amplitude="0" time_relative="true"/>
 <vpoint_6 time="180" amplitude="0" time_relative="true"/>
 </vibration_2>
 <vibration_3 comment="" zones="200" looped="true">
 <vpoint_1 time="0" amplitude="30" time_relative="false"/>
 <vpoint_2 time="60" amplitude="30" time_relative="true"/>
 <vpoint_3 time="60" amplitude="0" time_relative="true"/>
 <vpoint_4 time="180" amplitude="0" time_relative="true"/>
 </vibration_3>
 <vibration_4 comment="" zones="404" looped="true">
 <vpoint_1 time="0" amplitude="10" time_relative="false"/>
 <vpoint_2 time="60" amplitude="10" time_relative="false"/>
 <vpoint_3 time="60" amplitude="0" time_relative="true"/>
 <vpoint_4 time="360" amplitude="0" time_relative="false"/>
 </vibration_4>
 <sound path="Tiger_idle_02.wav"/>
</uberwoorf_vibro_effect>

 

 

Что думаешь делать дальше?

Продолжаю читать Лутца :)

Edited by kharlashkin

Share this post


Link to post

Short link
Share on other sites
Guest
This topic is now closed to further replies.

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...