-
Posts
829 -
Joined
-
Last visited
-
Days Won
7
Posts posted by kharlashkin
-
-
Пробовал через 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
Повторил второй раз проезд танка. Если нажать в бой и переключится в другое окно (в момент загрузки), после отсчета и прочего отправка клавиш работает.ХЗ от чего зависит.- 1
-
"Меня всегда поражало, как StranikS_Scan умеет всегда завести срач из ничего" © Lemon96
Истинно так ;)
- 1
-
Случайно наткнулся на утилиту 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()
Может это поможет понимающим людям понять как игра отрабатывает нажатия клавиш и можно будет туда добавить дополнительный обработчик.
- 1
- 1
-
Не ошибка, вы попытались просмотреть результат боя который был сыгран в прошлой сессии. В игре появляется сообщение что результат боя не доступен в питоне такой лог
Буду теперь знать что это такое. Спасибо!!!
Закрываю темку.
-
Как-то указанные ошибки, на мой взгляд, не очень вяжутся с изменением 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()
-
Ну а ради интереса не пробовали изменить и перекомпилировать 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 и выскочили те же ошибки, вот и вспомнил про темку.
Завтра раскомпилирую скрипты на которые ссылаются ошибки, посмотрим что там будет. Исправлять так исправлять ;)
-
Доброе время суток! Вопрос по прежнему актуален... Очень нужна помощь!
-
Доброе время суток всем! Давно не заходил на форум, и смотрю моей темой не интересуется никто. Наверное действительно эта тема не интересна.
- 1
-
Спасибо, будет полезно. Потому как иногда темы по несколько дней ваяются.
-
Может кто сделать например за эквивалент месяца премиума?
Наверное мало предложил ;) Может кто обосновать сумму необходимую?
- 1
- 1
-
Надо делать динамический зум миникарты :) Типа как в навигаторах - чем быстрее едешь, тем выше камеру поднимать. Кстати, вполне реально это сделать, хотя и геморно.
Плюсую. Будет прикольно, особенно (если принимать во внимание статистику обычного расположения противников) подкрашивать стрелку в соответствующий цвет.
Но на самом деле научиться играть лучше поможет только развитие умения ориентироваться в конкретной ситуации, а не тупая накатка предложенных шаблонов =)По моему мнению одно вытекает из другого, т.е. сначала режим обучения и накатка по шаблонам, затем уже сам игрок будет экспериментировать по полученному опыту.
-
Сегодня пришла следующая идея в голову, выношу её на общее обсуждение - от этого будет зависеть стоит дальше искать решение предложенной мною модификации или нет:
Есть скрипт управления курсором
'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)? Может кто сделать например за эквивалент месяца премиума?
- 1
- 1
-
Так-с осталось найти режиссера, продюссера и спонсора и дело в шляпе.
Сори за оффтоп (пишу по памяти):
Снимали фильм: режиссер - шизофреник, слепой оператор, глухой звукорежиссер, сценарист аутист, актеры дауны и т.п. Сняли, смонтировали, озвучили - Премьера, набилось полный зал интересующихся. В конце фильма остается в зале только режиссер и произносит: "А мне нравится!!!"
-
Вот идея для ТС-а, скинемся по рублю на сервер, запилим на нем пару сотен тысяч клонов такого интеллектуального бота и законнектим их на сервера ВГ. И будет идиллия - тысячи ботов с одного сервера катаются в онлайне на другом сервере.... очередной сюжет для голливудского фантастического блокбастера :)))))))))
А потом с помощью самообучающегося алгоритма боты начнут понимать - что как то не то, и начнут лезть на другие сервера и ...в конце концов образуют "SkyNet" и пошло-поехало :)
-
Я под столом лежал, правка мусора и петель через HxD - чел неделю ковырялся походу, либо просто прикалывается :))))
Идейный человек с морем терпения - из-за таких войну выиграли!
-
Завидую Вам всем "белой завистью" ;) Приятно, когда осознаешь, что на этом форуме собираются истинные профессионалы в программировании!
-
ну например я хотел бы чтонибудь такое что редко у кого есть, и что РЕАЛЬно в игре поможет
Ровные руки на python вряд ли можно сделать ;)
- 1
-
По поводу разделения игры на два окна.
Я пользуюсь NoFrame для фиксации окна игры, единое что она не работает с вторым окном, ну вы поговорите с автором.
Отписывался я в этой теме. Правда, не пробовал с запущенным VDM два ока без рамок, нужно попробовать как то в свободное время. В теме есть ещё ссылка на relocator - которая почти такая же утилита. Пробовал ещё и её перекомпилировать под нужные параметры - результат нет. Мне очень не понравилась эта VDM - ломает как то стандартный виндовый интерфейс. Да и не совсем мне понятно почему в полноэкранном режиме можно выставить любое разрешение, а в окошке минимум 1024х768. Так что поиск решения идет.
Где то встречал что WarGaming используют какой то "прием" для ускорения вывода изображений и не используют стандартные WinAPI, поэтому уменьшение картинки работает только с VDM (мне кажется утилита использует такой же или похожий прием, но так как VDM стартует сразу в окнах - имеет больший приоритет). В той же теме автор говорил о том, что это может быть функции не WinAPI а DirectX - соответственно должна быть другая утилита.
Блин я их перепробовал уже столько, что и не вспомнишь все (самая лучшая Snap - Win+стрелка вправо/стрелка влево, стандартная фича Windows 7).
- 1
- 1
-
Доброе время суток!
Мне (и не только мне) кажется. что тем способом, каким работает вибрация - нормально подключить геймпад не получиться. Клиент-серверная архитектура будет не так быстро работать, на вибрацию тайм-аут стоит 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>
Может кто подскажет дельное что-нибудь.
Кстати, следующий месяц я буду очень занят семейными делами, соответственно могу быстро не отвечать. Но очень жду помощи и правильного направления от знающих и понимающих людей!
- 1
- 1
-
Оказывается WoT принимает команды от геймпада почти "по-умолчанию". Спасибо inj3ct0r (я тебе должен) - подсказал как это проверить и дал скрипт, для отлавливания нажатий клавиш в ангаре с выводом системных сообщений.
Подключив геймпад к ноутбуку и жмакая кнопки увидел что игра принимает почти все нажатия, кроме крестовины и отклонения правого стика. В качестве пробы добавил кнопки в файл preferences.xml, как указано в этой теме на оф.форуме. В итоге - кнопки с геймпада действительно можно установить в качестве клавиш управления.
Теперь копаю скрипты из WoWP, там же геймпад полноценно поддерживается.
К сожалению, дело к ночи - к тому же для полноценной пробы нужен второй "фанатик" (типа меня). В связи с этим управление пока не настраивал - надо к этому серьезно подойти.Игра понимает только ввод данных из активного окна, разумеется когда два окна рядом одно из них будет активным, второе нет. Из-за этого и не пробовал данную теорию.
- 1
- 1
-
Сделал перерыв небольшой (голова пухнет от непонимания, что надо делать). Надо доставать опять книги по 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 не хочет помочь, хоть советом, хоть направлением, хоть куском кода. Я сам не потяну создание этого всего, в связи с чем и предлагаю денег за реализацию.
- 2
- 1
-
Пока не нашел в скриптах где-то ещё изменение минимального разрешения. Выкладываю тут скрипты снова (с измененными минимальными значениями):
'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 значениями. Подскажите где подчистить чтобы эта проверка не проходила.
- 1
- 1
-
def _TrackBreakingController__breakWithDirection(self, vehicle, isLeftTrackBroken):
directionMatrix = Math.Matrix(BigWorld.camera().source)
-------------------
def _TrackBreakingController__breakWithDirection(self, vehicle, isLeftTrackBroken):
directionMatrix = Math.Matrix(BigWorld.camera().matrix)
Очень хочется пояснений. Потому как это "картохины" скрипты.
-
Убил вечер, но есть некоторые результаты которыми стоит поделиться. Ниже скриншот успехов ;)
Итак по порядку.
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" путем тупого компилирования и замены констант. Соответственно копать в ту сторону буду.
- 1
- 1
Создание дополнительной информационной панели
in Modding General Discussion
Posted
Лучше пленочку )