Jump to content
Korean Random
Tee-m

Как получить телеметрию с танка реалтайм?

Recommended Posts

Доброго времени суток.

 

Надо во время боя иметь возможность считывать все параметры танка в сторонюю прогу (скорость, ХП, состояние модулей/экипажа, снаряды).

 

Сам до этого модами для ВоТ да и декомпиляциями клиентов не занимался, по этому буду рад совету от знающих - как к этой задаче правильно подойти?

  • Upvote 1
  • Downvote 1

Share this post


Link to post

Short link
Share on other sites

А не получится изобретать велосипед?

Может кто-то уже этим занимался и есть решения?

Share this post


Link to post

Short link
Share on other sites

А не получится изобретать велосипед?

Может кто-то уже этим занимался и есть решения?

Да. Тут полно тех, кто декомпилировал питон и терпеливо изучал его.  :gg:

  • Upvote 1
  • Downvote 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

Да. Тут полно тех, кто декомпилировал питон и терпеливо изучал его.  :gg:

 

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

Share this post


Link to post

Short link
Share on other sites

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

Терпение Вам в руки, те кто может Вам помочь очень ограничены во времени, да и человеческие факторы сказываются так же. Могу сказать что все возможно - ведь берут в бою и ХП танка, и каким снарядом кто стреляет. Местные жители форума очень отзывчивые люди. кто-то обязательно поможет!

А относительно копания в танковых скриптах - это обязательное условие для начинающих ;) Ну и гугление никто не отменял, ведь лучше Вас никто не сможет ничего сделать.

Share this post


Link to post

Short link
Share on other sites

Вы лучше сперва скажите... каковы Ваши знания питона? Может Вам и не стоит в это нырять.

  • Upvote 2
  • Downvote 1

Share this post


Link to post

Short link
Share on other sites

Вы лучше сперва скажите... каковы Ваши знания питона? Может Вам и не стоит в это нырять.

 

С питоном грустно, начальные ) Я больше по другой части. Поэтому и хотелось бы узнать, может у кого-то в коммюнити можно найти +/- в этом направлении сниппеты?

 

Пока ковырять начал сам.. Нашел на гитхабе вроде декомпиленный клиент:

https://github.com/Omegaice/WOTDecompiled/blob/master/res/scripts/client/gui/scaleform/battle.py

там в файл battle.py с функциями типа

 def updateSpeed(self, speed):
        if self.__speed is not speed:
            self.__speed = speed
            self.__callFlash('updateSpeed', [speed])

Я правильно понимаю, что этот файл можно замодить(или написать новый, по образу и подобию) и выводить сразу такого типа данные куда-то ещё?

Edited by Tee-m

Share this post


Link to post

Short link
Share on other sites

Собственно, для чего тебе эта инфа?

 

Вообще у каждого танка есть свой ID. По ID танка можно получить объект PyModel. Из него можно получить и хп, и скорость, а также дескриптор класса, определяющий расположение различных деталей танка, про матрицы компонентов (корпус, башня, пушка) я вообще молчу. Короче любую инфу о танке как объекте. Только подклассы у PyModel могут быть разные, и иметь разные свойства-методы (всякий танк - модель, но не всякая модель - танк). Вообще я бы посоветовал тебе почитать файлик хэлпа по питону BigWorld, он не сильно изменился с допотопных версий, хотя накрутили, конечно, много. Копай в сторону BigWorld.entity(ID).

python_client.zip

Что касается внедрения скриптов в клиент, то подменять исходные файлы наверное самая плохая идея из всех существующих. Грамотные мододелы используют так называемые хуки (в питоне это реализуется вытаскиванием исходного метода какого-либо класса в глобальную переменную мода, вместо него подставляется свой метод, вызывающий исходный + дополнительный код). Это касаемо способа реализации с привязкой к каким-либо событиям (читай объектно-ориентированное программирование). Можно реализовать также через BigWorld.callback(), но этот способ сильно просаживает fps, если выполняемый внутри цикла код довольно громоздкий.

Только вот я не понимаю, нафига вытаскивать динамические данные в другую программу. Если их обрабатывать и потом возвращать обратно в игру, то проще все реализовать сразу на питоне. А в остальном... если интересует "ангарная" (небоевая) информация о машине, то есть у PyModel такое свойство typeDescriptor кажется, там все описано. Пушка, снаряды, критические УВН/УГН, максимальные скорости вперед/назад, баллистические постоянные для каждого типа снарядов и т.п. Я сейчас не дома, так что точно сказать не могу, по памяти пишу. Вообще имена методов объекта в питоне можно получить через dir() кажется. А в остальном, если надо, то только терпеливое раскапывание скриптов и изучение питона, в особенности интроспекции, тут поможет. За тебя код писать вряд ли кто будет. К тому же непонятно что (и непонятно зачем).

Edited by GPCracker
  • Upvote 2

Share this post


Link to post

Short link
Share on other sites
С питоном грустно

 

Тогда лучше начинать с чего полегче.

 

 

Нашел на гитхабе вроде декомпиленный клиент

Все это шустро устаревает... возьмите самый свежий клиент и декомпильните всю папку scripts... если у Вас возникает вопрос "как" - тогда это даже не начальный уровень получается. Тогда нужно начинать с азов.

 

 

Что касается внедрения скриптов в клиент, то подменять исходные файлы наверное самая плохая идея из всех существующих

Золотые слова, Юрий Венедиктович © Наша Russia

этим грешат евромодеры... наши четче пишут.

Edited by Yusha
  • Upvote 1
  • Downvote 2

Share this post


Link to post

Short link
Share on other sites

@GPCracker, благодарю за инфу.

 

Чтобы проянисть - телеметрию танка я хочу вывести на ком порт(усб с ком преобразователем). А дальше уже сваять железку отдельно от компа. Пример с спидометром был относительно близок к моей задумке. Сам я больше хардвером занимаюсь - схемотехника, механика, прошивка под контроллеры(firmware), по этому моды и питон для меня это тёмный лес в который я могу въехать только на общих знаниях об ООП и склонность быстро схватывать инфу :) . От мода то в принципе требуется только (1)выудить телеметрию и (2)передать её в ком порт. Второе наверняка делается готовой библиотекой, да и  любом случае решаемо - варианты есть, вот и для первого хочется найти чего-то не требующего изобретения велосипедов, но пока потихоньку буду вникать в питон, похоже)

Edited by Tee-m

Share this post


Link to post

Short link
Share on other sites

Сам я больше хардвером занимаюсь - схемотехника, механика, прошивка под контроллеры(firmware), по этому моды и питон для меня это тёмный лес в который я могу въехать только на общих знаниях об ООП и склонность быстро схватывать инфу :)

Уважаю. Сам на инженера учусь)

 

Код по части захвата телеметрии там немного, с состоянием модулей и снарядов не знаю, пока не сталкивался. callback вряд ли удастся обойти, так что некоторая просадка fps все равно будет. Вот  портами тут не все так просто, возможно, придется на си кодить... С внедрением си в питон, пока тоже не работал, не знаю, но говорят можно). В общем, если будет время, мож накидаю чего в общем виде, только дебажить на моем калькуляторе пне4 (а я с ним до сентября) не получится.

Share this post


Link to post

Short link
Share on other sites

Накидал немного... с танком проще, есть атрибуты, а вот с боекомплектом и модулями... их состояние нигде не сохраняется по ходу... только изменяется по команде сервера... так что там нужно ставить хуки на методы.
Модули из DamagePanel, снаряды - consumablesPanel





import BigWorld, Math

#Данные о технике
playerVehicle = BigWorld.entity(BigWorld.player().playerVehicleID)
if playerVehicle is not None:
    position = playerVehicle.position
    direction = Math.Matrix(playerVehicle.matrix).applyVector(Math.Vector3(0, 0, 1))
    gunPosition = playerVehicle.appearance.modelsDesc['gun']['model'].position
    gunDirection = Math.Matrix(playerVehicle.appearance.modelsDesc['gun']['model'].matrix).applyVector(Math.Vector3(0, 0, 1))
    speedVector = playerVehicle.velocity
    speed = playerVehicle.velocity.length
    speed2 = playerVehicle.getSpeed()
    HP = playerVehicle.health
    operatable = playerVehicle.isCrewActive and playerVehicle.health > 0
    isAlive = playerVehicle.isAlive()
    typeDescriptor = vehicle.typeDescriptor ##Тут есть вся информация о конкретной технике как классе. 
    ##Вся инфа в ангаре берется отсюда, но отображается в ангаре лишь малая часть того, что тут есть...

#сами панели (объекты)
from gui.WindowsManager import g_windowsManager
DamagePanel = g_windowsManager.battleWindow.damagePanel
consumablesPanel = g_windowsManager.battleWindow.consumablesPanel

#классы панелей
from gui.Scaleform.Battle import ConsumablesPanel, DamagePanel

И еще. Немного инфы на тему получения информации об объектах
http://www.ibm.com/developerworks/ru/library/l-pyint/
 
Описание модуля, на английском, правда
https://docs.python.org/2/library/inspect.html

Edited by GPCracker
  • Upvote 2

Share this post


Link to post

Short link
Share on other sites

О, огроменно спасибо! )

А то у меня пока ничего дельного не получается.

 

Буду пробовать этот кусок кода использовать так, чтобы всё таки через питон всё шло на ком порт. Как понимаю http://pyserial.sourceforge.net/pyserial.html# эта библиотека должна давать такую опцию.

Share this post


Link to post

Short link
Share on other sites

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

Модули из DamagePanel, снаряды - consumablesPanel





import BigWorld, Math

#Данные о технике
playerVehicle = BigWorld.entity(BigWorld.player().playerVehicleID)
if playerVehicle is not None:
    position = playerVehicle.position
    direction = Math.Matrix(playerVehicle.matrix).applyVector(Math.Vector3(0, 0, 1))
    gunPosition = playerVehicle.appearance.modelsDesc['gun']['model'].position
    gunDirection = Math.Matrix(playerVehicle.appearance.modelsDesc['gun']['model'].matrix).applyVector(Math.Vector3(0, 0, 1))
    speedVector = playerVehicle.velocity
    speed = playerVehicle.velocity.length
    speed2 = playerVehicle.getSpeed()
    HP = playerVehicle.health
    operatable = playerVehicle.isCrewActive and playerVehicle.health > 0
    isAlive = playerVehicle.isAlive()
    typeDescriptor = vehicle.typeDescriptor ##Тут есть вся информация о конкретной технике как классе. 
    ##Вся инфа в ангаре берется отсюда, но отображается в ангаре лишь малая часть того, что тут есть...

#сами панели (объекты)
from gui.WindowsManager import g_windowsManager
DamagePanel = g_windowsManager.battleWindow.damagePanel
consumablesPanel = g_windowsManager.battleWindow.consumablesPanel

#классы панелей
from gui.Scaleform.Battle import ConsumablesPanel, DamagePanel

А можно ли как то передать значения во внешнее приложение с помощью UDP ? Скажем я запускаю сервер на питоне и хочу отправить значение любого параметра из выше приведенных с помощью:

import socket
import sys
UDP_IP = "127.0.0.1"
UDP_PORT = 7777
MESSAGE = " speed2" #ЗНАЧЕНИЕ ПАРАМЕТРА пример
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))

если возможно покажите как правильно это делать.

 

Или может лучше так?

import BigWorld, Math
import socket
from PlayerEvents import g_playerEvents

class Message(object):
    def __init__(self):
        g_playerEvents.onAccountShowGUI += self.message
    def message(self, ctx):
        UDP_IP = '127.0.0.1'
        UDP_PORT = 7777
        MESSAGE = playerVehicle.getSpeed() #ЗНАЧЕНИЕ ПАРАМЕТРА пример
        socket.socket(socket.AF_INET, socket.SOCK_DGRAM).sendto(MESSAGE, (UDP_IP, UDP_PORT))
        g_playerEvents.onAccountShowGUI -= self.message
Message()
Edited by Serfer_78

Share this post


Link to post

Short link
Share on other sites

А можно ли как то передать значения во внешнее приложение с помощью UDP ?

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

2. UDP - это тема множества примеров в интернете. Код там тоже имеется. Не буду заниматься баянами и велосипедами.

3. Мост между UDP и данными. Называется сериализация. Иными словами, кодирование/декодирование информации при пересылке. JSON, marshal, cPickle... Компрессия и прочие трансформации для оптимизации под канал передачи (zlib, base64, ...). Возможно потребуется приведение к примитивному типу для некоторых объектов BigWorld (tuple() для векторов например).

Все есть уже. Давно. Просто поискать немного надо. Все нужные доки по BigWorld кидал ранее, кажется даже в этой теме.

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

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

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

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

2. UDP - это тема множества примеров в интернете. Код там тоже имеется. Не буду заниматься баянами и велосипедами.

3. Мост между UDP и данными. Называется сериализация. Иными словами, кодирование/декодирование информации при пересылке. JSON, marshal, cPickle... Компрессия и прочие трансформации для оптимизации под канал передачи (zlib, base64, ...). Возможно потребуется приведение к примитивному типу для некоторых объектов BigWorld (tuple() для векторов например).

Все есть уже. Давно. Просто поискать немного надо. Все нужные доки по BigWorld кидал ранее, кажется даже в этой теме.

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

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

 

Дело в том что данные из клиента я уже свободно передаю сообщение 'Hello, World!' в свой мини сервер из папки mods, в каком виде они передаются я тоже уже понял.. Как получить данные в танках вроде разобрался , т.к с питоном да и в целом с ООП на "Вы" просмотрел очень хорошие видео по ООП (попрактиковал малость)    тут    автор все замечательно разъяснил.  Но в танках все довольно спецефично на мой взгляд, и хотя нашел примеры в гугле все же решил не городить огород , а обратиться на форум чтобы убедиться что не заблуждаюсь. 

Просто надеялся что гуру подтолкнут хотя бы нейтральным примером в нужную сторону

чтонибудь типа такого примера:

Передаем скорость  speed = playerVehicle.velocity.length

Message(self,speed)

 

 

А в остальном вот это работает как часики:

import socket
from PlayerEvents import g_playerEvents
UDP_IP = '127.0.0.1'
UDP_PORT = 7777
MESSAGE = 'Hello, World!'
g_playerEvents.onAccountShowGUI += lambda ctx: socket.socket(socket.AF_INET, socket.SOCK_DGRAM).sendto(MESSAGE, (UDP_IP, UDP_PORT))

Этот код тоже шустро пашет и передает данные :

import socket
from PlayerEvents import g_playerEvents
class Message(object):
    def __init__(self):
        g_playerEvents.onAccountShowGUI += self.message
    def message(self, ctx):
        UDP_IP = '127.0.0.1'
        UDP_PORT = 7777
        MESSAGE = 'Hello, World!'
        socket.socket(socket.AF_INET, socket.SOCK_DGRAM).sendto(MESSAGE, (UDP_IP, UDP_PORT))
        g_playerEvents.onAccountShowGUI -= self.message
Message()

Все равно спасибо что откликнулись  , тепрь хотя бы знаю что это в принципе возможно, буду эксперементировать, рано или поздно заработает )))

Edited by Serfer_78

Share this post


Link to post

Short link
Share on other sites

g_playerEvents.onAccountShowGUI += lambda ctx: socket.socket(socket.AF_INET, socket.SOCK_DGRAM).sendto(MESSAGE, (UDP_IP, UDP_PORT))

Не стоит так делать. Используй потоки.

Одно из основных правил хорошего кода - выносить все операции ввода-вывода в отдельный поток/потоки. Ибо они могут просто повесить обработку события и создать лаг.

Или просто сорвать выполнение неожиданным исключением. Типа "файл недоступен", "нет прав", "сеть не работает" и в том же стиле.

Edited by GPCracker
  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

Не стоит так делать. Используй потоки.

Одно из основных правил хорошего кода - выносить все операции ввода-вывода в отдельный поток/потоки. Ибо они могут просто повесить обработку события и создать лаг.

Или просто сорвать выполнение неожиданным исключением. Типа "файл недоступен", "нет прав", "сеть не работает" и в том же стиле.

 

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

Share this post


Link to post

Short link
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...