Jump to content
Korean Random

kharlashkin

User
  • Posts

    829
  • Joined

  • Last visited

  • Days Won

    7

Posts posted by kharlashkin

  1. Пробовал через AutoHotkey отправлять в pid процесса нажатие клавиши "W", чтобы в неактивном окне танк ехал вперед. Блин и один раз он таки поехал ;) Но при переключении между окнами перестал ;( С чем связано - не знаю... Ниже выкладываю на обсуждение скрипт.

    'test.ahk'

    w:: 
    WinGet, wot, PID, WoT Client
    ControlSend,, {sc11 Down}, ahk_pid %wot%
    KeyWait, w
    ControlSend,, {sc11 Up}, ahk_pid %wot%
    Return 


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

    • Downvote 1
  2. Случайно наткнулся на утилиту AutoHotkey, которая стала для меня небольшим открытием, но думаю что очень многим форумчанам знакома не по наслышке. Даже нашелся скрипт для геймпада:

    'JoyMouse.ahk'

    ; Increase the following value to make the mouse cursor move faster:
    JoyMultiplier = 0.30
    
    ; Decrease the following value to require less joystick displacement-from-center
    ; to start moving the mouse.  However, you may need to calibrate your joystick
    ; -- ensuring it's properly centered -- to avoid cursor drift. A perfectly tight
    ; and centered joystick could use a value of 1:
    JoyThreshold = 3
    
    ; Change the following to true to invert the Y-axis, which causes the mouse to
    ; move vertically in the direction opposite the stick:
    InvertYAxis := false
    
    ; Change these values to use joystick button numbers other than 1, 2, and 3 for
    ; the left, right, and middle mouse buttons.  Available numbers are 1 through 32.
    ; Use the Joystick Test Script to find out your joystick's numbers more easily.
    ButtonLeft = 1
    ButtonRight = 2
    ButtonMiddle = 3
    
    ; If your joystick has a POV control, you can use it as a mouse wheel.  The
    ; following value is the number of milliseconds between turns of the wheel.
    ; Decrease it to have the wheel turn faster:
    WheelDelay = 250
    
    ; If your system has more than one joystick, increase this value to use a joystick
    ; other than the first:
    JoystickNumber = 1
    
    ; END OF CONFIG SECTION -- Don't change anything below this point unless you want
    ; to alter the basic nature of the script.
    
    #SingleInstance
    
    JoystickPrefix = %JoystickNumber%Joy
    Hotkey, %JoystickPrefix%%ButtonLeft%, ButtonLeft
    Hotkey, %JoystickPrefix%%ButtonRight%, ButtonRight
    Hotkey, %JoystickPrefix%%ButtonMiddle%, ButtonMiddle
    
    ; Calculate the axis displacements that are needed to start moving the cursor:
    JoyThresholdUpper := 50 + JoyThreshold
    JoyThresholdLower := 50 - JoyThreshold
    if InvertYAxis
        YAxisMultiplier = -1
    else
        YAxisMultiplier = 1
    
    SetTimer, WatchJoystick, 10  ; Monitor the movement of the joystick.
    
    GetKeyState, JoyInfo, %JoystickNumber%JoyInfo
    IfInString, JoyInfo, P  ; Joystick has POV control, so use it as a mouse wheel.
        SetTimer, MouseWheel, %WheelDelay%
    
    return  ; End of auto-execute section.
    
    
    ; The subroutines below do not use KeyWait because that would sometimes trap the
    ; WatchJoystick quasi-thread beneath the wait-for-button-up thread, which would
    ; effectively prevent mouse-dragging with the joystick.
    
    ButtonLeft:
    SetMouseDelay, -1  ; Makes movement smoother.
    MouseClick, left,,, 1, 0, D  ; Hold down the left mouse button.
    SetTimer, WaitForLeftButtonUp, 10
    return
    
    ButtonRight:
    SetMouseDelay, -1  ; Makes movement smoother.
    MouseClick, right,,, 1, 0, D  ; Hold down the right mouse button.
    SetTimer, WaitForRightButtonUp, 10
    return
    
    ButtonMiddle:
    SetMouseDelay, -1  ; Makes movement smoother.
    MouseClick, middle,,, 1, 0, D  ; Hold down the right mouse button.
    SetTimer, WaitForMiddleButtonUp, 10
    return
    
    WaitForLeftButtonUp:
    if GetKeyState(JoystickPrefix . ButtonLeft)
        return  ; The button is still, down, so keep waiting.
    ; Otherwise, the button has been released.
    SetTimer, WaitForLeftButtonUp, off
    SetMouseDelay, -1  ; Makes movement smoother.
    MouseClick, left,,, 1, 0, U  ; Release the mouse button.
    return
    
    WaitForRightButtonUp:
    if GetKeyState(JoystickPrefix . ButtonRight)
        return  ; The button is still, down, so keep waiting.
    ; Otherwise, the button has been released.
    SetTimer, WaitForRightButtonUp, off
    MouseClick, right,,, 1, 0, U  ; Release the mouse button.
    return
    
    WaitForMiddleButtonUp:
    if GetKeyState(JoystickPrefix . ButtonMiddle)
        return  ; The button is still, down, so keep waiting.
    ; Otherwise, the button has been released.
    SetTimer, WaitForMiddleButtonUp, off
    MouseClick, middle,,, 1, 0, U  ; Release the mouse button.
    return
    
    WatchJoystick:
    MouseNeedsToBeMoved := false  ; Set default.
    SetFormat, float, 03
    GetKeyState, joyx, %JoystickNumber%JoyX
    GetKeyState, joyy, %JoystickNumber%JoyY
    if joyx > %JoyThresholdUpper%
    {
        MouseNeedsToBeMoved := true
        DeltaX := joyx - JoyThresholdUpper
    }
    else if joyx < %JoyThresholdLower%
    {
        MouseNeedsToBeMoved := true
        DeltaX := joyx - JoyThresholdLower
    }
    else
        DeltaX = 0
    if joyy > %JoyThresholdUpper%
    {
        MouseNeedsToBeMoved := true
        DeltaY := joyy - JoyThresholdUpper
    }
    else if joyy < %JoyThresholdLower%
    {
        MouseNeedsToBeMoved := true
        DeltaY := joyy - JoyThresholdLower
    }
    else
        DeltaY = 0
    if MouseNeedsToBeMoved
    {
        SetMouseDelay, -1  ; Makes movement smoother.
        MouseMove, DeltaX * JoyMultiplier, DeltaY * JoyMultiplier * YAxisMultiplier, 0, R
    }
    return
    
    MouseWheel:
    GetKeyState, JoyPOV, %JoystickNumber%JoyPOV
    if JoyPOV = -1  ; No angle.
        return
    if (JoyPOV > 31500 or JoyPOV < 4500)  ; Forward
        Send {WheelUp}
    else if JoyPOV between 13500 and 22500  ; Back
        Send {WheelDown}
    return 

     

    Интересно вот что, сможет ли AutoHotkey принимать значения от 2-х геймпадов и отдавать разным окнам (двум клиентам WoT) значения клавиатуры/мыши? Может кто более детально использовал эту утилиту, подскажет мне...


    Небольшое гугление - AutoHotkey: отправка нажатий клавиш в неактивное окно. Надо более детально изучить.


    Проверил тестовым скриптом отправку нажатий клавиш в неактивное окно клиента WoT. Окошко команды принимает, но отрабатывает только тогда, когда окно становится активным. Т.е. окно не активно, я нажимаю WASD, переключаюсь в окно клиента и вижу нажатия кнопок WASD.


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

    'scripts/client/gui/InputHandler.pyс'

    import Event
    g_instance = None
    
    class _InputHandler:
        onKeyDown = Event.Event()
        onKeyUp = Event.Event()
    
        def handleKeyEvent(self, event):
            if event.isKeyDown():
                self.onKeyDown(event)
            else:
                self.onKeyUp(event)
    
    
    g_instance = _InputHandler() 

     

    Может это поможет понимающим людям понять как игра отрабатывает нажатия клавиш и можно будет туда добавить дополнительный обработчик.

    • Upvote 1
    • Downvote 1
  3. Не ошибка, вы попытались просмотреть результат боя который был сыгран в прошлой сессии. В игре появляется сообщение что результат боя не доступен в питоне такой лог

    Буду теперь знать что это такое. Спасибо!!!

    Закрываю темку.

  4. Как-то указанные ошибки, на мой взгляд, не очень вяжутся с изменением trackbreakingcontroller.pyс ...

    Мне изначально так же показалось, но как говорится "Одна голова хорошо, а форум лучше". Более того - сейчас вообще нет никаких ошибок ;)

    'python'

    Checking ./res_mods/0.9.0: mods found
    [XPM] preloader gui.Scaleform.locale
    [XPM] Working dir: ./res_mods/0.9.0/scripts/client/gui/mods
    [XPM] Loading mod: gpvibromanager 1.2.0 (http://www.koreanrandom.com/forum/user/16753-inj3ct0r/)
    urllib2.URLError (connect): <urlopen error [Errno 10061] Подключение не установлено,>
    [NOTE] (scripts/client/post_processing/__init__.py, 275): The quality = 4 was selected.
    [NOTE] (scripts/client/post_processing/__init__.py, 275): The quality = 3 was selected.
    [SPACE] Loading space: spaces/hangar_v2
    [SPACE] Loading space: spaces/86_himmelsdorf_winter
    [SPACE] Loading space: spaces/hangar_v2
    [SPACE] Loading space: spaces/01_karelia
    [SPACE] Loading space: spaces/hangar_v2
    PostProcessing.Phases.fini() 

  5. Ну а ради интереса не пробовали изменить и перекомпилировать trackbreakingcontroller.pyс, как выше советовал lportii?

    Как бэ да... Моя ошибка - сразу тогда не попробовал, попробовал сейчас.

    'python'

    [ERROR] (scripts/client/gui/shared/utils/requesters/__init__.py, 973): Server return error for stat request: responseCode=-10
    [ERROR] (scripts/client/gui/shared/utils/requesters/__init__.py, 1002): frames stack dumping --------------
     (scripts/client/gui/shared/utils/requesters/__init__.py, 999): __dumpStack
     (scripts/client/gui/shared/utils/requesters/__init__.py, 974): __valueResponse
     (scripts/client/account_helpers/BattleResultsCache.py, 90): __onGetResponse
     (scripts/client/Account.py, 289): onCmdResponse 

     

    За картошкой все скрипты теперь исправлять?

     

    Прошу прощения что так долго не пробовал этого решения - не до игр мне сейчас. А обновлял версию по просьбе до 0.9.0 и выскочили те же ошибки, вот и вспомнил про темку.

    Завтра раскомпилирую скрипты на которые ссылаются ошибки, посмотрим что там будет. Исправлять так исправлять ;)

  6. Надо делать динамический зум миникарты :) Типа как в навигаторах - чем быстрее едешь, тем выше камеру поднимать. Кстати, вполне реально это сделать, хотя и геморно.

    Плюсую. Будет прикольно, особенно (если принимать во внимание статистику обычного расположения противников) подкрашивать стрелку в соответствующий цвет.

     

     

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

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

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

    Есть скрипт управления курсором

    'scripts/client/gui/Cursor.pyс'

    import BigWorld
    import GUI
    import Math
    from debug_utils import *
    from bwdebug import WARNING_MSG
    _mouseModeRefCount = 0
    
    def showCursor(show):
        global _mouseModeRefCount
        if show:
            _mouseModeRefCount += 1
            if _mouseModeRefCount > 0:
                BigWorld.setCursor(GUI.mcursor())
                GUI.mcursor().visible = True
        else:
            _mouseModeRefCount -= 1
            if _mouseModeRefCount == 0:
                BigWorld.setCursor(BigWorld.dcursor())
                GUI.mcursor().visible = False
            if _mouseModeRefCount < 0:
                WARNING_MSG('mouseModeRefCount is negative!')
    
    
    def forceShowCursor(show):
        if show:
            BigWorld.setCursor(GUI.mcursor())
            GUI.mcursor().visible = True
        else:
            BigWorld.setCursor(BigWorld.dcursor())
            GUI.mcursor().visible = False
    
    
    def pixelPosition():
        screenWidth, screenHeight = GUI.screenResolution()
        mouseLeft, mouseTop = GUI.mcursor().position
        width = round((1.0 + mouseLeft) / 2.0 * screenWidth)
        height = round(-(-1.0 + mouseTop) / 2.0 * screenHeight)
        return (width, height) 

     

    Так же есть скрипты от самолетиков, реально написать тестовый скрипт для назначения правого стика геймпада (самолетные Оси 3 и 4)? Может кто сделать например за эквивалент месяца премиума?

    • Upvote 1
    • Downvote 1
  8. Так-с осталось найти режиссера, продюссера и спонсора и дело в шляпе.

     

    Сори за оффтоп (пишу по памяти):

    Снимали фильм: режиссер - шизофреник, слепой оператор, глухой звукорежиссер, сценарист аутист, актеры дауны и т.п. Сняли, смонтировали, озвучили - Премьера, набилось полный зал интересующихся. В конце фильма остается в зале только режиссер и произносит: "А мне нравится!!!" 

  9. Вот идея для ТС-а, скинемся по рублю на сервер, запилим на нем пару сотен тысяч клонов такого интеллектуального бота и законнектим их на сервера ВГ. И будет идиллия - тысячи ботов с одного сервера катаются в онлайне на другом сервере.... очередной сюжет для голливудского фантастического блокбастера :)))))))))

    А потом с помощью самообучающегося алгоритма боты начнут понимать - что как то не то, и начнут лезть на другие сервера и ...в конце концов образуют "SkyNet" и пошло-поехало :)

  10. По поводу разделения игры на два окна.

    Я пользуюсь NoFrame для фиксации окна игры, единое что она не работает с вторым окном, ну вы поговорите с автором.

     

    Отписывался я в этой теме. Правда, не пробовал с запущенным VDM два ока без рамок, нужно попробовать как то в свободное время. В теме есть ещё ссылка на relocator - которая почти такая же утилита. Пробовал ещё и её перекомпилировать под нужные параметры - результат нет. Мне очень не понравилась эта VDM - ломает как то стандартный виндовый интерфейс. Да и не совсем мне понятно почему в полноэкранном режиме можно выставить любое разрешение, а в окошке минимум 1024х768. Так что поиск решения идет.

     

    Где то встречал что WarGaming используют какой то "прием" для ускорения вывода изображений и не используют стандартные WinAPI, поэтому уменьшение картинки работает только с VDM (мне кажется утилита использует такой же или похожий прием, но так как VDM стартует сразу в окнах - имеет больший приоритет). В той же теме автор говорил о том, что это может быть функции не WinAPI а DirectX - соответственно должна быть другая утилита.

     

    Блин я их перепробовал уже столько, что и не вспомнишь все (самая лучшая Snap - Win+стрелка вправо/стрелка влево, стандартная фича Windows 7).

    • Upvote 1
    • Downvote 1
  11. Доброе время суток!

     

    Мне (и не только мне) кажется. что тем способом, каким работает вибрация - нормально подключить геймпад не получиться. Клиент-серверная архитектура будет не так быстро работать, на вибрацию тайм-аут стоит 250мс - что будет если четверть секунды будет управление реагировать (?) - так не пойдет.

     

    Соотвественно нужен как бы "подключающий" скрипт для геймпада - будем надеяться, что BigWorld одинаков в самолетах и танках. Исходя из этого предположения нужно выбрать из WoWP методы для xbox геймпада и создать этот самый подключающий скрипт, который будет использоваться BigWorld и подключать геймпад так же как и клавиатуру/мышь.

     

    Взято из WoWP:

    '/scripts/client/input/InputSubsystem/GamepadInput.pyс'

    import Keys
    import BWPersonality
    from CameraStates import CameraState
    from EntityHelpers import EntityStates
    import GameEnvironment
    from ICMultiUpdate import ICMultiUpdate
    import InputMapping
    import math
    from MathExt import *
    from consts import ROLL_AXIS, VERTICAL_AXIS, HORIZONTAL_AXIS, FORCE_AXIS, FLAPS_AXIS
    from input.InputSubsystem.InputSubsystemBase import InputSubsystemBase
    import wgPickle
    
    class DummyMouseEvent:
    
        def __init__(self):
            self.dx = 0.0
            self.dy = 0.0
            self.dz = 0.0
    
        def comparison(a, b):
            return a.dx == b.dx and a.dy == b.dy
    
        def clone(self):
            res = DummyMouseEvent()
            res.dx = self.dx
            res.dy = self.dy
            return res
    
    
    class GamepadInput(InputSubsystemBase, ICMultiUpdate):
    
        def __init__(self, profile):
            self.__profile = profile
            self.__holdDirection = None
            self.__lastDirection = Math.Vector3()
            self.__isExtraMode = False
            self.__data = DummyMouseEvent()
            self.__lastValue = Math.Vector2(0.0, 0.0)
            self.__notControlledByUser = False
            self.__laseCameraState = None
    
            class JoyEvent:
    
                def __init__(self):
                    self.deviceId = None
                    self.axis = None
                    self.value = None
                    return
    
            joyEvent = JoyEvent()
            for deviceId in BWPersonality.axis:
                for axis in BWPersonality.axis[deviceId]:
                    joyEvent.deviceId = deviceId
                    joyEvent.axis = axis
                    joyEvent.value = BWPersonality.axis[deviceId][axis]
                    self.processJoystickEvent(joyEvent)
    
            BigWorld.player().onStateChanged += self.__ePlayerAvatarChangeState
            ICMultiUpdate.__init__(self, (0.05, self.__sendCursor))
            return
    
        def notControlledByUser(self, value):
            self.__notControlledByUser = value
    
        def __sendCursor(self):
            if not self.__isRunning:
                return
            direction = GameEnvironment.getCamera().getStateObject().strategy.cursorDirection
            BigWorld.player().cell.sendDirection(direction)
    
        def __CursorToCenter(self):
            player = BigWorld.player()
            rotation = Math.Quaternion()
            rotation.fromEuler(player.roll, player.pitch, player.yaw)
            self.__targetPoint = rotation.rotateVec(Math.Vector3(0.0, 0.0, 1.0))
    
        @property
        def __inGame(self):
            return EntityStates.inState(BigWorld.player(), EntityStates.GAME)
    
        @property
        def __inCameraState(self):
            return GameEnvironment.getCamera().getState() == CameraState.GamepadCombat or GameEnvironment.getCamera().getState() == CameraState.GamepadAssault
    
        @property
        def __isRunning(self):
            return self.__inGame and self.__inCameraState and not self.__notControlledByUser
    
        def __ePlayerAvatarChangeState(self, oldState, newState):
            pass
    
        def restart(self):
            pass
    
        def dispose(self):
            ICMultiUpdate._SuspendUpdates(self)
            self.__profile = None
            return
    
        def processJoystickEvent(self, event):
            if not self.__isRunning:
                return
            jSet = InputMapping.g_instance.joystickSettings
            if event.axis == jSet.ROLL_AXIS and (event.deviceId == jSet.ROLL_DEVICE or 0 == jSet.ROLL_DEVICE):
                rValue = InputMapping.translateAxisValue(jSet.AXIS_X_CURVE, event.value)
                if abs(rValue) <= jSet.ROLL_DEAD_ZONE:
                    self.__profile.sendPrimaryAxis(ROLL_AXIS, 0.0)
                else:
                    rValue = math.copysign((abs(rValue) - jSet.ROLL_DEAD_ZONE) / (1.0 - jSet.ROLL_DEAD_ZONE), rValue)
                    rValue = -rValue if jSet.INVERT_ROLL else rValue
                    rValue = math.copysign(math.pow(abs(rValue), 1.0 + 3.0 * (1.0 - jSet.ROLL_SENSITIVITY)), rValue)
                    self.__profile.sendPrimaryAxis(ROLL_AXIS, clamp(-1.0, -rValue, 1.0))
            elif event.axis == jSet.VERTICAL_AXIS and (event.deviceId == jSet.VERTICAL_DEVICE or 0 == jSet.VERTICAL_DEVICE):
                vValue = InputMapping.translateAxisValue(jSet.AXIS_Y_CURVE, event.value)
                if abs(vValue) <= jSet.VERTICAL_DEAD_ZONE:
                    self.__profile.sendPrimaryAxis(VERTICAL_AXIS, 0.0)
                else:
                    vValue = math.copysign((abs(vValue) - jSet.VERTICAL_DEAD_ZONE) / (1 - jSet.VERTICAL_DEAD_ZONE), vValue)
                    vValue = vValue if jSet.INVERT_VERTICAL else -vValue
                    vValue = math.copysign(math.pow(abs(vValue), 1.0 + 3.0 * (1.0 - jSet.VERTICAL_SENSITIVITY)), vValue)
                self.__lastValue.x = vValue
                GameEnvironment.getCamera().setRotationSpeed(Math.Vector2(math.radians(self.__lastValue.x * 45.0), math.radians(self.__lastValue.y * 45.0)))
            elif event.axis == jSet.HORIZONTAL_AXIS and (event.deviceId == jSet.HORIZONTAL_DEVICE or 0 == jSet.HORIZONTAL_DEVICE):
                hValue = InputMapping.translateAxisValue(jSet.AXIS_Z_CURVE, event.value)
                if abs(hValue) <= jSet.HORIZONTAL_DEAD_ZONE:
                    self.__profile.sendPrimaryAxis(HORIZONTAL_AXIS, 0.0)
                else:
                    hValue = math.copysign((abs(hValue) - jSet.HORIZONTAL_DEAD_ZONE) / (1 - jSet.HORIZONTAL_DEAD_ZONE), hValue)
                    hValue = -hValue if jSet.INVERT_HORIZONTAL else hValue
                    hValue = math.copysign(math.pow(abs(hValue), 1.0 + 3.0 * (1.0 - jSet.HORIZONTAL_SENSITIVITY)), hValue)
                    self.__profile.sendPrimaryAxis(HORIZONTAL_AXIS, clamp(-1.0, hValue, 1.0))
                self.__lastValue.y = hValue
                GameEnvironment.getCamera().setRotationSpeed(Math.Vector2(math.radians(self.__lastValue.x * 45.0), math.radians(self.__lastValue.y * 45.0)))
            elif event.axis == jSet.FORCE_AXIS and (event.deviceId == jSet.FORCE_DEVICE or 0 == jSet.FORCE_DEVICE):
                fValue = event.value
                if abs(fValue) < jSet.FORCE_DEAD_ZONE:
                    self.__profile.sendPrimaryAxis(FORCE_AXIS, 0.0)
                else:
                    fValue = math.copysign((abs(fValue) - jSet.FORCE_DEAD_ZONE) / (1 - jSet.FORCE_DEAD_ZONE), fValue)
                    fValue = -fValue if jSet.INVERT_FORCE else fValue
                    self.__profile.sendPrimaryAxis(FORCE_AXIS, self.__renormalization(fValue))
    
        def setCursorCamera(self, isCursorCamera):
            pass
    
        def __renormalization(self, x):
            maxForce = InputMapping.g_instance.joystickSettings.POINT_OF_NORMAL_THRUST
            if x >= 1.0:
                return 1
            elif x > maxForce and x < 1:
                return 0
            else:
                return (x + 1) / (maxForce + 1) - 1 

    '/scripts/client/InputMapping.pyс'

    import inspect
    import BigWorld
    from Event import Event
    import ResMgr
    import Keys
    import consts
    from db.DBHelpers import readValue
    from Helpers.i18n import makeString, localizeOptions
    from MathExt import *
    import math
    import threading
    from debug_utils import *
    from input.ProfileLoader.DummyDeviceLoader import MouseDummy
    from input.ProfileLoader.MouseLoader import MouseLoader
    from input.ProfileLoader.JoystickLoader import JoystickSettings
    from input.ProfileLoader.KeyMapingLoader import Keyboard
    from input.ProfileLoader.GamepadLoader import GamepadProfileLoader
    g_instance = None
    g_descriptions = None
    FORCE_DEFAULT_INPUT_PATH = False
    
    def initInput(profileName, profilesPresets):
        global g_instance
        global g_descriptions
        g_descriptions = CommandDescriptions()
        g_instance = InputMapping(profileName, profilesPresets)
    
    
    def translateAxisValue(axisCurve, axisValue):
        return math.copysign(axisCurve.calc(abs(axisValue)), axisValue)
    
    
    SENSITIVITY_MIN = 0.05
    SENSITIVITY_MAX = 2.5
    HI_AXIS_BOUND = 0.5
    LOW_AXIS_BOUND = 0.3
    
    def convertToRealSensitivity(sliderValue):
        return sliderValue * (SENSITIVITY_MAX - SENSITIVITY_MIN) + SENSITIVITY_MIN
    
    
    COMMANDS_TO_REFRESH = []
    COMMANDS_TO_NOT_REFRESH = []
    CHAT_COMMANDS = []
    EQUIPMENT_COMMANDS = []
    
    class CommandDescriptions(object):
        __DATA_PATH = 'scripts/command_mapping_description.xml'
    
        def __init__(self):
            self.__commands = {}
            rootSection = ResMgr.openSection(self.__DATA_PATH)
            commandIntID = 1
            for commandID, dataSection in rootSection.items():
                self.__commands[commandID] = CommandDescription(commandIntID)
                self.__commands[commandID].readFromDatasection(dataSection)
                globals()[commandID] = commandIntID
                commandIntID += 1
    
            if consts.IS_DEBUG_IMPORTED:
                from debug.AvatarDebug import DebugCommands
                self.loadMappingFromClass(DebugCommands, commandIntID)
            self.__fillGlobalCommandLists()
            ResMgr.purge(self.__DATA_PATH, True)
    
        def __fillGlobalCommandLists(self):
            global CHAT_COMMANDS
            global COMMANDS_TO_REFRESH
            global EQUIPMENT_COMMANDS
            global COMMANDS_TO_NOT_REFRESH
            COMMANDS_TO_REFRESH = [CMD_AUTOPILOT]
            COMMANDS_TO_NOT_REFRESH = [CMD_INTERMISSION_MENU,
             CMD_VISIBILITY_HUD,
             CMD_SHOW_CURSOR,
             CMD_HELP,
             CMD_SHOW_MAP]
            CHAT_COMMANDS = [CMD_F2_CHAT_COMMAND,
             CMD_F3_CHAT_COMMAND,
             CMD_F4_CHAT_COMMAND,
             CMD_F5_CHAT_COMMAND,
             CMD_F6_CHAT_COMMAND,
             CMD_F7_CHAT_COMMAND,
             CMD_F8_CHAT_COMMAND,
             CMD_F9_CHAT_COMMAND]
            EQUIPMENT_COMMANDS = [CMD_USE_EQUIPMENT_1, CMD_USE_EQUIPMENT_2, CMD_USE_EQUIPMENT_3]
    
        def loadMappingFromClass(self, classWithMapping, commandIntID):
            import inspect
            for commandID, value in inspect.getmembers(classWithMapping):
                if commandID.startswith('CMD_'):
                    self.__commands[commandID] = CommandDescription(commandIntID, 'DEBUG')
                    globals()[commandID] = commandIntID
                    commandIntID += 1
    
        @property
        def commands(self):
            return self.__commands
    
        def getCommandWaitTime(self, commandName):
            if commandName in self.__commands:
                command = self.__commands[commandName]
                return command.waitTime
            return 0.0
    
        def getCommandGroupID(self, commandName):
            if commandName in self.__commands:
                command = self.__commands[commandName]
                return command.groupID
            return ''
    
        def getCommandLocalizationID(self, commandName):
            if commandName in self.__commands:
                command = self.__commands[commandName]
                return command.localizationID
            return ''
    
        def getLinkedAxisName(self, commandName):
            if commandName in self.__commands:
                command = self.__commands[commandName]
                return command.linkedAxisName
            else:
                return ''
    
        def getCommandIntID(self, commandName):
            if commandName in self.__commands:
                command = self.__commands[commandName]
                return command.commandID
            return ''
    
        def getCommandNameByID(self, commandID):
            for commandName, command in self.__commands.items():
                if commandID == command.commandID:
                    return (commandName, command.groupName)
    
            return (None, None)
    
    
    class CommandDescription():
    
        def __init__(self, commandIntID, groupName = 'MAIN', groupID = 'SETTINGS_BASIC'):
            self.commandID = commandIntID
            self.linkedAxisName = ''
            self.localizationID = ''
            self.groupName = groupName
            self.groupID = groupID
            self.waitTime = 0.0
    
        def readFromDatasection(self, dataSection):
            readValue(self, dataSection, 'linkedAxisName', '')
            readValue(self, dataSection, 'localizationID', '')
            readValue(self, dataSection, 'groupName', 'MAIN')
            readValue(self, dataSection, 'groupID', 'SETTINGS_BASIC')
            readValue(self, dataSection, 'waitTime', 0.0)
    
    
    class InputMappingLoader(threading.Thread):
    
        def __init__(self, threadData, callback):
            threading.Thread.__init__(self)
            self.__threadData = threadData
            self.__callback = callback
    
        def run(self):
            self.__callback(self.__threadData)
    
    
    class InputMapping(object):
        __DATA_PATH = 'scripts/input_mapping/'
        __DEFAULTS_PATH = __DATA_PATH + 'defaults/'
        __DEFAULT_CONFIG_FILE_NAME = 'keyboard'
        __PRIMARY_SETTINGS_LOADERS = {consts.INPUT_SYSTEM_STATE.KEYBOARD: MouseDummy,
         consts.INPUT_SYSTEM_STATE.JOYSTICK: JoystickSettings,
         consts.INPUT_SYSTEM_STATE.GAMEPAD_DIRECT_CONTROL: JoystickSettings,
         consts.INPUT_SYSTEM_STATE.MOUSE: MouseLoader}
    
        @property
        def descriptions(self):
            return g_descriptions
    
        def __init__(self, currentProfileName, profilesPresets):
            self.__profileNames = self.loadProfileNames(profilesPresets)
            if ResMgr.useDefaultDataPath() or FORCE_DEFAULT_INPUT_PATH:
                self.__dataPath = self.__DATA_PATH
            else:
                self.__dataPath = ResMgr.getInputMappingPath(self.__DEFAULTS_PATH, '.xml', self.__profileNames)
            self.__checkInputFiles(self.__DEFAULTS_PATH, self.__dataPath)
            LOG_INFO('Input mapping data path: ' + self.__dataPath)
            if currentProfileName not in self.__profileNames:
                if self.__DEFAULT_CONFIG_FILE_NAME in self.__profileNames:
                    currentProfileName = self.__DEFAULT_CONFIG_FILE_NAME
                elif self.__profileNames:
                    currentProfileName = self.__profileNames[0]
                else:
                    LOG_ERROR('InputMapping::__init__ - can"t load current profile name:', currentProfileName)
            self.onDefaultMappingRestored = Event()
            self.onProfileLoaded = Event()
            self.__loadLock = threading.Lock()
            self.__loadInProgressProfile = None
            self.__load(currentProfileName, False, True, None)
            self.onSaveControls = Event()
            return
    
        def __loadLockAcquire(self):
            self.__loadLock.acquire()
    
        def __loadLockRelease(self):
            self.__loadLock.release()
    
        def __getCallbackClient(self):
            return self.__callbackClient
    
        def __setCallbackClient(self, val):
            self.__callbackClient = val
    
        callbackClient = property(__getCallbackClient, __setCallbackClient)
    
        def __checkInputFiles(self, defaultDataPath, actualDataPath):
            if defaultDataPath == actualDataPath:
                LOG_ERROR('defaultDataPath equals actualDataPath:', defaultDataPath)
            else:
                defaultlDataSection = ResMgr.openSection(defaultDataPath)
                if defaultlDataSection == None:
                    LOG_ERROR('default data section does not exist')
                else:
                    actualDataSection = ResMgr.openSection(actualDataPath)
                    if actualDataSection == None:
                        LOG_ERROR('data section must already exist', actualDataPath)
                    else:
                        for profile in self.__profileNames:
                            self.__checkInputFile(defaultlDataSection, actualDataSection, profile)
    
            return
    
        def __checkInputFile(self, defaultlDataSection, actualDataSection, profile):
            fileName = profile + '.xml'
            if not defaultlDataSection.has_key(fileName):
                LOG_ERROR('default data section does not contain file', fileName)
            else:
                defaultProfile = defaultlDataSection[fileName]
                if defaultProfile == None:
                    LOG_ERROR('cannot open default file', fileName)
                elif actualDataSection.has_key(fileName):
                    actualProfile = actualDataSection[fileName]
                    if actualProfile == None:
                        LOG_ERROR('cannot open file', fileName)
                    else:
                        defaultVersion = defaultProfile.readInt('FILE_VERSION', 0)
                        actualVersion = actualProfile.readInt('FILE_VERSION', 0)
                        if actualVersion < defaultVersion:
                            actualProfile.copy(defaultProfile)
                            actualProfile.save()
                            LOG_INFO('version mismatch, replaced', fileName, defaultVersion, actualVersion)
                else:
                    actualProfile = actualDataSection.createSection(fileName)
                    if actualProfile == None:
                        LOG_ERROR('cannot create new section', fileName)
                    else:
                        actualProfile.copy(defaultProfile)
                        actualProfile.save()
                        LOG_INFO('created profile from default', fileName)
            return
    
        def getAllCommandsIds(self):
            commadIds = list()
            for command in g_descriptions.commands.values():
                commadIds.append(command.commandID)
    
            return commadIds
    
        def getCommandsButtonsList(self, commandIDsList):
            from input.InputController import UserKeyEvent
            keys = []
            for commandID in commandIDsList:
                keyCodes = self.keyboardSettings.getCommandKeys(commandID)
                if keyCodes and len(keyCodes) > 0:
                    keyInfo = keyCodes[0]
                    keys.append(UserKeyEvent(keyInfo['code'], keyInfo['device']))
    
            return keys
    
        def getAllCommandsButtonsList(self, ignoreCommandIDsList):
            from input.InputController import UserKeyEvent
            keys = []
            for command in g_descriptions.commands.values():
                keyCodes = None
                if command.commandID not in ignoreCommandIDsList:
                    keyCodes = self.keyboardSettings.getCommandKeys(command.commandID)
                if keyCodes and len(keyCodes) > 0:
                    keyInfo = keyCodes[0]
                    keys.append(UserKeyEvent(keyInfo['code'], keyInfo['device']))
    
            return keys
    
        def getProfileNames(self):
            return self.__profileNames
    
        def loadProfileNames(self, profilesPresets):
            """
            @param profilesPresets: <dict> Ex.: {mouse_directional : [{name:mouse_directional, localizationID:CONTROL_PROFILE_DEFAULT}] }
            @return: <list>
            """
            profiles = []
            rootSection = ResMgr.openSection(self.__DEFAULTS_PATH)
            for fileName in rootSection.keys():
                extentionPos = fileName.find('.xml')
                if extentionPos != -1:
                    profileName = fileName[0:extentionPos]
                    isPreset = False
                    if not isPreset:
                        profiles.append(profileName)
    
            ResMgr.purge(self.__DEFAULTS_PATH, True)
            return profiles
    
        def getLocalizedProfileNameCaps(self, profileName = None):
            if profileName is None:
                profileName = self.getCurProfileName()
            return localizeOptions('CONTROL_PROFILE_%s_CAPS' % profileName.upper())
    
        def getLocalizedProfileName(self, profileName = None):
            if profileName is None:
                profileName = self.getCurProfileName()
            return localizeOptions('CONTROL_PROFILE_%s' % profileName.upper())
    
        def getLocalizedProfileNames(self):
            locProfiles = []
            profiles = self.getProfileNames()
            for profile in profiles:
                locProfiles.append(localizeOptions('CONTROL_PROFILE_' + profile.upper()))
    
            return locProfiles
    
        def getProfileNameByIndex(self, index):
            profiles = self.getProfileNames()
            return profiles[index]
    
        def isCommandKey(self, command, key, keyDevice, axisIndex = -1, axisDevice = 0):
            return self.keyboardSettings.isCommandKey(command, key, keyDevice, axisIndex, axisDevice)
    
        def isMouseActivateEvent(self, key, event):
            if isinstance(event, BigWorld.KeyEvent):
                return event.wg_isMouseActivateEvent
            return False
    
        def setSwitchingStyle(self, command, switchingStyle):
            self.keyboardSettings.setSwitchingStyle(command, switchingStyle)
    
        def getSwitchingStyle(self, command):
            return self.keyboardSettings.getSwitchingStyle(command)
    
        def invertY(self):
            self.keyboardSettings.INVERT_Y = 1 - self.keyboardSettings.INVERT_Y
            self.primarySettings.INVERT_Y = 1 - self.primarySettings.INVERT_Y
    
        @property
        def mouseSettings(self):
            return self.primarySettings
    
        @property
        def joystickSettings(self):
            return self.primarySettings
    
        def __saveProfile(self, rootSection, profilePath):
            try:
                rootSection.save()
            except IOError:
                LOG_ERROR("Couldn't save profile: " + profilePath)
            else:
                LOG_DEBUG('Controls saved to ' + profilePath)
    
            ResMgr.purge(profilePath, True)
    
        def saveControlls(self, curProfileName, profileNameKeyBoard = None):
            if self.__loadInProgressProfile:
                LOG_INFO('::saveControlls: Save rejected. Profile %s is loading' % self.__loadInProgressProfile['profileName'])
                return
            else:
                try:
                    self.__loadLockAcquire()
                    profilePath = ''.join([self.__dataPath, self.__curProfileName if curProfileName is None else curProfileName, '.xml'])
                    rootSection = ResMgr.openSection(profilePath)
                    self.keyboardSettings.flash(rootSection['KEYBOARD'])
                    self.primarySettings.flash(rootSection['PRIMARY'])
                    self.__saveProfile(rootSection, profilePath)
                    if profileNameKeyBoard is not None:
                        LOG_INFO('saveControlls - save KEYBOARD to %s.xml curProfileName=%s' % (profileNameKeyBoard, curProfileName))
                        keyBoardPath = ''.join([self.__dataPath, profileNameKeyBoard, '.xml'])
                        keyBoardRootSection = ResMgr.openSection(keyBoardPath)
                        self.keyboardSettings.flash(keyBoardRootSection['KEYBOARD'])
                        self.__saveProfile(keyBoardRootSection, keyBoardPath)
                    self.onSaveControls()
                except:
                    LOG_CURRENT_EXCEPTION()
                finally:
                    self.__loadLockRelease()
    
                return
    
        def getCurProfileName(self):
            return self.__curProfileName
    
        def setCurProfileName(self, ProfileName):
            LOG_INFO('setCurProfileName - old=(%s), new=(%s)' % (self.__curProfileName, ProfileName))
            self.__curProfileName = ProfileName
    
        def getCurProfileIndex(self):
            profiles = self.getProfileNames()
            return profiles.index(self.__curProfileName)
    
        def changeProfile(self, profileName):
            self.__load(profileName, False, True, None)
            return
    
        def loadProfileFromPreset(self, profileName, loadFromDefaults, profileNameForKeyboardSettings):
            self.__load(profileName, loadFromDefaults, False, profileNameForKeyboardSettings)
    
        def restoreDefaultsCommandMapping(self):
            self.__load(self.__curProfileName, True, True, None)
            return
    
        def getCurMapping(self):
            return self.keyboardSettings.getCurMapping(self.joystickSettings)
    
        def applyNewMapping(self, mapping):
            self.keyboardSettings.applyNewMapping(mapping, self.joystickSettings)
    
        def setKeyboardLining(self, value):
            self.keyboardSettings.setLining(value)
    
        def getKeyboardLining(self):
            return self.keyboardSettings.getLining()
    
        def getLocalizedCommandKeysAndAxes(self, commandName):
            """
            Returns list with localized names of keys/axes that correspond to given command or empty list
            @param commandName: command name from command_mapping_description.xml
            @rtype: list
            """
            keysControls = []
            curMapping = self.getCurMapping()
            record = curMapping.get(g_descriptions.getCommandIntID(commandName), None)
            if record is not None:
                for key in record['keyNames']:
                    if 'KEY_NONE' != key['name']:
                        keysControls.append(getKeyLocalization(key['name']))
    
                if not self.currentProfileType == consts.INPUT_SYSTEM_STATE.KEYBOARD:
                    if not self.currentProfileType == consts.INPUT_SYSTEM_STATE.MOUSE:
                        if record['linkedAxisIndex'] != -1:
                            keysControls.append(getAxisLocalization(record['linkedAxisIndex']))
                        record['fireAxisIndex'] != -1 and keysControls.append(getAxisLocalization(record['fireAxisIndex']))
            return keysControls
    
        def getKeyControlsHelp(self, dataKeysControls):
            keysControls = {}
            curMapping = self.getCurMapping()
            for cmdID, record in curMapping.items():
                cmdLabel = getCommandLocalization(record['cmdName'])
                if cmdLabel is not None and cmdID in dataKeysControls:
                    keysControls[cmdID] = {'keys': [],
                     'isFireAxis': [],
                     'axisSign': []}
                    for key in record['keyNames']:
                        if 'KEY_NONE' != key['name']:
                            keysControls[cmdID]['keys'].append(key['name'])
                            keysControls[cmdID]['isFireAxis'].append(False)
                            keysControls[cmdID]['axisSign'].append(0)
    
                    if record['linkedAxisIndex'] != -1:
                        keysControls[cmdID]['keys'].append('_'.join(['AXIS', str(record['linkedAxisIndex'])]))
                        keysControls[cmdID]['isFireAxis'].append(False)
                        keysControls[cmdID]['axisSign'].append(0)
                    elif record['fireAxisIndex'] != -1:
                        keysControls[cmdID]['keys'].append('_'.join(['AXIS', str(record['fireAxisIndex'])]))
                        keysControls[cmdID]['isFireAxis'].append(True)
                        keysControls[cmdID]['axisSign'].append(record['fireAxisSign'])
    
            return keysControls
    
        def __load(self, profileName, loadFromDefaults, isOverrideCurProfileName, profileNameForKeyboardSettings, loadFromDefaultsKeyboardSettings = False):
            if isOverrideCurProfileName:
                self.__curProfileName = profileName
            profilePath = profileName + '.xml'
            profilePath = self.__DEFAULTS_PATH + profilePath if loadFromDefaults else self.__dataPath + profilePath
            LOG_DEBUG("Try to load config profile '%s'" % profileName)
            o = dict(profileName=self.__curProfileName, loadFromDefaults=loadFromDefaults)
            resources = (profilePath,)
            if profileNameForKeyboardSettings is not None:
                o['profileNameForKeyboardSettings'] = profileNameForKeyboardSettings
                o['loadFromDefaultsKeyboardSettings'] = loadFromDefaultsKeyboardSettings
                profilePathForKeyboardSettings = self.__DEFAULTS_PATH + profileNameForKeyboardSettings + '.xml' if loadFromDefaultsKeyboardSettings else self.__dataPath + profileNameForKeyboardSettings + '.xml'
                resources = (profilePath, profilePathForKeyboardSettings)
            self.__loadInProgressProfile = o
            BigWorld.loadResourceListBG(resources, self.__profileDataSectionLoaded, 64, o)
            return
    
        @property
        def currentProfileType(self):
            return self.__currentProfileType
    
        def __profileDataSectionLoaded(self, resourceRefs):
            profilePath = resourceRefs.resourceIDs[0]
            LOG_DEBUG("Loading config profile from '%s'" % profilePath, resourceRefs.has_key(profilePath))
            if not resourceRefs.has_key(profilePath):
                LOG_DEBUG("Can't load '%s'" % profilePath)
                if resourceRefs.extraData['loadFromDefaults']:
                    if resourceRefs.extraData['profileName'] != self.__DEFAULT_CONFIG_FILE_NAME:
                        self.__load(self.__DEFAULT_CONFIG_FILE_NAME, True, True, None)
                    else:
                        LOG_ERROR("Can't load system configs")
                else:
                    self.__load(resourceRefs.extraData['profileName'], True, True, None)
            else:
                LOG_DEBUG('Profile successfully loaded')
                rootSection = resourceRefs[profilePath]
                if self.__loadInProgressProfile == resourceRefs.extraData:
                    self.__loadLockAcquire()
                    try:
                        s = rootSection.readString('TYPE')
                        try:
                            self.__currentProfileType = consts.INPUT_SYSTEM_STATE.__dict__[s]
                        except KeyError:
                            LOG_DEBUG('Bad profile type - [' + str(s) + '] in ' + profilePath)
                            raise
    
                        rootSectionKeyboard = rootSection
                        if len(resourceRefs.resourceIDs) > 1 and 'profileNameForKeyboardSettings' in resourceRefs.extraData:
                            keyboardPath = resourceRefs.resourceIDs[1]
                            if resourceRefs.has_key(keyboardPath):
                                rootSectionKeyboard = resourceRefs[keyboardPath]
                                LOG_INFO('__profileDataSectionLoaded - KEYBOARD loaded from %s profilePath=%s' % (keyboardPath, profilePath))
                                ResMgr.purge(keyboardPath, True)
                        self.keyboardSettings = Keyboard(rootSectionKeyboard['KEYBOARD'])
                        profileLoaderClass = self.__PRIMARY_SETTINGS_LOADERS.get(self.currentProfileType, None)
                        if profileLoaderClass is not None:
                            self.primarySettings = profileLoaderClass(rootSection['PRIMARY'])
                        else:
                            LOG_INFO('::__profileDataSectionLoaded: Profile [%s],ProfileType[%s] ignored as an obsolete loading' % (profilePath, self.currentProfileType))
                        ResMgr.purge(profilePath, True)
                        self.onProfileLoaded()
                    except:
                        LOG_CURRENT_EXCEPTION()
                    finally:
                        self.__loadLockRelease()
                        self.__loadInProgressProfile = None
    
                else:
                    LOG_INFO('::__profileDataSectionLoaded: Profile [%s] ignored as an obsolete loading' % profilePath)
            return
    
    
    class Command():
        MODIFIERS = {'ALT': lambda : BigWorld.isKeyDown(Keys.KEY_RALT, 0) or BigWorld.isKeyDown(Keys.KEY_LALT, 0),
         'SHIFT': lambda : BigWorld.isKeyDown(Keys.KEY_RSHIFT, 0) or BigWorld.isKeyDown(Keys.KEY_LSHIFT, 0),
         'CTRL': lambda : BigWorld.isKeyDown(Keys.KEY_RCONTROL, 0) or BigWorld.isKeyDown(Keys.KEY_LCONTROL, 0),
         'RALT': lambda : BigWorld.isKeyDown(Keys.KEY_RALT, 0),
         'LALT': lambda : BigWorld.isKeyDown(Keys.KEY_LALT, 0),
         'LCTRL': lambda : BigWorld.isKeyDown(Keys.KEY_LCONTROL, 0),
         'RCTRL': lambda : BigWorld.isKeyDown(Keys.KEY_RCONTROL, 0)}
    
        def __init__(self, id, linkedAxisName, fireAxisIndex, fireAxisSign, fireAxisDevice, keyNames, modifier, isBlock, isBase, switchingStyle):
            self.id = id
            self.linkedAxisName = linkedAxisName
            self.fireAxisIndex = fireAxisIndex
            self.fireAxisSign = fireAxisSign
            self.fireAxisDevice = fireAxisDevice
            self.__modifierFnc = Command.MODIFIERS.get(modifier, None)
            self.applyNewKeys(keyNames)
            self.isBlock = isBlock
            self.isBase = isBase
            self.switchingStyle = switchingStyle
            self.lastExecuteTime = 0.0
            return
    
        def checkKey(self, key, keyDevice):
            for keyRecord in self.__keys:
                if key == keyRecord['code'] and (keyDevice == keyRecord['device'] or keyRecord['device'] == 0):
                    return keyRecord
    
            return False
    
        def checkAxis(self, axisIndex, axisDevice):
            import BWPersonality
            if axisIndex != -1 and self.fireAxisIndex != -1:
                if self.fireAxisDevice == 0 or self.fireAxisDevice == axisDevice:
                    return self.fireAxisIndex == axisIndex and axisIndex in BWPersonality.axis[axisDevice]
            return False
    
        def isModifierActive(self):
            return self.__modifierFnc is None or self.__modifierFnc()
    
        def isCommandActive(self):
            import BWPersonality
            if self.fireAxisIndex != -1:
                for device, axes in BWPersonality.axis.items():
                    if (device == self.fireAxisDevice or self.fireAxisDevice == 0) and self.fireAxisIndex in axes:
                        axisValue = axes[self.fireAxisIndex]
                        if sign(axisValue) == sign(self.fireAxisSign) and abs(axisValue) > HI_AXIS_BOUND:
                            return True
    
            for key in self.__keys:
                if BigWorld.isKeyDown(key['code'], key['device']):
                    return True
    
            return False
    
        def clear(self):
            self.__keys = []
    
        def flash(self, rootSection):
            rootSection.deleteSection(self.id)
            section = rootSection.createSection(self.id)
            keysSection = section.createSection('FIRE_KEYS')
            for key in self.__keys:
                keySection = keysSection.createSection('FIRE_KEY')
                keySection.writeString('fireKeyName', key['name'])
                keySection.writeInt64('fireKeyDevice', key['device'])
    
            section.writeInt('fireAxisIndex', self.fireAxisIndex)
            section.writeInt('fireAxisSign', self.fireAxisSign)
            section.writeInt64('fireAxisDevice', self.fireAxisDevice)
            section.writeInt('isBase', self.isBase)
            section.writeInt('switchingStyle', self.switchingStyle)
    
        def getMappedKeyCodes(self):
            return self.__keys
    
        def applyNewKeys(self, keyNames):
            """
            Fill 'code'(int keyCode) for all keys in record and drop all last empty keys
            
            keyNames : {'name':str,'device':UINT}
            
            """
            self.__keys = keyNames
            keyIndex = 0
            lastValidKeyIndex = 0
            for key in self.__keys:
                key['code'] = getKeyCodeByName(key['name'])
                keyIndex += 1
                if key['name'] != 'KEY_NONE':
                    lastValidKeyIndex = keyIndex
    
            self.__keys = self.__keys[:lastValidKeyIndex]
    
    
    def getKeyNameByCode(keyCode):
        if keyCode == 0:
            return 'KEY_NONE'
        for k, v in Keys.__dict__.items():
            if v == keyCode:
                return k
    
        return 'KEY_NONE'
    
    
    def getKeyCodeByName(keyName):
        if keyName in Keys.__dict__:
            return int(Keys.__dict__.get(keyName))
        else:
            return 0
    
    
    def getKeyLocalization(keyName):
        return makeString('#keys:' + keyName)
    
    
    def getAxisLocalization(axisIndex):
        if axisIndex == -1:
            return ''
        return getKeyLocalization('_'.join(['AXIS', str(axisIndex)]))
    
    
    def getCommandLocalization(commandName):
        localizationID = g_descriptions.getCommandLocalizationID(commandName)
        if localizationID == '':
            return None
        else:
            return makeString('#options:KEYMAPPING/' + localizationID)
            return None 

    '/scripts/client/input/Profile/GamepadProfile.pyс'

    import BigWorld
    import GameEnvironment
    from ICMultiUpdate import ICMultiUpdate
    import InputMapping
    from MathExt import clamp, FloatToCInt16
    import math
    from _preparedBattleData_db import preparedBattleData
    from consts import FORCE_AXIS, FLAPS_AXIS, ROLL_AXIS, VERTICAL_AXIS, HORIZONTAL_AXIS
    from input.InputSubsystem.GamepadInput import GamepadInput
    from input.InputSubsystem.KeyboardInput import KeyboardInput
    from input.Profile.ProfileBase import IProfileBase
    
    class GamepadProfile(IProfileBase, ICMultiUpdate):
    
        def __init__(self, inputAxis, notControlledByUser):
            self._notControlledByUser = notControlledByUser
            self._forciblySendAxis = False
            InputMapping.g_instance.onSaveControls += self._onSaveControls
            self.__axisKeyBoard = [0.0] * 5
            self.__axisJoy = [0.0] * 5
            self.__lastAxis = [0.0] * 5
            self.__gamepad = GamepadInput(self)
            self.__keyboard = KeyboardInput(self)
            self._onSaveControls()
    
        def getCurrentForce(self):
            return self.__axisJoy[FORCE_AXIS]
    
        def dispose(self):
            InputMapping.g_instance.onSaveControls -= self._onSaveControls
            self.__gamepad.dispose()
            self.__keyboard.dispose()
            self.__gamepad = None
            self.__keyboard = None
            return
    
        def restart(self):
            pass
    
        def _onSaveControls(self):
            pass
    
        def setCamDirection(self, direction):
            pass
    
        def __send(self, axis):
            player = BigWorld.player()
            value = self.__axisJoy[axis] * (1.0 - abs(self.__axisKeyBoard[axis])) + self.__axisKeyBoard[axis]
            if self.__lastAxis[axis] != value:
                player.cell.sendInputJoyAxis(axis, FloatToCInt16(value))
                player.applyInputAxis(axis, value)
                self.__lastAxis[axis] = value
    
        def sendAxis(self, axis, value):
            self.__axisKeyBoard[axis] = value
            if self._notControlledByUser:
                return
            self.__send(axis)
    
        def sendPrimaryAxis(self, axis, value):
            self.__axisJoy[axis] = value
            if self._notControlledByUser:
                return
            self.__send(axis)
    
        def notControlledByUser(self, value):
            self._notControlledByUser = value
            self.__gamepad.notControlledByUser(value)
            if not self._notControlledByUser:
                for axis in range(0, 5):
                    self.__send(axis)
    
        def processMouseEvent(self, event):
            pass
    
        def processJoystickEvent(self, event):
            self.__gamepad.processJoystickEvent(event)
    
        def addCommandListeners(self, processor):
            self.__keyboard.addCommandListeners(processor)
    
        def removeCommandListeners(self, processor):
            self.__keyboard.removeCommandListeners(processor)
    
        def __autopilotUpdate(self):
            """successor should provide an update of this method through its own ICMultiUpdate """
            owner = BigWorld.player()
            if abs(owner.pitch) < 0.25 * math.pi:
                rollAxis = owner.roll * 0.5
                rollAxis = min(1.0, max(-1.0, rollAxis))
                owner.applyInputAxis(ROLL_AXIS, -rollAxis)
            pitchAxis = owner.pitch
            pitchAxis = min(1.0, max(-1.0, pitchAxis))
            owner.applyInputAxis(VERTICAL_AXIS, pitchAxis)
            owner.applyInputAxis(HORIZONTAL_AXIS, 0) 

    '\scripts\input_mapping\defaults\gamepad_dc_1_xbox_360.xml'

    <gamepad_dc_1_xbox_360.xml>
      <FILE_VERSION>	66	</FILE_VERSION>
      <TYPE>GAMEPAD_DIRECT_CONTROL</TYPE>
      <PRIMARY>
        <COMMON>
          <TOP_ROLL_BOUND>	30	</TOP_ROLL_BOUND>
          <BOTTOM_ROLL_BOUND>	25	</BOTTOM_ROLL_BOUND>
          <ROLL_LINING_ZONE>2.0</ROLL_LINING_ZONE>
          <SEALING_SPLINE>
            <p>0.0  0.8</p>
            <p>0.4  0.9</p>
            <p>0.7  0.95</p>
            <p>0.95 1.0</p>
            <pointCount>	100	</pointCount>
          </SEALING_SPLINE>
          <BOTTOM_BLOCK_ROLL>30.0</BOTTOM_BLOCK_ROLL>
          <ROLL_BASIS>0.7</ROLL_BASIS>
          <VERTICAL_POW>	1	</VERTICAL_POW>
          <HORIZONTAL_POW>	1	</HORIZONTAL_POW>
          <VERTICAL_POW_INNER>0.8</VERTICAL_POW_INNER>
          <HORIZONTAL_POW_INNER>0.8</HORIZONTAL_POW_INNER>
          <ROLL_POW>1.0</ROLL_POW>
        </COMMON>
        <INVERT_Y>	1	</INVERT_Y>
        <AUTOMATIC_FLAPS>	false	</AUTOMATIC_FLAPS>
        <ROLL_AXIS>	0	</ROLL_AXIS>
        <VERTICAL_AXIS>	1	</VERTICAL_AXIS>
        <FORCE_AXIS>	4	</FORCE_AXIS>
        <HORIZONTAL_AXIS>	3	</HORIZONTAL_AXIS>
        <INVERT_ROLL>	0	</INVERT_ROLL>
        <INVERT_VERTICAL>	0	</INVERT_VERTICAL>
        <INVERT_FORCE>	0	</INVERT_FORCE>
        <INVERT_HORIZONTAL>	0	</INVERT_HORIZONTAL>
        <AXIS_X_CURVE>
          <p>0.0 0.00</p>
          <p>0.01 0.01</p>
          <p>0.1 0.1</p>
          <p>0.2 0.2</p>
          <p>0.3 0.3</p>
          <p>0.4 0.4</p>
          <p>0.5 0.5</p>
          <p>0.6 0.6</p>
          <p>0.7 0.7</p>
          <p>0.8 0.8</p>
          <p>0.9 0.9</p>
          <p>1.0 1.0</p>
          <pointCount>	100	</pointCount>
        </AXIS_X_CURVE>
        <AXIS_Y_CURVE>
          <p>0.0 0.00</p>
          <p>0.01 0.01</p>
          <p>0.1 0.1</p>
          <p>0.2 0.2</p>
          <p>0.3 0.3</p>
          <p>0.4 0.4</p>
          <p>0.5 0.5</p>
          <p>0.6 0.6</p>
          <p>0.7 0.7</p>
          <p>0.8 0.8</p>
          <p>0.9 0.9</p>
          <p>1.0 1.0</p>
          <pointCount>	100	</pointCount>
        </AXIS_Y_CURVE>
        <AXIS_Z_CURVE>
          <p>0.0 0.00</p>
          <p>0.01 0.001</p>
          <p>0.1 0.1</p>
          <p>0.2 0.2</p>
          <p>0.3 0.3</p>
          <p>0.4 0.4</p>
          <p>0.5 0.5</p>
          <p>0.6 0.6</p>
          <p>0.7 0.7</p>
          <p>0.8 0.8</p>
          <p>0.9 0.9</p>
          <p>1.0 1.0</p>
          <pointCount>	100	</pointCount>
        </AXIS_Z_CURVE>
        <ROLL_SENSITIVITY>	1,000000	</ROLL_SENSITIVITY>
        <ROLL_DEAD_ZONE>	0,100000	</ROLL_DEAD_ZONE>
        <VERTICAL_SENSITIVITY>	1,000000	</VERTICAL_SENSITIVITY>
        <VERTICAL_DEAD_ZONE>	0,100000	</VERTICAL_DEAD_ZONE>
        <FORCE_SENSITIVITY>	1,000000	</FORCE_SENSITIVITY>
        <FORCE_DEAD_ZONE>	0,100000	</FORCE_DEAD_ZONE>
        <HORIZONTAL_SENSITIVITY>	1,000000	</HORIZONTAL_SENSITIVITY>
        <HORIZONTAL_DEAD_ZONE>	0,100000	</HORIZONTAL_DEAD_ZONE>
        <ROLL_DEVICE>	0	</ROLL_DEVICE>
        <VERTICAL_DEVICE>	0	</VERTICAL_DEVICE>
        <FORCE_DEVICE>	0	</FORCE_DEVICE>
        <HORIZONTAL_DEVICE>	0	</HORIZONTAL_DEVICE>
        <POINT_OF_NORMAL_THRUST>	0,000000	</POINT_OF_NORMAL_THRUST>
        <SLIP_COMPENSATION>	true	</SLIP_COMPENSATION>
        <SWITCHING_STYLE>	0	</SWITCHING_STYLE>
      </PRIMARY>
      <KEYBOARD>
        <INVERT_Y>	1	</INVERT_Y>
        <YAW_SPEED_CURVE>
          <p>0.0  0.0</p>
          <p>0.1  0.05</p>
          <p>0.2  0.2</p>
          <p>0.3  0.3</p>
          <p>0.5  0.6</p>
          <p>0.8  0.9</p>
          <p>1.0  1.0</p>
          <pointCount>	100	</pointCount>
        </YAW_SPEED_CURVE>
        <ROLL_SPEED_CURVE>
          <p>0.0  0.0</p>
          <p>0.1  0.05</p>
          <p>0.2  0.2</p>
          <p>0.3  0.3</p>
          <p>0.5  0.6</p>
          <p>0.8  0.9</p>
          <p>1.0  1.0</p>
          <pointCount>	100	</pointCount>
        </ROLL_SPEED_CURVE>
        <PITCH_SPEED_CURVE>
          <p>0.0  0.0</p>
          <p>0.1  0.05</p>
          <p>0.2  0.2</p>
          <p>0.3  0.3</p>
          <p>0.5  0.6</p>
          <p>0.8  0.9</p>
          <p>1.0  1.0</p>
          <pointCount>	100	</pointCount>
        </PITCH_SPEED_CURVE>
        <KEY_SENSITIVITY>	0,500000	</KEY_SENSITIVITY>
        <ENABLE_LINING>	1	</ENABLE_LINING>
        <MAPPING>
          <MAIN>
            <CMD_BATTLE_MODE>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_LSHIFT</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOYL2</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	0	</switchingStyle>
            </CMD_BATTLE_MODE>
            <CMD_PITCH_DOWN>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_UPARROW</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	1	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_PITCH_DOWN>
            <CMD_PITCH_UP>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_DOWNARROW</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	-1	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_PITCH_UP>
            <CMD_ROLL_LEFT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_LEFTARROW</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	-1	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_ROLL_LEFT>
            <CMD_ROLL_RIGHT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_RIGHTARROW</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	1	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_ROLL_RIGHT>
            <CMD_USE_EQUIPMENT_1>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_4</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_1</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
              <isBase>	0	</isBase>
            </CMD_USE_EQUIPMENT_1>
            <CMD_USE_EQUIPMENT_2>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_5</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_2</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
              <isBase>	0	</isBase>
            </CMD_USE_EQUIPMENT_2>
            <CMD_USE_EQUIPMENT_3>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_6</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_3</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
              <isBase>	0	</isBase>
            </CMD_USE_EQUIPMENT_3>
            <CMD_TURN_LEFT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_A</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	-1	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_TURN_LEFT>
            <CMD_TURN_RIGHT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_D</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	1	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_TURN_RIGHT>
            <CMD_PRIMARY_FIRE>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_SPACE</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	2	</fireAxisIndex>
              <fireAxisSign>	1	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_PRIMARY_FIRE>
            <CMD_LAUNCH_ROCKET>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_R</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOYY</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	1	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_LAUNCH_ROCKET>
            <CMD_LAUNCH_BOMB>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_B</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOY9</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_LAUNCH_BOMB>
            <CMD_INCREASE_FORCE>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_W</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	1	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	1	</switchingStyle>
            </CMD_INCREASE_FORCE>
            <CMD_ENGINE_OFF>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_S</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	-1	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_ENGINE_OFF>
            <CMD_FLAPS_UP>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_E</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	2	</fireAxisIndex>
              <fireAxisSign>	-1	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_FLAPS_UP>
            <CMD_SHOW_PLAYERS_INFO>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_LALT</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SHOW_PLAYERS_INFO>
            <CMD_LOCK_TARGET>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_C</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <switchingStyle>	-1	</switchingStyle>
              <isBase>	0	</isBase>
            </CMD_LOCK_TARGET>
            <CMD_LOCK_TARGET_IN_SCREEN_CENTER>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NONE</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOYSQUARE</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_LOCK_TARGET_IN_SCREEN_CENTER>
            <CMD_NEXT_TARGET>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_X</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOY8</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_NEXT_TARGET>
            <CMD_NEXT_TARGET_TEAM_OBJECT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_V</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_NEXT_TARGET_TEAM_OBJECT>
            <CMD_SHOW_MAP>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_M</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SHOW_MAP>
            <CMD_SHOW_CURSOR>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_LCONTROL</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_RCONTROL</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SHOW_CURSOR>
            <CMD_MINIMAP_ZOOM_IN>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_RBRACKET</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_MINIMAP_ZOOM_IN>
            <CMD_MINIMAP_ZOOM_OUT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_LBRACKET</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_MINIMAP_ZOOM_OUT>
            <CMD_MINIMAP_SIZE_INC>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_EQUALS</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_ADD</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_MINIMAP_SIZE_INC>
            <CMD_MINIMAP_SIZE_DEC>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_MINUS</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_NUMPADMINUS</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_MINIMAP_SIZE_DEC>
            <CMD_SNIPER_CAMERA>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_F</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOY15</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	0	</switchingStyle>
            </CMD_SNIPER_CAMERA>
            <CMD_BOMBING_SIGHT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_H</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	0	</switchingStyle>
            </CMD_BOMBING_SIGHT>
            <CMD_CURSOR_CAMERA>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_MOUSE1</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_CURSOR_CAMERA>
            <CMD_TARGET_CAMERA>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_G</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	1	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_TARGET_CAMERA>
            <CMD_BACK_VIEW>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_Q</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_BACK_VIEW>
            <CMD_SIDE_VIEW_LEFT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NUMPAD4</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOYPOVLEFT</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SIDE_VIEW_LEFT>
            <CMD_SIDE_VIEW_RIGHT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NUMPAD6</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOYPOVRIGHT</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SIDE_VIEW_RIGHT>
            <CMD_SIDE_VIEW_UP>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NUMPAD8</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOYPOVUP</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SIDE_VIEW_UP>
            <CMD_SIDE_VIEW_DOWN>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NUMPAD2</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOYPOVDOWN</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SIDE_VIEW_DOWN>
            <CMD_SIDE_VIEW_DOWN_LEFT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NUMPAD1</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOYPOVDOWNLEFT</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SIDE_VIEW_DOWN_LEFT>
            <CMD_SIDE_VIEW_DOWN_RIGHT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NUMPAD3</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOYPOVDOWNRIGHT</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SIDE_VIEW_DOWN_RIGHT>
            <CMD_SIDE_VIEW_UP_LEFT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NUMPAD7</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOYPOVUPLEFT</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SIDE_VIEW_UP_LEFT>
            <CMD_SIDE_VIEW_UP_RIGHT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NUMPAD9</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_JOYPOVUPRIGHT</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SIDE_VIEW_UP_RIGHT>
            <CMD_SIDE_CAMERA_ALT>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NUMPAD5</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SIDE_CAMERA_ALT>
            <CMD_PUSH_TO_TALK>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_GRAVE</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_PUSH_TO_TALK>
            <CMD_PUSH_TO_TALK_SQUAD>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_Z</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	0	</switchingStyle>
            </CMD_PUSH_TO_TALK_SQUAD>
            <CMD_TOGGLE_ARENA_VOICE_CHANNEL>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_Y</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_TOGGLE_ARENA_VOICE_CHANNEL>
            <CMD_SHOW_TEAMS>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_TAB</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_SHOW_TEAMS>
            <CMD_F2_CHAT_COMMAND>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_F5</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_F2_CHAT_COMMAND>
            <CMD_F3_CHAT_COMMAND>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_F6</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_F3_CHAT_COMMAND>
            <CMD_F4_CHAT_COMMAND>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_F4</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_F4_CHAT_COMMAND>
            <CMD_F5_CHAT_COMMAND>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_F7</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_F5_CHAT_COMMAND>
            <CMD_F6_CHAT_COMMAND>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_F8</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_F6_CHAT_COMMAND>
            <CMD_F7_CHAT_COMMAND>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_F9</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_F7_CHAT_COMMAND>
            <CMD_F8_CHAT_COMMAND>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_F2</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_F8_CHAT_COMMAND>
            <CMD_F9_CHAT_COMMAND>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_F3</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
                <FIRE_KEY>
                  <fireKeyName>KEY_T</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_F9_CHAT_COMMAND>
            <CMD_HELP>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_F1</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	1	</switchingStyle>
            </CMD_HELP>
            <CMD_FIRE_GROUP_1>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NONE</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_FIRE_GROUP_1>
            <CMD_FIRE_GROUP_2>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NONE</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_FIRE_GROUP_2>
            <CMD_FIRE_GROUP_3>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_NONE</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_FIRE_GROUP_3>
            <CMD_AUTOPILOT>
              <FIRE_KEYS>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_AUTOPILOT>
            <CMD_INTERMISSION_MENU>
              <FIRE_KEYS>
                <FIRE_KEY>
                  <fireKeyName>KEY_ESCAPE</fireKeyName>
                  <fireKeyDevice>	0	</fireKeyDevice>
                </FIRE_KEY>
              </FIRE_KEYS>
              <fireAxisIndex>	-1	</fireAxisIndex>
              <fireAxisSign>	0	</fireAxisSign>
              <fireAxisDevice>	0	</fireAxisDevice>
              <isBase>	0	</isBase>
              <switchingStyle>	-1	</switchingStyle>
            </CMD_INTERMISSION_MENU>
          </MAIN>
        </MAPPING>
      </KEYBOARD>
    </gamepad_dc_1_xbox_360.xml> 

    Может кто подскажет дельное что-нибудь.


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

    • Upvote 1
    • Downvote 1
  12. Оказывается WoT принимает команды от геймпада почти "по-умолчанию". Спасибо inj3ct0r (я тебе должен) - подсказал как это проверить и дал скрипт, для отлавливания нажатий клавиш в ангаре с выводом системных сообщений.

    post-19155-0-28963800-1396032890_thumb.jpg

    Подключив геймпад к ноутбуку и жмакая кнопки увидел что игра принимает почти все нажатия, кроме крестовины и отклонения правого стика. В качестве пробы добавил кнопки в файл preferences.xml, как указано в этой теме на оф.форуме. В итоге - кнопки с геймпада действительно можно установить в качестве клавиш управления.

    Теперь копаю скрипты из WoWP, там же геймпад полноценно поддерживается.


     

     

    К сожалению, дело к ночи - к тому же для полноценной пробы нужен второй "фанатик" (типа меня). В связи с этим управление пока не настраивал - надо к этому серьезно подойти.

    Игра понимает только ввод данных из активного окна, разумеется когда два окна рядом одно из них будет активным, второе нет. Из-за этого и не пробовал данную теорию.

    • Upvote 1
    • Downvote 1
  13. Сделал перерыв небольшой (голова пухнет от непонимания, что надо делать). Надо доставать опять книги по Python ;)

     

    Пришла вот такая идея относительно управления. Разве надо делать эмулятор клавиатуры/мыши через геймпад? Думаю что нет. 

     

    Сравнивая скрипты от WoWP и WoT, кажется нашел именно то, что нужно.

    'X:\Games\World_of_Warplanes\res\scripts\client\InputMapping.pyс'

    import inspect
    import BigWorld
    from Event import Event
    import ResMgr
    import Keys
    import consts
    from db.DBHelpers import readValue
    from Helpers.i18n import makeString, localizeOptions
    from MathExt import *
    import math
    import threading
    from debug_utils import *
    from input.ProfileLoader.DummyDeviceLoader import MouseDummy
    from input.ProfileLoader.MouseLoader import MouseLoader
    from input.ProfileLoader.JoystickLoader import JoystickSettings
    from input.ProfileLoader.KeyMapingLoader import Keyboard
    from input.ProfileLoader.GamepadLoader import GamepadProfileLoader
    g_instance = None
    g_descriptions = None
    FORCE_DEFAULT_INPUT_PATH = False
    
    def initInput(profileName, profilesPresets):
        global g_instance
        global g_descriptions
        g_descriptions = CommandDescriptions()
        g_instance = InputMapping(profileName, profilesPresets)
    
    
    def translateAxisValue(axisCurve, axisValue):
        return math.copysign(axisCurve.calc(abs(axisValue)), axisValue)
    
    
    SENSITIVITY_MIN = 0.05
    SENSITIVITY_MAX = 2.5
    HI_AXIS_BOUND = 0.5
    LOW_AXIS_BOUND = 0.3
    
    def convertToRealSensitivity(sliderValue):
        return sliderValue * (SENSITIVITY_MAX - SENSITIVITY_MIN) + SENSITIVITY_MIN
    
    
    COMMANDS_TO_REFRESH = []
    COMMANDS_TO_NOT_REFRESH = []
    CHAT_COMMANDS = []
    EQUIPMENT_COMMANDS = []
    
    class CommandDescriptions(object):
        __DATA_PATH = 'scripts/command_mapping_description.xml'
    
        def __init__(self):
            self.__commands = {}
            rootSection = ResMgr.openSection(self.__DATA_PATH)
            commandIntID = 1
            for commandID, dataSection in rootSection.items():
                self.__commands[commandID] = CommandDescription(commandIntID)
                self.__commands[commandID].readFromDatasection(dataSection)
                globals()[commandID] = commandIntID
                commandIntID += 1
    
            if consts.IS_DEBUG_IMPORTED:
                from debug.AvatarDebug import DebugCommands
                self.loadMappingFromClass(DebugCommands, commandIntID)
            self.__fillGlobalCommandLists()
            ResMgr.purge(self.__DATA_PATH, True)
    
        def __fillGlobalCommandLists(self):
            global CHAT_COMMANDS
            global COMMANDS_TO_REFRESH
            global EQUIPMENT_COMMANDS
            global COMMANDS_TO_NOT_REFRESH
            COMMANDS_TO_REFRESH = [CMD_AUTOPILOT]
            COMMANDS_TO_NOT_REFRESH = [CMD_INTERMISSION_MENU,
             CMD_VISIBILITY_HUD,
             CMD_SHOW_CURSOR,
             CMD_HELP,
             CMD_SHOW_MAP]
            CHAT_COMMANDS = [CMD_F2_CHAT_COMMAND,
             CMD_F3_CHAT_COMMAND,
             CMD_F4_CHAT_COMMAND,
             CMD_F5_CHAT_COMMAND,
             CMD_F6_CHAT_COMMAND,
             CMD_F7_CHAT_COMMAND,
             CMD_F8_CHAT_COMMAND,
             CMD_F9_CHAT_COMMAND]
            EQUIPMENT_COMMANDS = [CMD_USE_EQUIPMENT_1, CMD_USE_EQUIPMENT_2, CMD_USE_EQUIPMENT_3]
    
        def loadMappingFromClass(self, classWithMapping, commandIntID):
            import inspect
            for commandID, value in inspect.getmembers(classWithMapping):
                if commandID.startswith('CMD_'):
                    self.__commands[commandID] = CommandDescription(commandIntID, 'DEBUG')
                    globals()[commandID] = commandIntID
                    commandIntID += 1
    
        @property
        def commands(self):
            return self.__commands
    
        def getCommandWaitTime(self, commandName):
            if commandName in self.__commands:
                command = self.__commands[commandName]
                return command.waitTime
            return 0.0
    
        def getCommandGroupID(self, commandName):
            if commandName in self.__commands:
                command = self.__commands[commandName]
                return command.groupID
            return ''
    
        def getCommandLocalizationID(self, commandName):
            if commandName in self.__commands:
                command = self.__commands[commandName]
                return command.localizationID
            return ''
    
        def getLinkedAxisName(self, commandName):
            if commandName in self.__commands:
                command = self.__commands[commandName]
                return command.linkedAxisName
            else:
                return ''
    
        def getCommandIntID(self, commandName):
            if commandName in self.__commands:
                command = self.__commands[commandName]
                return command.commandID
            return ''
    
        def getCommandNameByID(self, commandID):
            for commandName, command in self.__commands.items():
                if commandID == command.commandID:
                    return (commandName, command.groupName)
    
            return (None, None)
    
    
    class CommandDescription():
    
        def __init__(self, commandIntID, groupName = 'MAIN', groupID = 'SETTINGS_BASIC'):
            self.commandID = commandIntID
            self.linkedAxisName = ''
            self.localizationID = ''
            self.groupName = groupName
            self.groupID = groupID
            self.waitTime = 0.0
    
        def readFromDatasection(self, dataSection):
            readValue(self, dataSection, 'linkedAxisName', '')
            readValue(self, dataSection, 'localizationID', '')
            readValue(self, dataSection, 'groupName', 'MAIN')
            readValue(self, dataSection, 'groupID', 'SETTINGS_BASIC')
            readValue(self, dataSection, 'waitTime', 0.0)
    
    
    class InputMappingLoader(threading.Thread):
    
        def __init__(self, threadData, callback):
            threading.Thread.__init__(self)
            self.__threadData = threadData
            self.__callback = callback
    
        def run(self):
            self.__callback(self.__threadData)
    
    
    class InputMapping(object):
        __DATA_PATH = 'scripts/input_mapping/'
        __DEFAULTS_PATH = __DATA_PATH + 'defaults/'
        __DEFAULT_CONFIG_FILE_NAME = 'keyboard'
        __PRIMARY_SETTINGS_LOADERS = {consts.INPUT_SYSTEM_STATE.KEYBOARD: MouseDummy,
         consts.INPUT_SYSTEM_STATE.JOYSTICK: JoystickSettings,
         consts.INPUT_SYSTEM_STATE.GAMEPAD_DIRECT_CONTROL: JoystickSettings,
         consts.INPUT_SYSTEM_STATE.MOUSE: MouseLoader}
    
        @property
        def descriptions(self):
            return g_descriptions
    
        def __init__(self, currentProfileName, profilesPresets):
            self.__profileNames = self.loadProfileNames(profilesPresets)
            if ResMgr.useDefaultDataPath() or FORCE_DEFAULT_INPUT_PATH:
                self.__dataPath = self.__DATA_PATH
            else:
                self.__dataPath = ResMgr.getInputMappingPath(self.__DEFAULTS_PATH, '.xml', self.__profileNames)
            self.__checkInputFiles(self.__DEFAULTS_PATH, self.__dataPath)
            LOG_INFO('Input mapping data path: ' + self.__dataPath)
            if currentProfileName not in self.__profileNames:
                if self.__DEFAULT_CONFIG_FILE_NAME in self.__profileNames:
                    currentProfileName = self.__DEFAULT_CONFIG_FILE_NAME
                elif self.__profileNames:
                    currentProfileName = self.__profileNames[0]
                else:
                    LOG_ERROR('InputMapping::__init__ - can"t load current profile name:', currentProfileName)
            self.onDefaultMappingRestored = Event()
            self.onProfileLoaded = Event()
            self.__loadLock = threading.Lock()
            self.__loadInProgressProfile = None
            self.__load(currentProfileName, False, True, None)
            self.onSaveControls = Event()
            return
    
        def __loadLockAcquire(self):
            self.__loadLock.acquire()
    
        def __loadLockRelease(self):
            self.__loadLock.release()
    
        def __getCallbackClient(self):
            return self.__callbackClient
    
        def __setCallbackClient(self, val):
            self.__callbackClient = val
    
        callbackClient = property(__getCallbackClient, __setCallbackClient)
    
        def __checkInputFiles(self, defaultDataPath, actualDataPath):
            if defaultDataPath == actualDataPath:
                LOG_ERROR('defaultDataPath equals actualDataPath:', defaultDataPath)
            else:
                defaultlDataSection = ResMgr.openSection(defaultDataPath)
                if defaultlDataSection == None:
                    LOG_ERROR('default data section does not exist')
                else:
                    actualDataSection = ResMgr.openSection(actualDataPath)
                    if actualDataSection == None:
                        LOG_ERROR('data section must already exist', actualDataPath)
                    else:
                        for profile in self.__profileNames:
                            self.__checkInputFile(defaultlDataSection, actualDataSection, profile)
    
            return
    
        def __checkInputFile(self, defaultlDataSection, actualDataSection, profile):
            fileName = profile + '.xml'
            if not defaultlDataSection.has_key(fileName):
                LOG_ERROR('default data section does not contain file', fileName)
            else:
                defaultProfile = defaultlDataSection[fileName]
                if defaultProfile == None:
                    LOG_ERROR('cannot open default file', fileName)
                elif actualDataSection.has_key(fileName):
                    actualProfile = actualDataSection[fileName]
                    if actualProfile == None:
                        LOG_ERROR('cannot open file', fileName)
                    else:
                        defaultVersion = defaultProfile.readInt('FILE_VERSION', 0)
                        actualVersion = actualProfile.readInt('FILE_VERSION', 0)
                        if actualVersion < defaultVersion:
                            actualProfile.copy(defaultProfile)
                            actualProfile.save()
                            LOG_INFO('version mismatch, replaced', fileName, defaultVersion, actualVersion)
                else:
                    actualProfile = actualDataSection.createSection(fileName)
                    if actualProfile == None:
                        LOG_ERROR('cannot create new section', fileName)
                    else:
                        actualProfile.copy(defaultProfile)
                        actualProfile.save()
                        LOG_INFO('created profile from default', fileName)
            return
    
        def getAllCommandsIds(self):
            commadIds = list()
            for command in g_descriptions.commands.values():
                commadIds.append(command.commandID)
    
            return commadIds
    
        def getCommandsButtonsList(self, commandIDsList):
            from input.InputController import UserKeyEvent
            keys = []
            for commandID in commandIDsList:
                keyCodes = self.keyboardSettings.getCommandKeys(commandID)
                if keyCodes and len(keyCodes) > 0:
                    keyInfo = keyCodes[0]
                    keys.append(UserKeyEvent(keyInfo['code'], keyInfo['device']))
    
            return keys
    
        def getAllCommandsButtonsList(self, ignoreCommandIDsList):
            from input.InputController import UserKeyEvent
            keys = []
            for command in g_descriptions.commands.values():
                keyCodes = None
                if command.commandID not in ignoreCommandIDsList:
                    keyCodes = self.keyboardSettings.getCommandKeys(command.commandID)
                if keyCodes and len(keyCodes) > 0:
                    keyInfo = keyCodes[0]
                    keys.append(UserKeyEvent(keyInfo['code'], keyInfo['device']))
    
            return keys
    
        def getProfileNames(self):
            return self.__profileNames
    
        def loadProfileNames(self, profilesPresets):
            """
            @param profilesPresets: <dict> Ex.: {mouse_directional : [{name:mouse_directional, localizationID:CONTROL_PROFILE_DEFAULT}] }
            @return: <list>
            """
            profiles = []
            rootSection = ResMgr.openSection(self.__DEFAULTS_PATH)
            for fileName in rootSection.keys():
                extentionPos = fileName.find('.xml')
                if extentionPos != -1:
                    profileName = fileName[0:extentionPos]
                    isPreset = False
                    if not isPreset:
                        profiles.append(profileName)
    
            ResMgr.purge(self.__DEFAULTS_PATH, True)
            return profiles
    
        def getLocalizedProfileNameCaps(self, profileName = None):
            if profileName is None:
                profileName = self.getCurProfileName()
            return localizeOptions('CONTROL_PROFILE_%s_CAPS' % profileName.upper())
    
        def getLocalizedProfileName(self, profileName = None):
            if profileName is None:
                profileName = self.getCurProfileName()
            return localizeOptions('CONTROL_PROFILE_%s' % profileName.upper())
    
        def getLocalizedProfileNames(self):
            locProfiles = []
            profiles = self.getProfileNames()
            for profile in profiles:
                locProfiles.append(localizeOptions('CONTROL_PROFILE_' + profile.upper()))
    
            return locProfiles
    
        def getProfileNameByIndex(self, index):
            profiles = self.getProfileNames()
            return profiles[index]
    
        def isCommandKey(self, command, key, keyDevice, axisIndex = -1, axisDevice = 0):
            return self.keyboardSettings.isCommandKey(command, key, keyDevice, axisIndex, axisDevice)
    
        def isMouseActivateEvent(self, key, event):
            if isinstance(event, BigWorld.KeyEvent):
                return event.wg_isMouseActivateEvent
            return False
    
        def setSwitchingStyle(self, command, switchingStyle):
            self.keyboardSettings.setSwitchingStyle(command, switchingStyle)
    
        def getSwitchingStyle(self, command):
            return self.keyboardSettings.getSwitchingStyle(command)
    
        def invertY(self):
            self.keyboardSettings.INVERT_Y = 1 - self.keyboardSettings.INVERT_Y
            self.primarySettings.INVERT_Y = 1 - self.primarySettings.INVERT_Y
    
        @property
        def mouseSettings(self):
            return self.primarySettings
    
        @property
        def joystickSettings(self):
            return self.primarySettings
    
        def __saveProfile(self, rootSection, profilePath):
            try:
                rootSection.save()
            except IOError:
                LOG_ERROR("Couldn't save profile: " + profilePath)
            else:
                LOG_DEBUG('Controls saved to ' + profilePath)
    
            ResMgr.purge(profilePath, True)
    
        def saveControlls(self, curProfileName, profileNameKeyBoard = None):
            if self.__loadInProgressProfile:
                LOG_INFO('::saveControlls: Save rejected. Profile %s is loading' % self.__loadInProgressProfile['profileName'])
                return
            else:
                try:
                    self.__loadLockAcquire()
                    profilePath = ''.join([self.__dataPath, self.__curProfileName if curProfileName is None else curProfileName, '.xml'])
                    rootSection = ResMgr.openSection(profilePath)
                    self.keyboardSettings.flash(rootSection['KEYBOARD'])
                    self.primarySettings.flash(rootSection['PRIMARY'])
                    self.__saveProfile(rootSection, profilePath)
                    if profileNameKeyBoard is not None:
                        LOG_INFO('saveControlls - save KEYBOARD to %s.xml curProfileName=%s' % (profileNameKeyBoard, curProfileName))
                        keyBoardPath = ''.join([self.__dataPath, profileNameKeyBoard, '.xml'])
                        keyBoardRootSection = ResMgr.openSection(keyBoardPath)
                        self.keyboardSettings.flash(keyBoardRootSection['KEYBOARD'])
                        self.__saveProfile(keyBoardRootSection, keyBoardPath)
                    self.onSaveControls()
                except:
                    LOG_CURRENT_EXCEPTION()
                finally:
                    self.__loadLockRelease()
    
                return
    
        def getCurProfileName(self):
            return self.__curProfileName
    
        def setCurProfileName(self, ProfileName):
            LOG_INFO('setCurProfileName - old=(%s), new=(%s)' % (self.__curProfileName, ProfileName))
            self.__curProfileName = ProfileName
    
        def getCurProfileIndex(self):
            profiles = self.getProfileNames()
            return profiles.index(self.__curProfileName)
    
        def changeProfile(self, profileName):
            self.__load(profileName, False, True, None)
            return
    
        def loadProfileFromPreset(self, profileName, loadFromDefaults, profileNameForKeyboardSettings):
            self.__load(profileName, loadFromDefaults, False, profileNameForKeyboardSettings)
    
        def restoreDefaultsCommandMapping(self):
            self.__load(self.__curProfileName, True, True, None)
            return
    
        def getCurMapping(self):
            return self.keyboardSettings.getCurMapping(self.joystickSettings)
    
        def applyNewMapping(self, mapping):
            self.keyboardSettings.applyNewMapping(mapping, self.joystickSettings)
    
        def setKeyboardLining(self, value):
            self.keyboardSettings.setLining(value)
    
        def getKeyboardLining(self):
            return self.keyboardSettings.getLining()
    
        def getLocalizedCommandKeysAndAxes(self, commandName):
            """
            Returns list with localized names of keys/axes that correspond to given command or empty list
            @param commandName: command name from command_mapping_description.xml
            @rtype: list
            """
            keysControls = []
            curMapping = self.getCurMapping()
            record = curMapping.get(g_descriptions.getCommandIntID(commandName), None)
            if record is not None:
                for key in record['keyNames']:
                    if 'KEY_NONE' != key['name']:
                        keysControls.append(getKeyLocalization(key['name']))
    
                if not self.currentProfileType == consts.INPUT_SYSTEM_STATE.KEYBOARD:
                    if not self.currentProfileType == consts.INPUT_SYSTEM_STATE.MOUSE:
                        if record['linkedAxisIndex'] != -1:
                            keysControls.append(getAxisLocalization(record['linkedAxisIndex']))
                        record['fireAxisIndex'] != -1 and keysControls.append(getAxisLocalization(record['fireAxisIndex']))
            return keysControls
    
        def getKeyControlsHelp(self, dataKeysControls):
            keysControls = {}
            curMapping = self.getCurMapping()
            for cmdID, record in curMapping.items():
                cmdLabel = getCommandLocalization(record['cmdName'])
                if cmdLabel is not None and cmdID in dataKeysControls:
                    keysControls[cmdID] = {'keys': [],
                     'isFireAxis': [],
                     'axisSign': []}
                    for key in record['keyNames']:
                        if 'KEY_NONE' != key['name']:
                            keysControls[cmdID]['keys'].append(key['name'])
                            keysControls[cmdID]['isFireAxis'].append(False)
                            keysControls[cmdID]['axisSign'].append(0)
    
                    if record['linkedAxisIndex'] != -1:
                        keysControls[cmdID]['keys'].append('_'.join(['AXIS', str(record['linkedAxisIndex'])]))
                        keysControls[cmdID]['isFireAxis'].append(False)
                        keysControls[cmdID]['axisSign'].append(0)
                    elif record['fireAxisIndex'] != -1:
                        keysControls[cmdID]['keys'].append('_'.join(['AXIS', str(record['fireAxisIndex'])]))
                        keysControls[cmdID]['isFireAxis'].append(True)
                        keysControls[cmdID]['axisSign'].append(record['fireAxisSign'])
    
            return keysControls
    
        def __load(self, profileName, loadFromDefaults, isOverrideCurProfileName, profileNameForKeyboardSettings, loadFromDefaultsKeyboardSettings = False):
            if isOverrideCurProfileName:
                self.__curProfileName = profileName
            profilePath = profileName + '.xml'
            profilePath = self.__DEFAULTS_PATH + profilePath if loadFromDefaults else self.__dataPath + profilePath
            LOG_DEBUG("Try to load config profile '%s'" % profileName)
            o = dict(profileName=self.__curProfileName, loadFromDefaults=loadFromDefaults)
            resources = (profilePath,)
            if profileNameForKeyboardSettings is not None:
                o['profileNameForKeyboardSettings'] = profileNameForKeyboardSettings
                o['loadFromDefaultsKeyboardSettings'] = loadFromDefaultsKeyboardSettings
                profilePathForKeyboardSettings = self.__DEFAULTS_PATH + profileNameForKeyboardSettings + '.xml' if loadFromDefaultsKeyboardSettings else self.__dataPath + profileNameForKeyboardSettings + '.xml'
                resources = (profilePath, profilePathForKeyboardSettings)
            self.__loadInProgressProfile = o
            BigWorld.loadResourceListBG(resources, self.__profileDataSectionLoaded, 64, o)
            return
    
        @property
        def currentProfileType(self):
            return self.__currentProfileType
    
        def __profileDataSectionLoaded(self, resourceRefs):
            profilePath = resourceRefs.resourceIDs[0]
            LOG_DEBUG("Loading config profile from '%s'" % profilePath, resourceRefs.has_key(profilePath))
            if not resourceRefs.has_key(profilePath):
                LOG_DEBUG("Can't load '%s'" % profilePath)
                if resourceRefs.extraData['loadFromDefaults']:
                    if resourceRefs.extraData['profileName'] != self.__DEFAULT_CONFIG_FILE_NAME:
                        self.__load(self.__DEFAULT_CONFIG_FILE_NAME, True, True, None)
                    else:
                        LOG_ERROR("Can't load system configs")
                else:
                    self.__load(resourceRefs.extraData['profileName'], True, True, None)
            else:
                LOG_DEBUG('Profile successfully loaded')
                rootSection = resourceRefs[profilePath]
                if self.__loadInProgressProfile == resourceRefs.extraData:
                    self.__loadLockAcquire()
                    try:
                        s = rootSection.readString('TYPE')
                        try:
                            self.__currentProfileType = consts.INPUT_SYSTEM_STATE.__dict__[s]
                        except KeyError:
                            LOG_DEBUG('Bad profile type - [' + str(s) + '] in ' + profilePath)
                            raise
    
                        rootSectionKeyboard = rootSection
                        if len(resourceRefs.resourceIDs) > 1 and 'profileNameForKeyboardSettings' in resourceRefs.extraData:
                            keyboardPath = resourceRefs.resourceIDs[1]
                            if resourceRefs.has_key(keyboardPath):
                                rootSectionKeyboard = resourceRefs[keyboardPath]
                                LOG_INFO('__profileDataSectionLoaded - KEYBOARD loaded from %s profilePath=%s' % (keyboardPath, profilePath))
                                ResMgr.purge(keyboardPath, True)
                        self.keyboardSettings = Keyboard(rootSectionKeyboard['KEYBOARD'])
                        profileLoaderClass = self.__PRIMARY_SETTINGS_LOADERS.get(self.currentProfileType, None)
                        if profileLoaderClass is not None:
                            self.primarySettings = profileLoaderClass(rootSection['PRIMARY'])
                        else:
                            LOG_INFO('::__profileDataSectionLoaded: Profile [%s],ProfileType[%s] ignored as an obsolete loading' % (profilePath, self.currentProfileType))
                        ResMgr.purge(profilePath, True)
                        self.onProfileLoaded()
                    except:
                        LOG_CURRENT_EXCEPTION()
                    finally:
                        self.__loadLockRelease()
                        self.__loadInProgressProfile = None
    
                else:
                    LOG_INFO('::__profileDataSectionLoaded: Profile [%s] ignored as an obsolete loading' % profilePath)
            return
    
    
    class Command():
        MODIFIERS = {'ALT': lambda : BigWorld.isKeyDown(Keys.KEY_RALT, 0) or BigWorld.isKeyDown(Keys.KEY_LALT, 0),
         'SHIFT': lambda : BigWorld.isKeyDown(Keys.KEY_RSHIFT, 0) or BigWorld.isKeyDown(Keys.KEY_LSHIFT, 0),
         'CTRL': lambda : BigWorld.isKeyDown(Keys.KEY_RCONTROL, 0) or BigWorld.isKeyDown(Keys.KEY_LCONTROL, 0),
         'RALT': lambda : BigWorld.isKeyDown(Keys.KEY_RALT, 0),
         'LALT': lambda : BigWorld.isKeyDown(Keys.KEY_LALT, 0),
         'LCTRL': lambda : BigWorld.isKeyDown(Keys.KEY_LCONTROL, 0),
         'RCTRL': lambda : BigWorld.isKeyDown(Keys.KEY_RCONTROL, 0)}
    
        def __init__(self, id, linkedAxisName, fireAxisIndex, fireAxisSign, fireAxisDevice, keyNames, modifier, isBlock, isBase, switchingStyle):
            self.id = id
            self.linkedAxisName = linkedAxisName
            self.fireAxisIndex = fireAxisIndex
            self.fireAxisSign = fireAxisSign
            self.fireAxisDevice = fireAxisDevice
            self.__modifierFnc = Command.MODIFIERS.get(modifier, None)
            self.applyNewKeys(keyNames)
            self.isBlock = isBlock
            self.isBase = isBase
            self.switchingStyle = switchingStyle
            self.lastExecuteTime = 0.0
            return
    
        def checkKey(self, key, keyDevice):
            for keyRecord in self.__keys:
                if key == keyRecord['code'] and (keyDevice == keyRecord['device'] or keyRecord['device'] == 0):
                    return keyRecord
    
            return False
    
        def checkAxis(self, axisIndex, axisDevice):
            import BWPersonality
            if axisIndex != -1 and self.fireAxisIndex != -1:
                if self.fireAxisDevice == 0 or self.fireAxisDevice == axisDevice:
                    return self.fireAxisIndex == axisIndex and axisIndex in BWPersonality.axis[axisDevice]
            return False
    
        def isModifierActive(self):
            return self.__modifierFnc is None or self.__modifierFnc()
    
        def isCommandActive(self):
            import BWPersonality
            if self.fireAxisIndex != -1:
                for device, axes in BWPersonality.axis.items():
                    if (device == self.fireAxisDevice or self.fireAxisDevice == 0) and self.fireAxisIndex in axes:
                        axisValue = axes[self.fireAxisIndex]
                        if sign(axisValue) == sign(self.fireAxisSign) and abs(axisValue) > HI_AXIS_BOUND:
                            return True
    
            for key in self.__keys:
                if BigWorld.isKeyDown(key['code'], key['device']):
                    return True
    
            return False
    
        def clear(self):
            self.__keys = []
    
        def flash(self, rootSection):
            rootSection.deleteSection(self.id)
            section = rootSection.createSection(self.id)
            keysSection = section.createSection('FIRE_KEYS')
            for key in self.__keys:
                keySection = keysSection.createSection('FIRE_KEY')
                keySection.writeString('fireKeyName', key['name'])
                keySection.writeInt64('fireKeyDevice', key['device'])
    
            section.writeInt('fireAxisIndex', self.fireAxisIndex)
            section.writeInt('fireAxisSign', self.fireAxisSign)
            section.writeInt64('fireAxisDevice', self.fireAxisDevice)
            section.writeInt('isBase', self.isBase)
            section.writeInt('switchingStyle', self.switchingStyle)
    
        def getMappedKeyCodes(self):
            return self.__keys
    
        def applyNewKeys(self, keyNames):
            """
            Fill 'code'(int keyCode) for all keys in record and drop all last empty keys
            
            keyNames : {'name':str,'device':UINT}
            
            """
            self.__keys = keyNames
            keyIndex = 0
            lastValidKeyIndex = 0
            for key in self.__keys:
                key['code'] = getKeyCodeByName(key['name'])
                keyIndex += 1
                if key['name'] != 'KEY_NONE':
                    lastValidKeyIndex = keyIndex
    
            self.__keys = self.__keys[:lastValidKeyIndex]
    
    
    def getKeyNameByCode(keyCode):
        if keyCode == 0:
            return 'KEY_NONE'
        for k, v in Keys.__dict__.items():
            if v == keyCode:
                return k
    
        return 'KEY_NONE'
    
    
    def getKeyCodeByName(keyName):
        if keyName in Keys.__dict__:
            return int(Keys.__dict__.get(keyName))
        else:
            return 0
    
    
    def getKeyLocalization(keyName):
        return makeString('#keys:' + keyName)
    
    
    def getAxisLocalization(axisIndex):
        if axisIndex == -1:
            return ''
        return getKeyLocalization('_'.join(['AXIS', str(axisIndex)]))
    
    
    def getCommandLocalization(commandName):
        localizationID = g_descriptions.getCommandLocalizationID(commandName)
        if localizationID == '':
            return None
        else:
            return makeString('#options:KEYMAPPING/' + localizationID)
            return None 

     

    'X:\Games\World_of_Tanks\res\scripts\client\CommandMapping.pyc'

    import BigWorld
    import ResMgr
    import Keys
    import Event
    import Settings
    from debug_utils import *
    g_instance = None
    CMD_MOVE_FORWARD = 1
    CMD_MOVE_FORWARD_SPEC = 2
    CMD_MOVE_BACKWARD = 3
    CMD_ROTATE_LEFT = 4
    CMD_ROTATE_RIGHT = 5
    CMD_INCREMENT_CRUISE_MODE = 6
    CMD_DECREMENT_CRUISE_MODE = 7
    CMD_STOP_UNTIL_FIRE = 8
    CMD_SWITCH_SERVER_MARKER = 9
    CMD_AMMO_CHOICE_1 = 10
    CMD_AMMO_CHOICE_2 = 11
    CMD_AMMO_CHOICE_3 = 12
    CMD_AMMO_CHOICE_4 = 13
    CMD_AMMO_CHOICE_5 = 14
    CMD_AMMO_CHOICE_6 = 15
    CMD_AMMO_CHOICE_7 = 16
    CMD_AMMO_CHOICE_8 = 17
    CMD_AMMO_CHOICE_9 = 18
    CMD_AMMO_CHOICE_0 = 19
    CMD_CHAT_SHORTCUT_ATTACK = 21
    CMD_CHAT_SHORTCUT_BACKTOBASE = 22
    CMD_CHAT_SHORTCUT_FOLLOWME = 23
    CMD_CHAT_SHORTCUT_POSITIVE = 24
    CMD_CHAT_SHORTCUT_NEGATIVE = 25
    CMD_CHAT_SHORTCUT_HELPME = 26
    CMD_CM_SHOOT = 27
    CMD_CM_SWITCH_TRAJECTORY = 28
    CMD_CM_FREE_CAMERA = 29
    CMD_CM_LOCK_TARGET = 30
    CMD_CM_LOCK_TARGET_OFF = 31
    CMD_CM_CAMERA_ROTATE_LEFT = 32
    CMD_CM_CAMERA_ROTATE_RIGHT = 33
    CMD_CM_CAMERA_ROTATE_UP = 34
    CMD_CM_CAMERA_ROTATE_DOWN = 35
    CMD_CM_VEHICLE_SWITCH_AUTOROTATION = 36
    CMD_CM_INCREASE_ZOOM = 37
    CMD_CM_DECREASE_ZOOM = 38
    CMD_CM_ALTERNATE_MODE = 39
    CMD_CM_CAMERA_RESTORE_DEFAULT = 40
    CMD_CM_POSTMORTEM_NEXT_VEHICLE = 41
    CMD_CM_POSTMORTEM_SELF_VEHICLE = 42
    CMD_VEHICLE_MARKERS_SHOW_INFO = 43
    CMD_AMMO_PANEL_SELECT = 44
    CMD_MINIMAP_HIGHLIGHT_CELL = 45
    CMD_MINIMAP_VEHICLE_SPECIFIC = 46
    CMD_MINIMAP_SIZE_UP = 47
    CMD_MINIMAP_SIZE_DOWN = 48
    CMD_MINIMAP_VISIBLE = 49
    CMD_VOICECHAT_MUTE = 50
    CMD_USE_HORN = 51
    CMD_LOGITECH_SWITCH_VIEW = 52
    CMD_TOGGLE_GUI = 53
    CMD_RELOAD_PARTIAL_CLIP = 54
    CMD_RADIAL_MENU_SHOW = 55
    CMD_CHAT_SHORTCUT_RELOAD = 56
    
    class CommandMapping:
        __DEFAULT_CONFIG_FILE_NAME = 'scripts/command_mapping.xml'
        __USER_CONFIG_SECTION_NAME = 'commandMapping'
        onMappingChanged = Event.Event()
    
        def __init__(self):
            self.__mapping = {}
            self.__dictCommand2CommandName = {}
            self.restoreUserConfig()
    
        def add(self, commandName, fireKeyName, satelliteKeyNames = [], isDefault = False):
            try:
                command = int(self.getCommand(commandName))
                fireKey = int(Keys.__dict__.get(fireKeyName))
                satelliteKeys = tuple(map(lambda x: int(Keys.__dict__.get(x)), satelliteKeyNames))
                keyInfo = (command, satelliteKeys, isDefault)
            except:
                return False
    
            if not isDefault:
                if not self.__checkUserKey(fireKey):
                    return False
                for key in satelliteKeys:
                    if not self.__checkUserKey(key):
                        return False
    
            if fireKey not in self.__mapping:
                self.__mapping[fireKey] = []
            if keyInfo not in self.__mapping[fireKey]:
                self.__mapping[fireKey].append(keyInfo)
            self.__dictCommand2CommandName[command] = commandName
            return True
    
        def get(self, commandName):
            try:
                command = int(self.getCommand(commandName))
                for fireKey, listKeyInfo in self.__mapping.iteritems():
                    for keyInfo in listKeyInfo:
                        if keyInfo[0] == command and len(keyInfo[1]) == 0:
                            return fireKey
    
            except:
                return None
    
            return None
    
        def remove(self, commandName, fireKeyName = None, satelliteKeyNames = None, isDefault = None):
            try:
                delCommand = int(self.getCommand(commandName))
                delFireKey = None if fireKeyName is None else int(Keys.__dict__.get(fireKeyName))
                delSatelliteKeys = None if satelliteKeyNames is None else tuple(map(lambda x: int(Keys.__dict__.get(x)), satelliteKeyNames))
                delIsDefault = isDefault
            except:
                return False
    
            delListFireKey = []
            for fireKey in self.__mapping:
                if delFireKey is not None:
                    if fireKey != delFireKey:
                        continue
                delListKeyInfo = []
                for keyInfo in self.__mapping[fireKey]:
                    if keyInfo[0] != delCommand:
                        continue
                    if delSatelliteKeys is not None:
                        if keyInfo[1] != delSatelliteKeys:
                            continue
                    if delIsDefault is not None:
                        if keyInfo[2] != delIsDefault:
                            continue
                    delListKeyInfo.append(keyInfo)
    
                for keyInfo in delListKeyInfo:
                    self.__mapping[fireKey].remove(keyInfo)
    
                if not len(self.__mapping[fireKey]):
                    delListFireKey.append(fireKey)
    
            for fireKey in delListFireKey:
                del self.__mapping[fireKey]
    
            return True
    
        def clear(self):
            self.__mapping = {}
    
        def restoreDefault(self):
            self.clear()
            self.__loadDefault()
            self.__loadDevelopment()
    
        def restoreUserConfig(self):
            self.clear()
            self.__loadDefault()
            self.__loadUserConfig()
            self.__loadDevelopment()
    
        def isActive(self, command):
            for fireKey, listKeyInfo in self.__mapping.iteritems():
                if not BigWorld.isKeyDown(fireKey):
                    continue
                for keyInfo in listKeyInfo:
                    if keyInfo[0] != command:
                        continue
                    bContinue = False
                    satelliteKeys = keyInfo[1]
                    for key in satelliteKeys:
                        if not BigWorld.isKeyDown(key):
                            bContinue = True
                            break
    
                    if bContinue:
                        continue
                    return True
    
            return False
    
        def isActiveList(self, listCommands, bAndNor = False):
            if bAndNor:
                for command in listCommands:
                    if not self.isActive(command):
                        return False
    
            else:
                for command in listCommands:
                    if self.isActive(command):
                        return True
    
            return bool(bAndNor)
    
        def isFired(self, command, key):
            listKeyInfo = self.__mapping.get(key)
            if listKeyInfo is None or key == Keys.KEY_NONE:
                return False
            else:
                for keyInfo in listKeyInfo:
                    if keyInfo[0] != command:
                        continue
                    bContinue = False
                    satelliteKeys = keyInfo[1]
                    for key in satelliteKeys:
                        if not BigWorld.isKeyDown(key):
                            bContinue = True
                            break
    
                    if bContinue:
                        continue
                    return True
    
                return False
    
        def isFiredList(self, listCommands, key, bAndNor = False):
            if bAndNor:
                for command in listCommands:
                    if not self.isFired(command, key):
                        return False
    
            else:
                for command in listCommands:
                    if self.isFired(command, key):
                        return True
    
            return bool(bAndNor)
    
        def getName(self, command):
            if command in self.__dictCommand2CommandName:
                return self.__dictCommand2CommandName[command]
            else:
                return None
    
        def getCommand(self, name):
            return globals().get(name)
    
        def save(self):
            tmpList = []
            for fireKey, listKeyInfo in self.__mapping.iteritems():
                for command, satelliteKeys, isDefault in listKeyInfo:
                    if isDefault:
                        continue
                    if len(satelliteKeys):
                        continue
                    commandName = self.getName(command)
                    listSatelliteKeyNames = []
                    for key in satelliteKeys:
                        listSatelliteKeyNames.append('KEY_' + BigWorld.keyToString(key))
    
                    strSatelliteKeyNames = ''
                    for keyName in listSatelliteKeyNames:
                        strSatelliteKeyNames += keyName + ' '
    
                    strSatelliteKeyNames = strSatelliteKeyNames.strip()
                    fireKeyName = 'KEY_' + BigWorld.keyToString(fireKey)
                    tmpList.append((commandName, fireKeyName, strSatelliteKeyNames))
    
            if len(tmpList):
                section = Settings.g_instance.userPrefs
                section.deleteSection(CommandMapping.__USER_CONFIG_SECTION_NAME)
                section = section.createSection(CommandMapping.__USER_CONFIG_SECTION_NAME)
                for commandName, fireKeyName, strSatelliteKeynames in tmpList:
                    subsec = section.createSection(commandName)
                    subsec.writeString('fireKey', fireKeyName)
                    subsec.writeString('satelliteKeys', strSatelliteKeyNames)
    
                Settings.g_instance.save()
    
        def __checkUserKey(self, key):
            """if Keys.KEY_1 <= key <= Keys.KEY_0: return True
            if Keys.KEY_Q <= key <= Keys.KEY_P: return True
            if Keys.KEY_A <= key <= Keys.KEY_L: return True
            if Keys.KEY_Z <= key <= Keys.KEY_M: return True
            if key == Keys.KEY_SPACE: return True
            return False"""
            return True
    
        def __loadFromSection(self, section, bDelOldCmds = True, asDefault = False):
            needsResave = False
            tempList = []
            for commandName in section.keys():
                subsec = section[commandName]
                fireKeyName = subsec.readString('fireKey')
                satelliteKeyNames = []
                if subsec.has_key('satelliteKeys'):
                    satelliteKeyNames = subsec.readString('satelliteKeys').split()
                if bDelOldCmds:
                    self.remove(commandName)
                if commandName.find('_SHORTCAT_') != -1:
                    commandName = commandName.replace('_SHORTCAT_', '_SHORTCUT_')
                    needsResave = True
                tempList.append((commandName, fireKeyName, satelliteKeyNames))
    
            for commandName, fireKeyName, satelliteKeyNames in tempList:
                if not self.add(commandName, fireKeyName, satelliteKeyNames, asDefault):
                    LOG_DEBUG('<__loadFromSection>: ' + ('default' if asDefault else 'user') + ' command ' + str(commandName) + ' was not loaded')
    
            if needsResave:
                self.save()
    
        def getDefaults(self):
            section = ResMgr.openSection(CommandMapping.__DEFAULT_CONFIG_FILE_NAME)
            result = {}
            for commandName in section.keys():
                subsec = section[commandName]
                fireKeyName = subsec.readString('fireKey')
                satelliteKeyNames = []
                if subsec.has_key('satelliteKeys'):
                    satelliteKeyNames = subsec.readString('satelliteKeys').split()
                if len(satelliteKeyNames) == 0:
                    result[self.getCommand(commandName)] = int(Keys.__dict__.get(fireKeyName, 0))
    
            return result
    
        def __loadDefault(self):
            section = ResMgr.openSection(CommandMapping.__DEFAULT_CONFIG_FILE_NAME)
            self.__loadFromSection(section, bDelOldCmds=True, asDefault=True)
    
        def __loadUserConfig(self):
            section = Settings.g_instance.userPrefs
            if not section.has_key(CommandMapping.__USER_CONFIG_SECTION_NAME):
                return
            section = section[CommandMapping.__USER_CONFIG_SECTION_NAME]
            self.__loadFromSection(section, bDelOldCmds=True, asDefault=False)
    
        def __loadDevelopment(self):
            pass 

     

    А в этих файлах есть все необходимые кнопки геймпадов:

    'X:\Games\World_of_Warplanes\res_bw\scripts\client\Keys.pyc'

    """
    This module contains definitions of all keycodes known to the client.
    They are set to the values as in the C++ files.
    """
    MODIFIER_SHIFT = 1
    MODIFIER_CTRL = 2
    MODIFIER_ALT = 4
    KEY_NOT_FOUND = 0
    KEY_NONE = 0
    KEY_NULL = 0
    KEY_ESCAPE = 1
    KEY_1 = 2
    KEY_2 = 3
    KEY_3 = 4
    KEY_4 = 5
    KEY_5 = 6
    KEY_6 = 7
    KEY_7 = 8
    KEY_8 = 9
    KEY_9 = 10
    KEY_0 = 11
    KEY_MINUS = 12
    KEY_EQUALS = 13
    KEY_BACKSPACE = 14
    KEY_TAB = 15
    KEY_Q = 16
    KEY_W = 17
    KEY_E = 18
    KEY_R = 19
    KEY_T = 20
    KEY_Y = 21
    KEY_U = 22
    KEY_I = 23
    KEY_O = 24
    KEY_P = 25
    KEY_LBRACKET = 26
    KEY_RBRACKET = 27
    KEY_RETURN = 28
    KEY_LCONTROL = 29
    KEY_A = 30
    KEY_S = 31
    KEY_D = 32
    KEY_F = 33
    KEY_G = 34
    KEY_H = 35
    KEY_J = 36
    KEY_K = 37
    KEY_L = 38
    KEY_SEMICOLON = 39
    KEY_APOSTROPHE = 40
    KEY_GRAVE = 41
    KEY_LSHIFT = 42
    KEY_BACKSLASH = 43
    KEY_Z = 44
    KEY_X = 45
    KEY_C = 46
    KEY_V = 47
    KEY_B = 48
    KEY_N = 49
    KEY_M = 50
    KEY_COMMA = 51
    KEY_PERIOD = 52
    KEY_SLASH = 53
    KEY_RSHIFT = 54
    KEY_NUMPADSTAR = 55
    KEY_LALT = 56
    KEY_SPACE = 57
    KEY_CAPSLOCK = 58
    KEY_F1 = 59
    KEY_F2 = 60
    KEY_F3 = 61
    KEY_F4 = 62
    KEY_F5 = 63
    KEY_F6 = 64
    KEY_F7 = 65
    KEY_F8 = 66
    KEY_F9 = 67
    KEY_F10 = 68
    KEY_NUMLOCK = 69
    KEY_SCROLL = 70
    KEY_NUMPAD7 = 71
    KEY_NUMPAD8 = 72
    KEY_NUMPAD9 = 73
    KEY_NUMPADMINUS = 74
    KEY_NUMPAD4 = 75
    KEY_NUMPAD5 = 76
    KEY_NUMPAD6 = 77
    KEY_ADD = 78
    KEY_NUMPAD1 = 79
    KEY_NUMPAD2 = 80
    KEY_NUMPAD3 = 81
    KEY_NUMPAD0 = 82
    KEY_NUMPADPERIOD = 83
    KEY_OEM_102 = 86
    KEY_F11 = 87
    KEY_F12 = 88
    KEY_F13 = 100
    KEY_F14 = 101
    KEY_F15 = 102
    KEY_KANA = 112
    KEY_ABNT_C1 = 115
    KEY_CONVERT = 121
    KEY_NOCONVERT = 123
    KEY_YEN = 125
    KEY_ABNT_C2 = 126
    KEY_NUMPADEQUALS = 141
    KEY_PREVTRACK = 144
    KEY_AT = 145
    KEY_COLON = 146
    KEY_UNDERLINE = 147
    KEY_KANJI = 148
    KEY_STOP = 149
    KEY_AX = 150
    KEY_UNLABELED = 151
    KEY_NEXTTRACK = 153
    KEY_NUMPADENTER = 156
    KEY_RCONTROL = 157
    KEY_MUTE = 160
    KEY_CALCULATOR = 161
    KEY_PLAYPAUSE = 162
    KEY_MEDIASTOP = 164
    KEY_VOLUMEDOWN = 174
    KEY_VOLUMEUP = 176
    KEY_WEBHOME = 178
    KEY_NUMPADCOMMA = 179
    KEY_NUMPADSLASH = 181
    KEY_SYSRQ = 183
    KEY_RALT = 184
    KEY_PAUSE = 197
    KEY_HOME = 199
    KEY_UPARROW = 200
    KEY_PGUP = 201
    KEY_LEFTARROW = 203
    KEY_RIGHTARROW = 205
    KEY_END = 207
    KEY_DOWNARROW = 208
    KEY_PGDN = 209
    KEY_INSERT = 210
    KEY_DELETE = 211
    KEY_LWIN = 219
    KEY_RWIN = 220
    KEY_APPS = 221
    KEY_POWER = 222
    KEY_SLEEP = 223
    KEY_WAKE = 227
    KEY_WEBSEARCH = 229
    KEY_WEBFAVORITES = 230
    KEY_WEBREFRESH = 231
    KEY_WEBSTOP = 232
    KEY_WEBFORWARD = 233
    KEY_WEBBACK = 234
    KEY_MYCOMPUTER = 235
    KEY_MAIL = 236
    KEY_MEDIASELECT = 237
    KEY_IME_CHAR = 255
    KEY_MOUSE0 = 256
    KEY_LEFTMOUSE = 256
    KEY_MOUSE1 = 257
    KEY_RIGHTMOUSE = 257
    KEY_MOUSE2 = 258
    KEY_MIDDLEMOUSE = 258
    KEY_MOUSE3 = 259
    KEY_MOUSE4 = 260
    KEY_MOUSE5 = 261
    KEY_MOUSE6 = 262
    KEY_MOUSE7 = 263
    KEY_JOY0 = 272
    KEY_JOY1 = 273
    KEY_JOY2 = 274
    KEY_JOY3 = 275
    KEY_JOY4 = 276
    KEY_JOY5 = 277
    KEY_JOY6 = 278
    KEY_JOY7 = 279
    KEY_JOY8 = 280
    KEY_JOY9 = 281
    KEY_JOY10 = 282
    KEY_JOY11 = 283
    KEY_JOY12 = 284
    KEY_JOY13 = 285
    KEY_JOY14 = 286
    KEY_JOY15 = 287
    KEY_JOY16 = 288
    KEY_JOY17 = 289
    KEY_JOY18 = 290
    KEY_JOY19 = 291
    KEY_JOY20 = 292
    KEY_JOY21 = 293
    KEY_JOY22 = 294
    KEY_JOY23 = 295
    KEY_JOY24 = 296
    KEY_JOY25 = 297
    KEY_JOY26 = 298
    KEY_JOY27 = 299
    KEY_JOY28 = 300
    KEY_JOY29 = 301
    KEY_JOY30 = 302
    KEY_JOY31 = 303
    KEY_JOYDUP = 272
    KEY_JOYDDOWN = 273
    KEY_JOYDLEFT = 274
    KEY_JOYDRIGHT = 275
    KEY_JOYSTART = 276
    KEY_JOYSELECT = 277
    KEY_JOYBACK = 277
    KEY_JOYALPUSH = 278
    KEY_JOYARPUSH = 279
    KEY_JOYCROSS = 280
    KEY_JOYA = 280
    KEY_JOYCIRCLE = 281
    KEY_JOYB = 281
    KEY_JOYSQUARE = 282
    KEY_JOYX = 282
    KEY_JOYTRIANGLE = 283
    KEY_JOYY = 283
    KEY_JOYL1 = 284
    KEY_JOYBLACK = 284
    KEY_JOYR1 = 285
    KEY_JOYWHITE = 285
    KEY_JOYL2 = 286
    KEY_JOYLTRIGGER = 286
    KEY_JOYR2 = 287
    KEY_JOYRTRIGGER = 287
    KEY_JOYAHARD = 288
    KEY_JOYBHARD = 289
    KEY_JOYXHARD = 290
    KEY_JOYYHARD = 291
    KEY_JOYBLACKHARD = 292
    KEY_JOYWHITEHARD = 293
    KEY_JOYLTRIGGERHARD = 294
    KEY_JOYRTRIGGERHARD = 295
    KEY_JOYALUP = 304
    KEY_JOYALDOWN = 305
    KEY_JOYALLEFT = 306
    KEY_JOYALRIGHT = 307
    KEY_JOYARUP = 308
    KEY_JOYARDOWN = 309
    KEY_JOYARLEFT = 310
    KEY_JOYARRIGHT = 311
    KEY_JOYPOVUP = 312
    KEY_JOYPOVUPRIGHT = 313
    KEY_JOYPOVRIGHT = 330
    KEY_JOYPOVDOWNRIGHT = 331
    KEY_JOYPOVDOWN = 332
    KEY_JOYPOVDOWNLEFT = 333
    KEY_JOYPOVLEFT = 334
    KEY_JOYPOVUPLEFT = 335
    KEY_DEBUG = 336
    AXIS_LX = 0
    AXIS_LY = 1
    AXIS_LZ = 2
    AXIS_RX = 3
    AXIS_RY = 4
    AXIS_RZ = 5
    AXIS_U = 6
    AXIS_V = 7 

     

    'X:\Games\World_of_Tanks\res_bw\scripts\client\Keys.pyc'

    """
    This module contains definitions of all keycodes known to the client.
    They are set to the values as in the C++ files.
    """
    MODIFIER_SHIFT = 1
    MODIFIER_CTRL = 2
    MODIFIER_ALT = 4
    KEY_NOT_FOUND = 0
    KEY_NONE = 0
    KEY_NULL = 0
    KEY_ESCAPE = 1
    KEY_1 = 2
    KEY_2 = 3
    KEY_3 = 4
    KEY_4 = 5
    KEY_5 = 6
    KEY_6 = 7
    KEY_7 = 8
    KEY_8 = 9
    KEY_9 = 10
    KEY_0 = 11
    KEY_MINUS = 12
    KEY_EQUALS = 13
    KEY_BACKSPACE = 14
    KEY_TAB = 15
    KEY_Q = 16
    KEY_W = 17
    KEY_E = 18
    KEY_R = 19
    KEY_T = 20
    KEY_Y = 21
    KEY_U = 22
    KEY_I = 23
    KEY_O = 24
    KEY_P = 25
    KEY_LBRACKET = 26
    KEY_RBRACKET = 27
    KEY_RETURN = 28
    KEY_LCONTROL = 29
    KEY_A = 30
    KEY_S = 31
    KEY_D = 32
    KEY_F = 33
    KEY_G = 34
    KEY_H = 35
    KEY_J = 36
    KEY_K = 37
    KEY_L = 38
    KEY_SEMICOLON = 39
    KEY_APOSTROPHE = 40
    KEY_GRAVE = 41
    KEY_LSHIFT = 42
    KEY_BACKSLASH = 43
    KEY_Z = 44
    KEY_X = 45
    KEY_C = 46
    KEY_V = 47
    KEY_B = 48
    KEY_N = 49
    KEY_M = 50
    KEY_COMMA = 51
    KEY_PERIOD = 52
    KEY_SLASH = 53
    KEY_RSHIFT = 54
    KEY_NUMPADSTAR = 55
    KEY_LALT = 56
    KEY_SPACE = 57
    KEY_CAPSLOCK = 58
    KEY_F1 = 59
    KEY_F2 = 60
    KEY_F3 = 61
    KEY_F4 = 62
    KEY_F5 = 63
    KEY_F6 = 64
    KEY_F7 = 65
    KEY_F8 = 66
    KEY_F9 = 67
    KEY_F10 = 68
    KEY_NUMLOCK = 69
    KEY_SCROLL = 70
    KEY_NUMPAD7 = 71
    KEY_NUMPAD8 = 72
    KEY_NUMPAD9 = 73
    KEY_NUMPADMINUS = 74
    KEY_NUMPAD4 = 75
    KEY_NUMPAD5 = 76
    KEY_NUMPAD6 = 77
    KEY_ADD = 78
    KEY_NUMPAD1 = 79
    KEY_NUMPAD2 = 80
    KEY_NUMPAD3 = 81
    KEY_NUMPAD0 = 82
    KEY_NUMPADPERIOD = 83
    KEY_OEM_102 = 86
    KEY_F11 = 87
    KEY_F12 = 88
    KEY_F13 = 100
    KEY_F14 = 101
    KEY_F15 = 102
    KEY_KANA = 112
    KEY_ABNT_C1 = 115
    KEY_CONVERT = 121
    KEY_NOCONVERT = 123
    KEY_YEN = 125
    KEY_ABNT_C2 = 126
    KEY_NUMPADEQUALS = 141
    KEY_PREVTRACK = 144
    KEY_AT = 145
    KEY_COLON = 146
    KEY_UNDERLINE = 147
    KEY_KANJI = 148
    KEY_STOP = 149
    KEY_AX = 150
    KEY_UNLABELED = 151
    KEY_NEXTTRACK = 153
    KEY_NUMPADENTER = 156
    KEY_RCONTROL = 157
    KEY_MUTE = 160
    KEY_CALCULATOR = 161
    KEY_PLAYPAUSE = 162
    KEY_MEDIASTOP = 164
    KEY_VOLUMEDOWN = 174
    KEY_VOLUMEUP = 176
    KEY_WEBHOME = 178
    KEY_NUMPADCOMMA = 179
    KEY_NUMPADSLASH = 181
    KEY_SYSRQ = 183
    KEY_RALT = 184
    KEY_PAUSE = 197
    KEY_HOME = 199
    KEY_UPARROW = 200
    KEY_PGUP = 201
    KEY_LEFTARROW = 203
    KEY_RIGHTARROW = 205
    KEY_END = 207
    KEY_DOWNARROW = 208
    KEY_PGDN = 209
    KEY_INSERT = 210
    KEY_DELETE = 211
    KEY_LWIN = 219
    KEY_RWIN = 220
    KEY_APPS = 221
    KEY_POWER = 222
    KEY_SLEEP = 223
    KEY_WAKE = 227
    KEY_WEBSEARCH = 229
    KEY_WEBFAVORITES = 230
    KEY_WEBREFRESH = 231
    KEY_WEBSTOP = 232
    KEY_WEBFORWARD = 233
    KEY_WEBBACK = 234
    KEY_MYCOMPUTER = 235
    KEY_MAIL = 236
    KEY_MEDIASELECT = 237
    KEY_IME_CHAR = 255
    KEY_MOUSE0 = 256
    KEY_LEFTMOUSE = 256
    KEY_MOUSE1 = 257
    KEY_RIGHTMOUSE = 257
    KEY_MOUSE2 = 258
    KEY_MIDDLEMOUSE = 258
    KEY_MOUSE3 = 259
    KEY_MOUSE4 = 260
    KEY_MOUSE5 = 261
    KEY_MOUSE6 = 262
    KEY_MOUSE7 = 263
    KEY_JOY0 = 272
    KEY_JOY1 = 273
    KEY_JOY2 = 274
    KEY_JOY3 = 275
    KEY_JOY4 = 276
    KEY_JOY5 = 277
    KEY_JOY6 = 278
    KEY_JOY7 = 279
    KEY_JOY8 = 280
    KEY_JOY9 = 281
    KEY_JOY10 = 282
    KEY_JOY11 = 283
    KEY_JOY12 = 284
    KEY_JOY13 = 285
    KEY_JOY14 = 286
    KEY_JOY15 = 287
    KEY_JOY16 = 288
    KEY_JOY17 = 289
    KEY_JOY18 = 290
    KEY_JOY19 = 291
    KEY_JOY20 = 292
    KEY_JOY21 = 293
    KEY_JOY22 = 294
    KEY_JOY23 = 295
    KEY_JOY24 = 296
    KEY_JOY25 = 297
    KEY_JOY26 = 298
    KEY_JOY27 = 299
    KEY_JOY28 = 300
    KEY_JOY29 = 301
    KEY_JOY30 = 302
    KEY_JOY31 = 303
    KEY_JOYDUP = 272
    KEY_JOYDDOWN = 273
    KEY_JOYDLEFT = 274
    KEY_JOYDRIGHT = 275
    KEY_JOYSTART = 276
    KEY_JOYSELECT = 277
    KEY_JOYBACK = 277
    KEY_JOYALPUSH = 278
    KEY_JOYARPUSH = 279
    KEY_JOYCROSS = 280
    KEY_JOYA = 280
    KEY_JOYCIRCLE = 281
    KEY_JOYB = 281
    KEY_JOYSQUARE = 282
    KEY_JOYX = 282
    KEY_JOYTRIANGLE = 283
    KEY_JOYY = 283
    KEY_JOYL1 = 284
    KEY_JOYBLACK = 284
    KEY_JOYR1 = 285
    KEY_JOYWHITE = 285
    KEY_JOYL2 = 286
    KEY_JOYLTRIGGER = 286
    KEY_JOYR2 = 287
    KEY_JOYRTRIGGER = 287
    KEY_JOYAHARD = 288
    KEY_JOYBHARD = 289
    KEY_JOYXHARD = 290
    KEY_JOYYHARD = 291
    KEY_JOYBLACKHARD = 292
    KEY_JOYWHITEHARD = 293
    KEY_JOYLTRIGGERHARD = 294
    KEY_JOYRTRIGGERHARD = 295
    KEY_JOYALUP = 304
    KEY_JOYALDOWN = 305
    KEY_JOYALLEFT = 306
    KEY_JOYALRIGHT = 307
    KEY_JOYARUP = 308
    KEY_JOYARDOWN = 309
    KEY_JOYARLEFT = 310
    KEY_JOYARRIGHT = 311
    KEY_DEBUG = 312
    KEY_LCDKB_LEFT = 320
    KEY_LCDKB_RIGHT = 321
    KEY_LCDKB_OK = 322
    KEY_LCDKB_CANCEL = 323
    KEY_LCDKB_UP = 324
    KEY_LCDKB_DOWN = 325
    KEY_LCDKB_MENU = 326
    AXIS_LX = 0
    AXIS_LY = 1
    AXIS_RX = 2
    AXIS_RY = 3 

     

    Вывод - WoT (сам exe-файл) должен понимать кнопки/стики/триггеры геймпадов и джойстиков. Нужно просто сказать ему выполнять команды по нажатию кнопок не на клавиатуре/мышке.


    Добавление нужных геймпадовских кнопок в файлик command_mapping.xml, ни к чему не привело. Я думаю что из-за отсутствия скрипта подключения геймпада к игре.

     

    Блин, прямо руки опускаются - неужели те, кто знает и понимает python не хочет помочь, хоть советом, хоть направлением, хоть куском кода. Я сам не потяну создание этого всего, в связи с чем и предлагаю денег за реализацию.

    • Upvote 2
    • Downvote 1
  14. Пока не нашел в скриптах где-то ещё изменение минимального разрешения. Выкладываю тут скрипты снова (с измененными минимальными значениями):

    'X:\Games\World_of_Tanks\res\scripts\client\gui\graphicsresolutions.pyc'

    import BigWorld
    from debug_utils import LOG_CURRENT_EXCEPTION, LOG_ERROR, LOG_DEBUG
    
    class GraphicsResolutions(object):
        MIN_HEIGHT = 600
        MIN_WIDTH = 800
        MIN_COLOR_DEPTH = 23
    
        def __gcd(self, a, b):
            while a != 0:
                a, b = b % a, a
    
            return b
    
        def __init__(self):
            self.__allVideoModes = []
            maxWidth = 0
            maxHeight = 0
            self.ASPECT_RATIO = []
            self.ASPECT_RATIO.append((4, 3))
            self.ASPECT_RATIO.append((16, 9))
            self.ASPECT_RATIO.append((16, 10))
            self.ASPECT_RATIO.append((19, 10))
            for monitorModes in BigWorld.listVideoModesAllMonitors():
                modes = []
                for mode in monitorModes:
                    if self.__isVideoModeSuitable(mode):
                        modes.append(mode)
                        if mode[1] > maxWidth:
                            maxWidth = mode[1]
                        if mode[2] > maxHeight:
                            maxHeight = mode[2]
    
                self.__allVideoModes.append(modes)
    
            LOG_DEBUG('max resolution : %d / %d' % (maxWidth, maxHeight))
            if maxHeight > 0:
                _3dVisionAspectRatio = float(maxWidth) / float(maxHeight)
                LOG_DEBUG('aspect ratio : %f' % _3dVisionAspectRatio)
                if _3dVisionAspectRatio > 3.75:
                    gcd = self.__gcd(maxWidth, maxHeight)
                    LOG_DEBUG('aspect ratio inted: %d / %d' % (maxWidth / gcd, maxHeight / gcd))
                    self.ASPECT_RATIO.append((maxWidth / gcd, maxHeight / gcd))
            self.__multisamplingTypes = BigWorld.getSupportedMultisamplingTypes()
            self.__multisamplingTypes.insert(0, 0)
            self.__customAAModes = BigWorld.getSupportedCustomAAModes()
            self.__monitors = BigWorld.wg_getMonitorNames()
            self.__curentMonitorIndex = BigWorld.wg_getActiveMonitorIndex()
            self.__monitorChanged = False
            self.__lastFullscreenSize = None
            self.__lastWindowedSize = None
            BigWorld.wg_setSavePreferencesCallback(self.onSavePreferencesXml)
            return
    
        @property
        def monitorChanged(self):
            return self.__monitorChanged
    
        @property
        def __windowSizes(self):
            __windowSizes = []
            for monitorModes in self.__allVideoModes:
                maxWindow = BigWorld.wg_getMaxWindowedResolution(len(__windowSizes))
                modes = []
                for m in monitorModes:
                    if m[1] > maxWindow[0] or m[2] > maxWindow[1]:
                        continue
                    modes.append((m[1], m[2]))
    
                if maxWindow not in modes:
                    modes.append(maxWindow)
                __windowSizes.append(modes)
    
            return __windowSizes
    
        @property
        def __videoModes(self):
            return [ (m[0], m[1], m[2]) for m in self.__allVideoModes[self.monitorIndex] ]
    
        @property
        def __aspectRatios(self):
            return g_graficsResolutions.ASPECT_RATIO
    
        @property
        def __videoMode(self):
            return BigWorld.videoModeIndex()
    
        @property
        def __windowSize(self):
            return tuple(map(int, BigWorld.wg_getCurrentResolution(True)))
    
        @property
        def __aspectRatio(self):
            return round(BigWorld.getFullScreenAspectRatio(), 6)
    
        @property
        def __multisamplingType(self):
            return BigWorld.getMultisamplingType()
    
        @property
        def __customAAMode(self):
            return BigWorld.getCustomAAMode()
    
        @property
        def isVideoWindowed(self):
            return BigWorld.isVideoWindowed()
    
        @property
        def isVideoVSync(self):
            return BigWorld.isVideoVSync()
    
        @property
        def isTripleBuffered(self):
            return BigWorld.isTripleBuffered()
    
        @property
        def videoModeIndex(self):
            for index, videoModeInfo in enumerate(self.__videoModes):
                if videoModeInfo[0] == self.__videoMode:
                    return index
    
            return -1
    
        @property
        def monitorIndex(self):
            return BigWorld.wg_getActiveMonitorIndex()
    
        @property
        def realMonitorIndex(self):
            return self.__curentMonitorIndex
    
        @property
        def windowSizeIndex(self):
            for index, size in enumerate(self.__windowSizes[self.__curentMonitorIndex]):
                if size == self.__windowSize:
                    return index
    
            return len(self.__windowSizes[self.__curentMonitorIndex])
    
        @property
        def aspectRatioIndex(self):
            for index, size in enumerate(self.__aspectRatios):
                if round(float(size[0]) / size[1], 6) == self.__aspectRatio:
                    return index
    
            return len(self.__aspectRatios)
    
        @property
        def multisamplingTypeIndex(self):
            if self.__multisamplingType in self.__multisamplingTypes:
                return self.__multisamplingTypes.index(self.__multisamplingType)
            return -1
    
        @property
        def customAAModeIndex(self):
            if self.__customAAMode in self.__customAAModes:
                return self.__customAAModes.index(self.__customAAMode)
            return -1
    
        @property
        def videoModesList(self):
            allModes = []
            for monitorModes in self.__allVideoModes:
                modes = []
                for m in monitorModes:
                    modes.append('%dx%d' % (m[1], m[2]))
    
                allModes.append(modes)
    
            return allModes
    
        @property
        def monitorsList(self):
            return self.__monitors
    
        @property
        def windowSizesList(self):
            allModes = []
            for monitorModes in self.__windowSizes:
                modes = []
                for m in monitorModes:
                    modes.append('%dx%d' % m)
    
                current = '%dx%d' % self.__windowSize
                if current not in modes:
                    modes.append(current + '*')
                allModes.append(modes)
    
            return allModes
    
        @property
        def aspectRatiosList(self):
            aspectRatios = [ '%d:%d' % m for m in self.__aspectRatios ]
            if self.aspectRatioIndex == len(self.__aspectRatios):
                aspectRatios.append('%s:1*' % BigWorld.wg_getNiceNumberFormat(self.__aspectRatio))
            return aspectRatios
    
        @property
        def multisamplingTypesList(self):
            return [ '#settings:multisamplingType/type%s' % i for i in self.__multisamplingTypes ]
    
        @property
        def customAAModesList(self):
            return [ '#settings:customAAMode/mode%s' % i for i in self.__customAAModes ]
    
        def __isVideoModeSuitable(self, videoMode):
            return videoMode[1] >= GraphicsResolutions.MIN_WIDTH and videoMode[2] >= GraphicsResolutions.MIN_HEIGHT and videoMode[3] >= GraphicsResolutions.MIN_COLOR_DEPTH
    
        def getVideoModeByIndex(self, index):
            if len(self.__videoModes) > index > -1:
                return self.__videoModes[int(index)][0]
            else:
                return None
                return None
    
        def getWindowSizeByIndex(self, index):
            if len(self.__windowSizes[self.__curentMonitorIndex]) > index > -1:
                return self.__windowSizes[self.__curentMonitorIndex][int(index)]
            return self.__windowSize
    
        def getAspectRatioByIndex(self, index):
            if len(self.__aspectRatios) > index > -1:
                ars = self.__aspectRatios[int(index)]
                return round(float(ars[0]) / ars[1], 6)
            else:
                return None
                return None
    
        def getMultisamplingTypeByIndex(self, index):
            if len(self.__multisamplingTypes) > index > -1:
                return self.__multisamplingTypes[int(index)]
            else:
                return None
                return None
    
        def getCustomAAModeByIndex(self, index):
            if len(self.__customAAModes) > index > -1:
                return self.__customAAModes[int(index)]
            else:
                return None
                return None
    
        @property
        def gamma(self):
            return BigWorld.getGammaCorrection()
    
        def applyChanges(self, isFullScreen, isVideoVSync, isTripleBuffered, sizeIndex, aspectRatioIndex, multisamplingIndex, customAAIndex, gamma, monitorIndex):
            if self.__curentMonitorIndex != monitorIndex:
                self.__monitorChanged = True
            self.__curentMonitorIndex = monitorIndex
            BigWorld.wg_setActiveMonitorIndex(monitorIndex)
            if self.isVideoVSync != isVideoVSync:
                BigWorld.setVideoVSync(isVideoVSync)
            if self.isTripleBuffered != isTripleBuffered:
                BigWorld.setTripleBuffering(isTripleBuffered)
            if self.gamma != gamma:
                gamma = max(gamma, 0.5)
                gamma = min(gamma, 2.0)
                BigWorld.setGammaCorrection(gamma)
            aspectRatio = self.getAspectRatioByIndex(aspectRatioIndex)
            if aspectRatio is not None and aspectRatio != self.__aspectRatio:
                BigWorld.changeFullScreenAspectRatio(aspectRatio)
            multisamplingType = self.getMultisamplingTypeByIndex(multisamplingIndex)
            if self.__multisamplingType != multisamplingType:
                BigWorld.setMultisamplingType(multisamplingType)
            customAAMode = self.getCustomAAModeByIndex(customAAIndex)
            if self.__customAAMode != customAAMode:
                BigWorld.setCustomAAMode(customAAMode)
            if isFullScreen:
                videoMode = self.getVideoModeByIndex(sizeIndex)
                if not self.__monitorChanged and (videoMode != self.__videoMode or self.isVideoWindowed):
                    BigWorld.changeVideoMode(videoMode, False)
                windowSize = self.getWindowSizeByIndex(sizeIndex)
                self.__lastIsWindowed = False
                self.__lastFullscreenSize = (windowSize[0], windowSize[1])
            else:
                if not self.__monitorChanged and not self.isVideoWindowed:
                    BigWorld.changeVideoMode(self.getVideoModeByIndex(sizeIndex), True)
                windowSize = self.getWindowSizeByIndex(sizeIndex)
                oldResolution = BigWorld.wg_getCurrentResolution(True)
                if windowSize is not None and (oldResolution[0] != windowSize[0] or oldResolution[1] != windowSize[1]):
                    BigWorld.resizeWindow(windowSize[0], windowSize[1])
                self.__lastIsWindowed = True
                self.__lastWindowedSize = (windowSize[0], windowSize[1])
            return
    
        def onSavePreferencesXml(self, root):
            if not self.__monitorChanged:
                return
            else:
                devPref = root['devicePreferences']
                devPref.writeBool('windowed', self.__lastIsWindowed)
                if self.__lastFullscreenSize is not None:
                    devPref.writeInt('fullscreenWidth', self.__lastFullscreenSize[0])
                    devPref.writeInt('fullscreenHeight', self.__lastFullscreenSize[1])
                if self.__lastWindowedSize is not None:
                    devPref.writeInt('windowedWidth', self.__lastWindowedSize[0])
                    devPref.writeInt('windowedHeight', self.__lastWindowedSize[1])
                return
                return
    
    
    g_graficsResolutions = GraphicsResolutions() 

     

    'X:\Games\World_of_Tanks\res\scripts\client\gui\shared\utils\graphics.pyc'

    from collections import namedtuple
    import BigWorld
    from debug_utils import LOG_WARNING
    from gui.doc_loaders.GraphicsPresetsLoader import GraphicsPresetsLoader
    from gui.shared.utils import CONST_CONTAINER
    MIN_SCREEN_WIDTH = 800
    MIN_SCREEN_HEIGHT = 600
    MIN_COLOR_DEPTH = 23
    _g_graphSettingsIndices = None
    _g_graphPresets = None
    GraphicSetting = namedtuple('GraphicSetting', 'label value options hint advanced needRestart delayed')
    VideoMode = namedtuple('VideoMode', 'index width height colorDepth label')
    WindowSize = namedtuple('WindowSize', 'width height')
    
    class GRAPHICS_SETTINGS(CONST_CONTAINER):
        RENDER_PIPELINE = 'RENDER_PIPELINE'
        TEXTURE_QUALITY = 'TEXTURE_QUALITY'
        DECALS_QUALITY = 'DECALS_QUALITY'
        OBJECT_LOD = 'OBJECT_LOD'
        FAR_PLANE = 'FAR_PLANE'
        TERRAIN_QUALITY = 'TERRAIN_QUALITY'
        SHADOWS_QUALITY = 'SHADOWS_QUALITY'
        LIGHTING_QUALITY = 'LIGHTING_QUALITY'
        SPEEDTREE_QUALITY = 'SPEEDTREE_QUALITY'
        FLORA_QUALITY = 'FLORA_QUALITY'
        WATER_QUALITY = 'WATER_QUALITY'
        EFFECTS_QUALITY = 'EFFECTS_QUALITY'
        POST_PROCESSING_QUALITY = 'POST_PROCESSING_QUALITY'
        MOTION_BLUR_QUALITY = 'MOTION_BLUR_QUALITY'
        SNIPER_MODE_EFFECTS_QUALITY = 'SNIPER_MODE_EFFECTS_QUALITY'
        VEHICLE_DUST_ENABLED = 'VEHICLE_DUST_ENABLED'
        SNIPER_MODE_GRASS_ENABLED = 'SNIPER_MODE_GRASS_ENABLED'
        VEHICLE_TRACES_ENABLED = 'VEHICLE_TRACES_ENABLED'
        SNIPER_MODE_SWINGING_ENABLED = 'SNIPER_MODE_SWINGING_ENABLED'
    
    
    def __initPresetsData():
        global _g_graphPresets
        if _g_graphPresets is None:
            _g_graphPresets = GraphicsPresetsLoader()
            _g_graphPresets.load()
        return
    
    
    def __initGraphicsSettingsData():
        global _g_graphSettingsIndices
        if _g_graphSettingsIndices is None:
            _g_graphSettingsIndices = dict(((data[0], idx) for idx, data in enumerate(BigWorld.graphicsSettings())))
        return
    
    
    def isVideoModeSuitable(mode):
        return mode.width >= MIN_SCREEN_WIDTH and mode.height >= MIN_SCREEN_HEIGHT and mode.colorDepth >= MIN_COLOR_DEPTH
    
    
    def getSuitableVideoModes():
        result = []
        for monitorModes in BigWorld.listVideoModesAllMonitors():
            modes = []
            for mode in monitorModes:
                m = VideoMode(*mode)
                if isVideoModeSuitable(m):
                    modes.append(m)
    
            result.append(modes)
    
        return tuple(result)
    
    
    def getSuitableWindowSizes():
        result = []
        for idx, monitorModes in enumerate(getSuitableVideoModes()):
            maxSize = WindowSize(*BigWorld.wg_getMaxWindowedResolution(idx))
            modes = []
            for mode in monitorModes:
                if mode.width <= maxSize.width and mode.height <= maxSize.height:
                    modes.append(WindowSize(mode.width, mode.height))
    
            if maxSize not in modes:
                modes.append(maxSize)
            result.append(modes)
    
        return tuple(result)
    
    
    def getGraphicsSetting(settingName):
        __initGraphicsSettingsData()
        index = _g_graphSettingsIndices.get(settingName)
        if index is None:
            LOG_WARNING('Unknown graphics setting', settingName)
            return
        else:
            return GraphicSetting(*BigWorld.graphicsSettings()[index])
            return
    
    
    def getGraphicsPresets(presetIdx = None):
        __initPresetsData()
        if presetIdx is not None:
            return _g_graphPresets.getPreset(presetIdx)
        else:
            return [ _g_graphPresets.getPreset(key) for key in _g_graphPresets.getPresetsKeys() ]
            return
    
    
    def getGraphicsPresetsIndices():
        __initPresetsData()
        return dict(((key, idx) for idx, key in enumerate(_g_graphPresets.getPresetsKeys())))
    
    
    class MonitorSettings(object):
    
        def __init__(self):
            self.__suitableVideoModes = getSuitableVideoModes()
            self.__suitableWindowSizes = getSuitableWindowSizes()
            self.__monitorChanged = False
            self.__currentMonitorIdx = self.activeMonitor
    
        @property
        def windowSizes(self):
            return self.__suitableWindowSizes[self.activeMonitor]
    
        @property
        def currentWindowSize(self):
            return WindowSize(*map(int, BigWorld.wg_getCurrentResolution(True)))
    
        @property
        def videoModes(self):
            return self.__suitableVideoModes[self.activeMonitor]
    
        @property
        def currentVideoMode(self):
            for videoMode in self.videoModes:
                if videoMode.index == BigWorld.videoModeIndex():
                    return videoMode
    
            return None
    
        def changeMonitor(self, monitorIdx):
            if self.__currentMonitorIdx != monitorIdx:
                self.__monitorChanged = True
            self.__currentMonitorIdx = monitorIdx
            BigWorld.wg_setActiveMonitorIndex(monitorIdx)
    
        def setFullscreen(self, isFullscreen):
            vm = self.currentVideoMode
            if vm is not None and isFullscreen != self.isFullscreen:
                BigWorld.changeVideoMode(vm.index, not isFullscreen)
            return
    
        def changeVideoMode(self, videoMode):
            cvm = self.currentVideoMode
            if not self.isMonitorChanged and cvm is not None and (videoMode.index != cvm or not self.isFullscreen):
                BigWorld.changeVideoMode(videoMode.index, False)
            return
    
        def changeWindowSize(self, windowSize):
            if not self.isMonitorChanged and self.isFullscreen:
                self.setFullscreen(False)
            curWindowSize = self.currentWindowSize
            if curWindowSize.width != windowSize.width or curWindowSize.height != windowSize.height:
                BigWorld.resizeWindow(windowSize.width, windowSize.height)
    
        @property
        def activeMonitor(self):
            return BigWorld.wg_getActiveMonitorIndex()
    
        @property
        def currentMonitor(self):
            return self.__currentMonitorIdx
    
        @property
        def isMonitorChanged(self):
            return self.__monitorChanged
    
        @property
        def isFullscreen(self):
            return not BigWorld.isVideoWindowed()
    
        @property
        def maxParams(self):
            maxWidth = maxHeight = 0
            for monitorModes in self.__suitableVideoModes:
                for mode in monitorModes:
                    maxWidth = max(maxWidth, mode.width)
                    maxHeight = max(maxHeight, mode.height)
    
            return (maxWidth, maxHeight)
    
    
    g_monitorSettings = MonitorSettings() 

     

    Данные скрипты позволяют выбрать разрешение меньше чем стандартные 1024х768, но при нажатии кнопки применить нужное разрешение сбрасывается.

     

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

    • Upvote 1
    • Downvote 1
  15. def _TrackBreakingController__breakWithDirection(self, vehicle, isLeftTrackBroken):

            directionMatrix = Math.Matrix(BigWorld.camera().source)

    -------------------

    def _TrackBreakingController__breakWithDirection(self, vehicle, isLeftTrackBroken):

            directionMatrix = Math.Matrix(BigWorld.camera().matrix)

    Очень хочется пояснений. Потому как это "картохины" скрипты.

  16. Убил вечер, но есть некоторые результаты которыми стоит поделиться. Ниже скриншот успехов ;)

     

    post-19155-0-56900700-1395692862_thumb.jpg

     

    Итак по порядку.

    1. Огромная благодарность уважаемому inj3ct0r - подсказал как разделить вибрацию от каждой копии игры на два геймпада. Сделал два мода, каждый из них висят на разных портах и отдают вибрации в 1-й и 2-й геймпад (в Xinput 0-й и 1-й).

    2. С помощью Vitrual Display Manager разделил экран на два "виртуальных". Должен сказать, что решение очень кривое и при первой же возможности надо уйти от него.

    3. В Sandboxie запустил второй клиент WoT и покатался в тренировочном бою сам с собой.

     

    К сожалению, дело к ночи - к тому же для полноценной пробы нужен второй "фанатик" (типа меня). В связи с этим управление пока не настраивал - надо к этому серьезно подойти.

     

    На правой половине сриншота видны очень интересные настройки (разрешение 800х600 и выше). При чем они высвечиваются всегда и при запущенном Vitrual Display Manager даже применяются, но при выборе их в обычном режиме разрешение сбрасывается в 1024х768.

    Я так думаю что это последствия добавления прямых значений в скрипты "X:\Games\World_of_Tanks\res\scripts\client\gui\graphicsresolutions.pyc" и "X:\Games\World_of_Tanks\res\scripts\client\gui\shared\utils\graphics.pyc" путем тупого компилирования и замены констант. Соответственно копать в ту сторону буду.

    • Upvote 1
    • Downvote 1
×
×
  • Create New...