-
Posts
829 -
Joined
-
Last visited
-
Days Won
7
Posts posted by kharlashkin
-
-
Чего ты перед ним оправдываешься? Он же ясно написал, что ему подставные бои надо катать.
Ну я из вежливости. Хотя сам один раз попадал в команду подставную автодобором - было невесело и "осадок" остался.
-
А что я нарушаю? Это заказ для программистов.Я готов заплатить и работать в дальнейшем. "Подставные бои/роты/прочее" На раз два три..... тоже запретить?
Я разве сказал, что Вы что-то нарушаете? По моему мнению нет. Но мало информации в запросе дают "полет для мыслей", а тема Ваша в запросе - наподобие этой. В которой нелестно отзывались сами разработчики модов. Например в моей теме я конкретно указываю что мне нужно и пытаюсь всеми силами помочь. Описывайте все что Вам надо детальней и много сэкономите времени всем.
Не ужели трудно в личке у автора приведенной мною темы спросить что как и к чему сначала - ему ведь кто-то сделал нужный Вам мод, взвесить все "за" и "против". И если уже не найдете ничего - тогда заводить отдельный топик ведь 1,5k рублей - недорого.
Просто немного раздражает что плодятся темы однотипного характера, вопросы которые в них поднимаются уже решены, мне кажется, есть люди которые на этом неплохо зарабатывают (в их понимании) и с подобными вопросами к ним.
Я прошу прощения - если вдруг я что-то написал обидчивое для Вас.
- 2
-
Я бы на месте моредераторов начал бы предупреждения выдавать за такие темы. "Оплачиваемые заказы" превращаются в "Подставные бои/роты/прочее". Жаль.
- 1
- 1
-
На просторах интернета нашел вот такую вещь.
Если не внимательно читали, то проблем с запуском двух клиентов WoT у меня нет. Но все равно спасибо!
Кстати, пришел к одному выводу - можно попробовать сделать это все "малой кровью". Относительно вывода двух окон было сообщение в самом начале (цена вопроса 35$), все управление вторым танком можно повесить на клавиатуру (без мыши), кнопок на клавиатуре больше чем в игре используется - хватит, Xpadder поддерживает одновременно много геймпадов, мод вибрации перепишу специально для второго экземпляра игры - второй геймпад.
В итоге можно сказать, что проблема решена. По моему мнению, это корявое и временное решение все равно надо опробовать - по результатам отпишусь.
- 1
- 1
-
Скрипт SettingsInterface интересный, там все есть - обработка нажатий кнопок, настройки мыши. Публикую его полностью:
'SettingsInterface'
import sys from functools import partial import BigWorld import itertools import SoundGroups import ResMgr import ArenaType from gui.Scaleform.daapi.view.lobby.settings.options import APPLY_METHOD from helpers import i18n from gui.Scaleform.managers.windows_stored_data import g_windowsStoredData import nations from account_helpers import gameplay_ctx from account_helpers.SettingsCore import g_settingsCore from gui import GUI_SETTINGS, g_guiResetters from gui.BattleContext import g_battleContext from gui.GraphicsPresets import GraphicsPresets from gui.GraphicsResolutions import g_graficsResolutions from gui.shared.utils.key_mapping import getScaleformKey from gui.Scaleform import VoiceChatInterface from windows import UIInterface from debug_utils import LOG_DEBUG, LOG_NOTE, LOG_ERROR from account_helpers.AccountSettings import AccountSettings from post_processing import g_postProcessing import CommandMapping import Settings from adisp import process from gui.Scaleform.Waiting import Waiting from Vibroeffects import VibroManager from LogitechMonitor import LogitechMonitor from helpers import getClientOverride class SettingsInterface(UIInterface): KEYBOARD_MAPPING_COMMANDS = {'movement': {'forward': 'CMD_MOVE_FORWARD', 'backward': 'CMD_MOVE_BACKWARD', 'left': 'CMD_ROTATE_LEFT', 'right': 'CMD_ROTATE_RIGHT', 'auto_rotation': 'CMD_CM_VEHICLE_SWITCH_AUTOROTATION'}, 'cruis_control': {'forward': 'CMD_INCREMENT_CRUISE_MODE', 'backward': 'CMD_DECREMENT_CRUISE_MODE', 'stop_fire': 'CMD_STOP_UNTIL_FIRE'}, 'firing': {'fire': 'CMD_CM_SHOOT', 'lock_target': 'CMD_CM_LOCK_TARGET', 'lock_target_off': 'CMD_CM_LOCK_TARGET_OFF', 'alternate_mode': 'CMD_CM_ALTERNATE_MODE', 'reloadPartialClip': 'CMD_RELOAD_PARTIAL_CLIP'}, 'vehicle_other': {'showHUD': 'CMD_TOGGLE_GUI', 'showRadialMenu': 'CMD_RADIAL_MENU_SHOW'}, 'equipment': {'item01': 'CMD_AMMO_CHOICE_1', 'item02': 'CMD_AMMO_CHOICE_2', 'item03': 'CMD_AMMO_CHOICE_3', 'item04': 'CMD_AMMO_CHOICE_4', 'item05': 'CMD_AMMO_CHOICE_5', 'item06': 'CMD_AMMO_CHOICE_6', 'item07': 'CMD_AMMO_CHOICE_7', 'item08': 'CMD_AMMO_CHOICE_8'}, 'shortcuts': {'attack': 'CMD_CHAT_SHORTCUT_ATTACK', 'to_base': 'CMD_CHAT_SHORTCUT_BACKTOBASE', 'positive': 'CMD_CHAT_SHORTCUT_POSITIVE', 'negative': 'CMD_CHAT_SHORTCUT_NEGATIVE', 'help_me': 'CMD_CHAT_SHORTCUT_HELPME', 'reload': 'CMD_CHAT_SHORTCUT_RELOAD'}, 'camera': {'camera_up': 'CMD_CM_CAMERA_ROTATE_UP', 'camera_down': 'CMD_CM_CAMERA_ROTATE_DOWN', 'camera_left': 'CMD_CM_CAMERA_ROTATE_LEFT', 'camera_right': 'CMD_CM_CAMERA_ROTATE_RIGHT'}, 'voicechat': {'pushToTalk': 'CMD_VOICECHAT_MUTE'}, 'logitech_keyboard': {'switch_view': 'CMD_LOGITECH_SWITCH_VIEW'}, 'minimap': {'sizeUp': 'CMD_MINIMAP_SIZE_UP', 'sizeDown': 'CMD_MINIMAP_SIZE_DOWN', 'visible': 'CMD_MINIMAP_VISIBLE'}} KEYBOARD_MAPPING_BLOCKS = {'movement': ('forward', 'backward', 'left', 'right', 'auto_rotation'), 'cruis_control': ('forward', 'backward', 'stop_fire'), 'firing': ('fire', 'lock_target', 'lock_target_off', 'alternate_mode', 'reloadPartialClip'), 'vehicle_other': ('showHUD', 'showRadialMenu'), 'equipment': ('item01', 'item02', 'item03', 'item04', 'item05', 'item06', 'item07', 'item08'), 'shortcuts': ('attack', 'to_base', 'positive', 'negative', 'help_me', 'reload'), 'camera': ('camera_up', 'camera_down', 'camera_left', 'camera_right'), 'voicechat': ('pushToTalk',), 'logitech_keyboard': ('switch_view',), 'minimap': ('sizeUp', 'sizeDown', 'visible')} KEYBOARD_MAPPING_BLOCKS_ORDER = ('movement', 'cruis_control', 'firing', 'vehicle_other', 'equipment', 'shortcuts', 'camera', 'voicechat', 'minimap', 'logitech_keyboard') POPULATE_UI = 'SettingsDialog.PopulateUI' APPLY_SETTINGS = 'SettingsDialog.ApplySettings' COMMIT_SETTINGS = 'SettingsDialog.CommitSettings' DELAY_SETTINGS = 'SettingsDialog.DelaySettings' AUTODETECT_QUALITY = 'SettingsDialog.AutodetectQuality' CURSOR_VALUES = {'mixing': 3, 'gunTag': 15, 'centralTag': 14, 'net': 4, 'reloader': 0, 'condition': 0, 'cassette': 0, 'reloaderTimer': 0} SNIPER_VALUES = {'snpMixing': 3, 'snpGunTag': 6, 'snpCentralTag': 14, 'snpNet': 4, 'snpReloader': 0, 'snpCondition': 0, 'snpCassette': 0, 'snpReloaderTimer': 0} MARKER_VALUES = {'Hp': 4, 'Name': 3} MARKER_TYPES = ['Base', 'Alt'] MOUSE_KEYS = {'ingame': {'arcadeSens': ('arcade', 'sensitivity'), 'sniperSens': ('sniper', 'sensitivity'), 'artSens': ('strategic', 'sensitivity'), 'horInvert': ('arcade', 'horzInvert'), 'vertInvert': ('arcade', 'vertInvert'), 'backDraftInvert': ('arcade', 'backDraftInvert')}, 'lobby': {'arcadeSens': ('arcadeMode/camera', 'sensitivity', 'float'), 'sniperSens': ('sniperMode/camera', 'sensitivity', 'float'), 'artSens': ('strategicMode/camera', 'sensitivity', 'float'), 'horInvert': ('arcadeMode/camera', 'horzInvert', 'bool'), 'vertInvert': ('arcadeMode/camera', 'vertInvert', 'bool'), 'backDraftInvert': ('arcadeMode/camera', 'backDraftInvert', 'bool')}, 'default': {'arcadeSens': 1, 'sniperSens': 1, 'artSens': 1, 'horInvert': False, 'vertInvert': False, 'backDraftInvert': False}} GAMEPLAY_KEY_FORMAT = 'gameplay_{0:>s}' GAMEPLAY_PREFIX = 'gameplay_' def __init__(self, enableRedefineKeysMode = True): UIInterface.__init__(self) if not GUI_SETTINGS.minimapSize and self.KEYBOARD_MAPPING_BLOCKS.has_key('minimap'): del self.KEYBOARD_MAPPING_BLOCKS['minimap'] self.__enableRedefineKeysMode = enableRedefineKeysMode self.graphicsPresets = GraphicsPresets() self.resolutions = g_graficsResolutions self.__currentSettings = None self.__settingsUI = None self.__altVoiceSetting = g_settingsCore.options.getSetting('alternativeVoices') if not GUI_SETTINGS.voiceChat and self.KEYBOARD_MAPPING_COMMANDS.has_key('voicechat'): if self.KEYBOARD_MAPPING_COMMANDS.has_key('voicechat'): del self.KEYBOARD_MAPPING_COMMANDS['voicechat'] if self.KEYBOARD_MAPPING_BLOCKS.has_key('voicechat'): del self.KEYBOARD_MAPPING_BLOCKS['voicechat'] self.KEYBOARD_MAPPING_BLOCKS_ORDER = list(self.KEYBOARD_MAPPING_BLOCKS_ORDER) del self.KEYBOARD_MAPPING_BLOCKS_ORDER[self.KEYBOARD_MAPPING_BLOCKS_ORDER.index('voicechat')] self.KEYBOARD_MAPPING_BLOCKS_ORDER = tuple(self.KEYBOARD_MAPPING_BLOCKS_ORDER) return def populateUI(self, proxy): UIInterface.populateUI(self, proxy) self.uiHolder.addExternalCallbacks({SettingsInterface.POPULATE_UI: self.onPopulateUI, SettingsInterface.APPLY_SETTINGS: self.onApplySettings, SettingsInterface.COMMIT_SETTINGS: self.onCommitSettings, SettingsInterface.DELAY_SETTINGS: self.onDelaySettings, SettingsInterface.AUTODETECT_QUALITY: self.onAutodetectSettings, 'SettingsDialog.useRedifineKeysMode': self.onUseRedifineKeyMode, 'SettingsDialog.processVivoxTest': self.onProcessVivoxTest, 'SettingsDialog.voiceChatEnable': self.onVoiceChatEnable, 'SettingsDialog.updateCaptureDevices': self.onUpdateCaptureDevices, 'SettingsDialog.setVivoxMicVolume': self.onSetVivoxMicVolume, 'SettingsDialog.killDialog': self.onDialogClose}) VibroManager.g_instance.onConnect += self.__vm_onConnect VibroManager.g_instance.onDisconnect += self.__vm_onDisconnect g_guiResetters.add(self.onRecreateDevice) BigWorld.wg_setAdapterOrdinalNotifyCallback(self.onRecreateDevice) def dispossessUI(self): if self.__settingsUI: self.__settingsUI.script = None self.__settingsUI = None self.__altVoiceSetting = None self.uiHolder.removeExternalCallbacks(SettingsInterface.POPULATE_UI, SettingsInterface.APPLY_SETTINGS, SettingsInterface.COMMIT_SETTINGS, SettingsInterface.DELAY_SETTINGS, SettingsInterface.AUTODETECT_QUALITY, 'SettingsDialog.useRedifineKeysMode', 'SettingsDialog.processVivoxTest', 'SettingsDialog.voiceChatEnable', 'SettingsDialog.updateCaptureDevices', 'SettingsDialog.setVivoxMicVolume', 'SettingsDialog.killDialog') VibroManager.g_instance.onConnect -= self.__vm_onConnect VibroManager.g_instance.onDisconnect -= self.__vm_onDisconnect g_guiResetters.discard(self.onRecreateDevice) BigWorld.wg_setAdapterOrdinalNotifyCallback(None) UIInterface.dispossessUI(self) return def altVoicesPreview(self, soundMode): if not self.__altVoiceSetting.isOptionEnabled(): return True if not g_battleContext.isInBattle: SoundGroups.g_instance.enableVoiceSounds(True) self.__altVoiceSetting.preview(soundMode) return self.__altVoiceSetting.playPreviewSound(self.uiHolder.soundManager) def isSoundModeValid(self, soundMode): self.__altVoiceSetting.preview(soundMode) valid = self.__altVoiceSetting.isSoundModeValid() self.__altVoiceSetting.revert() return valid def onSetVivoxMicVolume(self, callbackId, value): import VOIP if round(SoundGroups.g_instance.getVolume('micVivox') * 100) != value: SoundGroups.g_instance.setVolume('micVivox', value / 100) VOIP.getVOIPManager().setMicrophoneVolume(int(value)) def onVoiceChatEnable(self, callbackId, isEnable): self.__voiceChatEnable(isEnable) def __voiceChatEnable(self, isEnable): if isEnable is None: return else: preveVoIP = Settings.g_instance.userPrefs.readBool(Settings.KEY_ENABLE_VOIP) import VOIP if preveVoIP != isEnable: VOIP.getVOIPManager().enable(isEnable) Settings.g_instance.userPrefs.writeBool(Settings.KEY_ENABLE_VOIP, bool(isEnable)) from gui.WindowsManager import g_windowsManager if g_windowsManager.battleWindow is not None and not isEnable: g_windowsManager.battleWindow.speakingPlayersReset() LOG_NOTE('Change state of voip: %s' % str(isEnable)) return def __changeCaptureDevice(self, captureDeviceIdx): if captureDeviceIdx is None or captureDeviceIdx == -1: return else: import VOIP rh = VOIP.getVOIPManager() devices = [ i18n.encodeUtf8(device.decode(sys.getfilesystemencoding())) for device in rh.captureDevices ] if captureDeviceIdx < len(devices): newCaptureDevice = devices[captureDeviceIdx] previousDevice = Settings.g_instance.userPrefs.readString(Settings.KEY_VOIP_DEVICE) if previousDevice != newCaptureDevice: Settings.g_instance.userPrefs.writeString(Settings.KEY_VOIP_DEVICE, newCaptureDevice) LOG_NOTE('Change device of voip: %s' % str(newCaptureDevice)) return def onUseRedifineKeyMode(self, callbackId, isUse): if self.__enableRedefineKeysMode: BigWorld.wg_setRedefineKeysMode(isUse) def onProcessVivoxTest(self, callbackId, isStart): LOG_DEBUG('Vivox test: %s' % str(isStart)) import VOIP rh = VOIP.getVOIPManager() rh.enterTestChannel() if isStart else rh.leaveTestChannel() self.respond([callbackId, False]) def __vm_onConnect(self): self.call('SettingsDialog.VibroManager.Connect') def __vm_onDisconnect(self): self.call('SettingsDialog.VibroManager.Disconnect') def __getVideoSettings(self): settings = {} settings['monitor'] = {'current': self.resolutions.monitorIndex, 'real': self.resolutions.realMonitorIndex, 'options': self.resolutions.monitorsList} settings['fullScreen'] = not self.resolutions.isVideoWindowed settings['windowSize'] = {'current': self.resolutions.windowSizeIndex, 'options': self.resolutions.windowSizesList} settings['resolution'] = {'current': self.resolutions.videoModeIndex, 'options': self.resolutions.videoModesList} return settings def __getSettings(self): settings = [self.graphicsPresets.getGraphicsPresetsData()] import VOIP rh = VOIP.getVOIPManager() g_windowsStoredData.start() vManager = VibroManager.g_instance vEffGroups = vManager.getGroupsSettings() vEffDefGroup = VibroManager.VibroManager.GroupSettings() vEffDefGroup.enabled = False vEffDefGroup.gain = 0 markers = {'enemy': g_settingsCore.getSetting('enemy'), 'dead': g_settingsCore.getSetting('dead'), 'ally': g_settingsCore.getSetting('ally')} datetimeIdx = g_settingsCore.getSetting('showDateMessage') << 0 | g_settingsCore.getSetting('showTimeMessage') << 1 config = {'locale': getClientOverride(), 'aspectRatio': {'current': self.resolutions.aspectRatioIndex, 'options': self.resolutions.aspectRatiosList}, 'vertSync': self.resolutions.isVideoVSync, 'tripleBuffered': self.resolutions.isTripleBuffered, 'multisampling': {'current': self.resolutions.multisamplingTypeIndex, 'options': self.resolutions.multisamplingTypesList}, 'customAA': {'current': self.resolutions.customAAModeIndex, 'options': self.resolutions.customAAModesList}, 'gamma': self.resolutions.gamma, 'masterVolume': round(SoundGroups.g_instance.getMasterVolume() * 100), 'musicVolume': round(SoundGroups.g_instance.getVolume('music') * 100), 'voiceVolume': round(SoundGroups.g_instance.getVolume('voice') * 100), 'vehiclesVolume': round(SoundGroups.g_instance.getVolume('vehicles') * 100), 'effectsVolume': round(SoundGroups.g_instance.getVolume('effects') * 100), 'guiVolume': round(SoundGroups.g_instance.getVolume('gui') * 100), 'ambientVolume': round(SoundGroups.g_instance.getVolume('ambient') * 100), 'masterVivoxVolume': round(SoundGroups.g_instance.getVolume('masterVivox') * 100), 'micVivoxVolume': round(SoundGroups.g_instance.getVolume('micVivox') * 100), 'masterFadeVivoxVolume': round(SoundGroups.g_instance.getVolume('masterFadeVivox') * 100), 'captureDevice': self.__getCaptureDeviceSettings(), 'voiceChatNotSupported': rh.vivoxDomain == '' or not VoiceChatInterface.g_instance.ready, 'datetimeIdx': datetimeIdx, 'enableOlFilter': g_settingsCore.getSetting('enableOlFilter'), 'enableSpamFilter': g_settingsCore.getSetting('enableSpamFilter'), 'enableStoreChatMws': g_settingsCore.getSetting('enableStoreMws'), 'enableStoreChatCws': g_settingsCore.getSetting('enableStoreCws'), 'invitesFromFriendsOnly': g_settingsCore.getSetting('invitesFromFriendsOnly'), 'storeReceiverInBattle': g_settingsCore.getSetting('storeReceiverInBattle'), 'disableBattleChat': g_settingsCore.getSetting('disableBattleChat'), 'dynamicCamera': g_settingsCore.getSetting('dynamicCamera'), 'horStabilizationSnp': g_settingsCore.getSetting('horStabilizationSnp'), 'enableVoIP': VOIP.getVOIPManager().channelsMgr.enabled, 'enablePostMortemEffect': g_settingsCore.getSetting('enablePostMortemEffect'), 'enablePostMortemDelay': g_settingsCore.getSetting('enablePostMortemDelay'), 'nationalVoices': AccountSettings.getSettings('nationalVoices'), 'isColorBlind': AccountSettings.getSettings('isColorBlind'), 'useServerAim': g_settingsCore.getSetting('useServerAim'), 'showVehiclesCounter': g_settingsCore.getSetting('showVehiclesCounter'), 'minimapAlpha': g_settingsCore.getSetting('minimapAlpha'), 'vibroIsConnected': vManager.connect(), 'vibroGain': vManager.getGain() * 100, 'vibroEngine': vEffGroups.get('engine', vEffDefGroup).gain * 100, 'vibroAcceleration': vEffGroups.get('acceleration', vEffDefGroup).gain * 100, 'vibroShots': vEffGroups.get('shots', vEffDefGroup).gain * 100, 'vibroHits': vEffGroups.get('hits', vEffDefGroup).gain * 100, 'vibroCollisions': vEffGroups.get('collisions', vEffDefGroup).gain * 100, 'vibroDamage': vEffGroups.get('damage', vEffDefGroup).gain * 100, 'vibroGUI': vEffGroups.get('gui', vEffDefGroup).gain * 100, 'ppShowLevels': g_settingsCore.getSetting('ppShowLevels'), 'ppShowTypes': AccountSettings.getSettings('players_panel')['showTypes'], 'replayEnabled': g_settingsCore.options.getSetting('replayEnabled').pack(), 'fpsPerfomancer': g_settingsCore.getSetting('fpsPerfomancer'), 'arcade': {'values': g_settingsCore.options.getSetting('arcade').toAccountSettings(), 'options': SettingsInterface.CURSOR_VALUES}, 'sniper': {'values': g_settingsCore.options.getSetting('sniper').toAccountSettings(), 'options': SettingsInterface.SNIPER_VALUES}, 'markers': {'values': markers, 'options': SettingsInterface.MARKER_VALUES, 'types': SettingsInterface.MARKER_TYPES}} if self.__altVoiceSetting.isOptionEnabled(): altVoices = [] for idx, desc in enumerate(self.__altVoiceSetting.getOptions()): altVoices.append({'data': idx, 'label': desc}) config['alternativeVoices'] = {'current': self.__altVoiceSetting.get(), 'options': altVoices} for name in ('ctf', 'domination', 'assault', 'nations'): key = self.GAMEPLAY_KEY_FORMAT.format(name) config[key] = g_settingsCore.getSetting(key) settings.append(config) if not LogitechMonitor.isPresentColor(): if self.KEYBOARD_MAPPING_BLOCKS.has_key('logitech_keyboard'): del self.KEYBOARD_MAPPING_BLOCKS['logitech_keyboard'] else: self.KEYBOARD_MAPPING_BLOCKS['logitech_keyboard'] = ('switch_view',) cmdMap = CommandMapping.g_instance defaults = cmdMap.getDefaults() keyboard = [] for group_name in self.KEYBOARD_MAPPING_BLOCKS_ORDER: if group_name in self.KEYBOARD_MAPPING_BLOCKS.keys(): group = {'id': group_name, 'commands': []} keyboard.append(group) for key_setting in self.KEYBOARD_MAPPING_BLOCKS[group_name]: command = cmdMap.getCommand(self.KEYBOARD_MAPPING_COMMANDS[group_name][key_setting]) keyCode = cmdMap.get(self.KEYBOARD_MAPPING_COMMANDS[group_name][key_setting]) defaultCode = defaults[command] if defaults.has_key(command) else 0 key = {'id': key_setting, 'command': command, 'key': getScaleformKey(keyCode), 'keyDefault': getScaleformKey(defaultCode)} group['commands'].append(key) settings.append(keyboard) mouse = {} player = BigWorld.player() if hasattr(player.inputHandler, 'ctrls'): for key, path in SettingsInterface.MOUSE_KEYS['ingame'].items(): if key == 'horInvert': value = g_settingsCore.getSetting('mouseHorzInvert') elif key == 'vertInvert': value = g_settingsCore.getSetting('mouseVertInvert') elif key == 'backDraftInvert': value = g_settingsCore.getSetting('backDraftInvert') else: value = player.inputHandler.ctrls[path[0]].camera.getUserConfigValue(path[1]) mouse[key] = {'defaultValue': SettingsInterface.MOUSE_KEYS['default'][key], 'value': value} else: ds = Settings.g_instance.userPrefs[Settings.KEY_CONTROL_MODE] for key, path in SettingsInterface.MOUSE_KEYS['lobby'].items(): default = SettingsInterface.MOUSE_KEYS['default'][key] value = default if key == 'horInvert': value = g_settingsCore.getSetting('mouseHorzInvert') elif key == 'vertInvert': value = g_settingsCore.getSetting('mouseVertInvert') elif key == 'backDraftInvert': value = g_settingsCore.getSetting('backDraftInvert') elif ds is not None: if path[2] == 'float': value = ds[path[0]].readFloat(path[1], default) elif path[2] == 'bool': value = ds[path[0]].readBool(path[1], default) else: LOG_DEBUG('Unknown mouse settings type %s %s' % (key, path)) mouse[key] = {'defaultValue': default, 'value': value} settings.append(mouse) g_windowsStoredData.stop() return settings def __getCaptureDeviceSettings(self): import VOIP rh = VOIP.getVOIPManager() devices = [ i18n.encodeUtf8(device.decode(sys.getfilesystemencoding())) for device in rh.captureDevices ] currentDeviceName = Settings.g_instance.userPrefs.readString(Settings.KEY_VOIP_DEVICE) currentCaptureDeviceIdx = -1 try: currentCaptureDeviceIdx = devices.index(currentDeviceName) except: try: currentCaptureDeviceIdx = rh.captureDevices.index(rh.currentCaptureDevice) except: pass settings = {'current': currentCaptureDeviceIdx, 'options': devices} return settings def onUpdateCaptureDevices(self, callbackId): self.__updateCaptureDevices() @process def __updateCaptureDevices(self): Waiting.show('__updateCaptureDevices') devices = yield VoiceChatInterface.g_instance.requestCaptureDevices() currentDeviceName = Settings.g_instance.userPrefs.readString(Settings.KEY_VOIP_DEVICE) currentCaptureDeviceIdx = -1 try: currentCaptureDeviceIdx = devices.index(currentDeviceName) except Exception: try: import VOIP currentCaptureDeviceIdx = devices.index(VOIP.getVOIPManager().currentCaptureDevice) except Exception: pass value = [currentCaptureDeviceIdx] value.extend([ i18n.encodeUtf8(d.decode(sys.getfilesystemencoding())) for d in devices ]) Waiting.hide('__updateCaptureDevices') self.call('SettingsDialog.updateCaptureDevices', value) def onRecreateDevice(self): if self.__settingsUI: if self.__currentSettings and self.__currentSettings != self.__getVideoSettings(): self.__currentSettings = self.__getVideoSettings() self.__settingsUI.buildGraphicsData(self.__getVideoSettings()) def onAutodetectSettings(self, callbackID): presetIndex = BigWorld.autoDetectGraphicsSettings() self.call('SettingsDialog.setPreset', [presetIndex]) def onPopulateUI(self, *args): self.graphicsPresets.checkCurrentPreset(True) self.__currentSettings = self.__getVideoSettings() VoiceChatInterface.g_instance.processFailedMessage() if self.__settingsUI: self.__settingsUI.script = None self.__settingsUI = None settingsDialogName = args[1] self.__settingsUI = self.uiHolder.getMember(settingsDialogName) if self.__settingsUI: settings = self.__getSettings() self.__settingsUI.buildData(settings[0], settings[1], settings[2], settings[3]) self.__settingsUI.buildGraphicsData(self.__getVideoSettings()) self.__settingsUI.script = self else: LOG_ERROR('settingsDialog is not found in flash by name {0}'.format(settingsDialogName)) return def onApplySettings(self, callbackId, settings): monitorIndex, presetIndex, settingsList, fullscreen = settings if (not self.resolutions.isVideoWindowed or fullscreen) and (monitorIndex != self.resolutions.realMonitorIndex or self.resolutions.monitorChanged): self.call('SettingsDialog.ApplySettings', ['restartNeeded']) return applyMethod = g_settingsCore.options.getApplyMethod(settingsList) method = 'apply' if applyMethod == APPLY_METHOD.RESTART: method = 'restartNeeded' elif applyMethod == APPLY_METHOD.DELAYED: method = 'hasPendingSettings' self.call('SettingsDialog.ApplySettings', [method]) def onDelaySettings(self, *args): self.apply(False, *args) def onCommitSettings(self, *args): self.apply(True, *args) def apply(self, restartApproved, callbackId, settings): restartClient = False import VOIP ppSettings = dict(AccountSettings.getSettings('players_panel')) ppSettings['showTypes'] = settings['ppShowTypes'] if (not self.resolutions.isVideoWindowed or settings['fullScreen']) and (settings['monitor'] != self.resolutions.realMonitorIndex or self.resolutions.monitorChanged): restartClient = True AccountSettings.setSettings('players_panel', ppSettings) g_settingsCore.applySetting('ppShowLevels', settings['ppShowLevels']) g_settingsCore.applySetting('replayEnabled', settings['replayEnabled']) g_settingsCore.applySetting('fpsPerfomancer', settings['fpsPerfomancer']) AccountSettings.setSettings('nationalVoices', settings['nationalVoices']) AccountSettings.setSettings('isColorBlind', settings['isColorBlind']) g_settingsCore.applySetting('useServerAim', settings['useServerAim']) g_settingsCore.applySetting('showVehiclesCounter', settings['showVehiclesCounter']) g_settingsCore.applySetting('minimapAlpha', settings['minimapAlpha']) arcade = g_settingsCore.options.getSetting('arcade').fromAccountSettings(settings['arcade']) sniper = g_settingsCore.options.getSetting('sniper').fromAccountSettings(settings['sniper']) g_settingsCore.applySetting('arcade', arcade) g_settingsCore.applySetting('sniper', sniper) g_settingsCore.applySetting('enemy', settings['markers']['enemy']) g_settingsCore.applySetting('dead', settings['markers']['dead']) g_settingsCore.applySetting('ally', settings['markers']['ally']) g_settingsCore.applySetting('dynamicCamera', settings['dynamicCamera']) g_settingsCore.applySetting('horStabilizationSnp', settings['horStabilizationSnp']) if self.__altVoiceSetting.isOptionEnabled(): altVoices = settings.get('alternativeVoices') if altVoices is not None: self.__altVoiceSetting.apply(altVoices) vManager = VibroManager.g_instance vManager.setGain(settings['vibroGain'] / 100.0) vEffGroups = vManager.getGroupsSettings() for groupName, newValue in [('engine', settings['vibroEngine']), ('acceleration', settings['vibroAcceleration']), ('shots', settings['vibroShots']), ('hits', settings['vibroHits']), ('collisions', settings['vibroCollisions']), ('damage', settings['vibroDamage']), ('gui', settings['vibroGUI'])]: if groupName in vEffGroups: vEffGroups[groupName].gain = newValue / 100.0 vEffGroups[groupName].enabled = newValue > 0 vManager.setGroupsSettings(vEffGroups) self.__voiceChatEnable(settings['enableVoIP']) self.__changeCaptureDevice(settings[Settings.KEY_VOIP_DEVICE]) g_settingsCore.applySetting('enablePostMortemEffect', settings['enablePostMortemEffect']) g_settingsCore.applySetting('enablePostMortemDelay', settings['enablePostMortemDelay']) self.uiHolder.clearCommands() keyboard = settings['controls']['keyboard'] keyboardMapping = {} keysLayout = dict(g_settingsCore.options.getSetting('keyboard').KEYS_LAYOUT) layout = list(itertools.chain(*keysLayout.values())) for i in xrange(len(self.KEYBOARD_MAPPING_BLOCKS)): group_name = keyboard[i]['id'] for j in xrange(len(self.KEYBOARD_MAPPING_BLOCKS[group_name])): key_name = keyboard[i]['commands'][j]['id'] value = keyboard[i]['commands'][j]['key'] cmd = self.KEYBOARD_MAPPING_COMMANDS[group_name][key_name] for item in layout: key, command = item[0], item[1] if command == cmd: keyboardMapping[key] = value break g_settingsCore.applySetting('keyboard', keyboardMapping) self.uiHolder.bindCommands() player = BigWorld.player() mouse = settings['controls']['mouse'] if hasattr(player.inputHandler, 'ctrls'): player.inputHandler.ctrls['arcade'].camera.setUserConfigValue('sensitivity', mouse['arcadeSens']['value']) player.inputHandler.ctrls['sniper'].camera.setUserConfigValue('sensitivity', mouse['sniperSens']['value']) player.inputHandler.ctrls['strategic'].camera.setUserConfigValue('sensitivity', mouse['artSens']['value']) else: ds = Settings.g_instance.userPrefs[Settings.KEY_CONTROL_MODE] if ds: ds['arcadeMode/camera'].writeFloat('sensitivity', mouse['arcadeSens']['value']) ds['sniperMode/camera'].writeFloat('sensitivity', mouse['sniperSens']['value']) ds['strategicMode/camera'].writeFloat('sensitivity', mouse['artSens']['value']) g_settingsCore.applySetting('mouseHorzInvert', bool(mouse['horInvert']['value'])) g_settingsCore.applySetting('mouseVertInvert', bool(mouse['vertInvert']['value'])) g_settingsCore.applySetting('backDraftInvert', bool(mouse['backDraftInvert']['value'])) self.resolutions.applyChanges(settings['fullScreen'], settings['vertSync'], settings['tripleBuffered'], settings['windowSize'] if not settings['fullScreen'] else settings['resolution'], settings['aspectRatio'], settings['multisampling'], settings['customAA'], settings['gamma'], settings['monitor']) if round(SoundGroups.g_instance.getVolume('masterVivox') * 100) != settings['masterVivoxVolume']: VOIP.getVOIPManager().setMasterVolume(settings['masterVivoxVolume']) if round(SoundGroups.g_instance.getVolume('micVivox') * 100) != settings['micVivoxVolume']: VOIP.getVOIPManager().setMicrophoneVolume(settings['micVivoxVolume']) SoundGroups.g_instance.setMasterVolume(float(settings['masterVolume']) / 100) SoundGroups.g_instance.setVolume('music', float(settings['musicVolume']) / 100) SoundGroups.g_instance.setVolume('voice', float(settings['voiceVolume']) / 100) SoundGroups.g_instance.setVolume('vehicles', float(settings['vehiclesVolume']) / 100) SoundGroups.g_instance.setVolume('effects', float(settings['effectsVolume']) / 100) SoundGroups.g_instance.setVolume('gui', float(settings['guiVolume']) / 100) SoundGroups.g_instance.setVolume('ambient', float(settings['ambientVolume']) / 100) SoundGroups.g_instance.setVolume('masterVivox', float(settings['masterVivoxVolume']) / 100) SoundGroups.g_instance.setVolume('micVivox', float(settings['micVivoxVolume']) / 100) SoundGroups.g_instance.setVolume('masterFadeVivox', float(settings['masterFadeVivoxVolume']) / 100) if len(VOIP.getVOIPManager().captureDevices): device = VOIP.getVOIPManager().captureDevices[0] if len(VOIP.getVOIPManager().captureDevices) > settings['captureDevice']: device = VOIP.getVOIPManager().captureDevices[settings['captureDevice']] VOIP.getVOIPManager().setCaptureDevice(device) g_settingsCore.applySetting('showDateMessage', settings['datetimeIdx'] & 1) g_settingsCore.applySetting('showTimeMessage', settings['datetimeIdx'] & 2) g_settingsCore.applySetting('enableOlFilter', settings['enableOlFilter']) g_settingsCore.applySetting('enableSpamFilter', settings['enableSpamFilter']) g_windowsStoredData.start() g_settingsCore.applySetting('enableStoreMws', settings['enableStoreChatMws']) g_settingsCore.applySetting('enableStoreCws', settings['enableStoreChatCws']) g_windowsStoredData.stop() g_settingsCore.applySetting('invitesFromFriendsOnly', settings['invitesFromFriendsOnly']) g_settingsCore.applySetting('storeReceiverInBattle', settings['storeReceiverInBattle']) g_settingsCore.applySetting('disableBattleChat', settings['disableBattleChat']) gameplayKeys = filter(lambda item: item.startswith(self.GAMEPLAY_PREFIX), settings.keys()) for key in gameplayKeys: g_settingsCore.applySetting(key, settings[key]) qualitySettings = settings['quality'] applyMethod = g_settingsCore.options.getApplyMethod(qualitySettings) for key in GraphicsPresets.GRAPHICS_QUALITY_SETTINGS: value = qualitySettings.get(key) if value is not None: g_settingsCore.applySetting(key, value) if applyMethod == APPLY_METHOD.RESTART: BigWorld.commitPendingGraphicsSettings() restartClient = True elif applyMethod == APPLY_METHOD.DELAYED: BigWorld.commitPendingGraphicsSettings() g_settingsCore.applyStorages() g_postProcessing.refresh() if restartClient: BigWorld.savePreferences() if restartApproved: from BattleReplay import g_replayCtrl if g_replayCtrl.isPlaying and g_replayCtrl.playbackSpeed == 0: g_replayCtrl.setPlaybackSpeedIdx(5) BigWorld.callback(0.3, BigWorld.restartGame) else: BigWorld.callback(0.0, partial(BigWorld.changeVideoMode, -1, BigWorld.isVideoWindowed())) return def onDialogClose(self, _): if self.__altVoiceSetting.isOptionEnabled(): self.__altVoiceSetting.revert() if not g_battleContext.isInBattle: SoundGroups.g_instance.enableVoiceSounds(False) elif hasattr(BigWorld.player(), 'vehicle'): SoundGroups.g_instance.soundModes.setCurrentNation(nations.NAMES[BigWorld.player().vehicle.typeDescriptor.type.id[0]]) g_settingsCore.clearStorages() if self.__settingsUI: self.__settingsUI.script = None self.__settingsUI = None return
В этом сообщении уважаемый sirmax, говорил о добавлении отдельных методов, не трогая оригинальные скрипты. Возможно сюда стоит добавить метод который будет брать значения кнопок/стиков/триггеров и предоставлять их как кнопки клавиатуры/мыши.
- 1
- 1
-
Да пусть обрабатывает, нужно чтобы он правильно обрабатывал - нужные нажатия, а не все подряд.Быть может, что worldoftanks.exe сам обрабатывает нажатия кнопок.
- 2
- 1
-
Спасибо за поддержку . В принципе, по логике вещей, ответ где-то рядом.@kharlashkin, Эх, я б вам помог, если бы знал пайтон... Но если будет необходимость в exe'шках и dll'ках, то пишите мне, я помогу.
Лучше поспрашивайте на форумах по пайтону. Я уверен, что среди програмистов должны быть любители танков.
Мое видение данного мода такое - таким же образом как в "вибромоде" вызываем системный python, с помощью pygame берем данные о нажатии кнопок/перемещении стиков, переназначаем их в соответствии с управлением в игре (я довольно долго экспериментировал с удобством игры на геймпаде - моя тема на оф.форуме), и отдаем команды непосредственно в игру. Вот с последним моментом пока проблема - ищу.
- 2
- 1
-
@kharlashkin, я перенёс вашу тему уровнем выше, поскольку она носит скорее характер поиска решения, нежели конкретного заказа. Возможно в этом разделе она получит больший отклик.
Да, согласен. Если при написании мода для "вибрации" - было понятно куда копать, то в данном случае не понятно. Необходимо сначала найти решение, а потом уже писать мод.
В скрипте X:\Games\World_of_Tanks\res\scripts\client\gui\Scaleform\SettingsInterface.py вот это меня заинтересовало
'SettingsInterface.py'
mouse = settings['controls']['mouse'] if hasattr(player.inputHandler, 'ctrls'): player.inputHandler.ctrls['arcade'].camera.setUserConfigValue('sensitivity', mouse['arcadeSens']['value']) player.inputHandler.ctrls['sniper'].camera.setUserConfigValue('sensitivity', mouse['sniperSens']['value']) player.inputHandler.ctrls['strategic'].camera.setUserConfigValue('sensitivity', mouse['artSens']['value']) else: ds = Settings.g_instance.userPrefs[Settings.KEY_CONTROL_MODE] if ds: ds['arcadeMode/camera'].writeFloat('sensitivity', mouse['arcadeSens']['value']) ds['sniperMode/camera'].writeFloat('sensitivity', mouse['sniperSens']['value']) ds['strategicMode/camera'].writeFloat('sensitivity', mouse['artSens']['value']) g_settingsCore.applySetting('mouseHorzInvert', bool(mouse['horInvert']['value'])) g_settingsCore.applySetting('mouseVertInvert', bool(mouse['vertInvert']['value'])) g_settingsCore.applySetting('backDraftInvert', bool(mouse['backDraftInvert']['value']))
Насколько я понимаю это настройки для мышки. Может как то это можно использовать...
Только заметил, что не опубликовал код тестовый для pygame, исправил это в сообщении про pygame.
- 2
- 1
-
Нашел скрипт управления курсором в игре
'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)
Знающие люди помогите! Кто может рассказать и объяснить что к чему в скрипте. Общее понятие у меня есть о том что к чему, но хочется убедиться в правильности предположений.
Нашел интересную темку, которая возможно сможет помочь в направлении использования стиков вместо мыши: Ошибка мода, пропадает обзор мышью.Нет там в теме ничего, что может помочь.
В принципе раскомпилировал уже всю игру - но не вывешивать же весь код сюда ;)
- 1
- 1
-
Просьба к форумчанам - кто нибудь подскажите, где лежат скрипты для клавиатуры/мыши в WoT?
Начал методично декомпилировать скрипты из игры и проверять. наткнулся на срипт graphicsresolutions.py в папке X:\Games\World_of_Tanks\res\scripts\client\gui\
'graphicsresolutions.py'
import BigWorld from debug_utils import LOG_CURRENT_EXCEPTION, LOG_ERROR, LOG_DEBUG class GraphicsResolutions(object): MIN_HEIGHT = 1024 MIN_WIDTH = 768 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()
Простая замена MIN_HEIGHT = 1024 и MIN_WIDTH = 768, на MIN_HEIGHT = 800 и MIN_WIDTH = 600 ничего не дала (я как бы и не надеялся, что взлетит - но решил попробовать), но по крайней мере есть хоть какое-то направление :)
Так же пробовал одновременно запускать тестовую программку pygame и скрипт вибрации - не мешают друг другу, pygame отлавливает нажатия кнопок и перемещение стиков/триггеров и одновременно геймпад вибрирует.
- 1
- 1
-
Стата и медальки - это разные вещи. 17 воинов за 10к боев - это еще раз доказывает, что гейпад надо выбрасывать и играть как все нормальные люди. Нормальный показатель ~80-100 воинов на 10к боев.
Я то как раз понимаю, про что говорю, вы не очень - 490 урона за бой это считаете вы тащили стреляя с авто прицела?! Быстро выцеливать слабые места противника на гейпаде не реально! Поэтому для них и предусмотрена резервация в большенстве нормальных игр.
Подавайте хоть в Гамбургский суд, там пекутся за права геев и других больных, которых током нужно лечить давно.
Предупреждение:- Оскорбление участников форума
- Оффтоп в разделе оплачиваемых заказов
Невнимательно читаете, уважаемый inq.
Как раз до игры на геймпаде я был "крабом" и "оленем". Играл на нетбуке 12' и не заморачивался вообще ни со стратегией, ни с логикой игры - только "Оло-ло раш! Пыщь-пыщь! И слив в первые пару минут". Так был отыгран почти год (думаю, что около 5k боев). Хочу так же напомнить, что на низких уровнях до 5 уровня включительно - попробуйте наносить хотя бы 300 урона среднего.
С автоприцелом я никогда не играл, даже сейчас на AMX1375 с геймпадом (!) не использую автоприцел (121 бой на 15.03.2014, 50% побед, знак классности 2)
- 1
- 1
-
Между прочем мой первый "воин" (как и все остальные) был получен именно на геймпаде, до сих пор помню дрожь в руках.Стата как раз доказывает, что так играть нельзя! Средний урон 490 это 2-3 пробития за бой, 49% побед говорит о дичайшем везении, тащила команда.
Я из тех, кто ненавидит сливающихся аутистов в первые 3 мин боя или стоящих/катающихся черти где.
У гейпадов есть своя резервация, ползайте там раз Вам так это нравиться. Смешивать консоль и PC это идиотизм.
"Скриншот результатов"
Все танки 6 лвл и выше игрались только на гемйпаде.
49% из более 10k боев "тащила команда" - Вы хоть понимаете о чем говорите?
В общем прошу Вас не флудить в теме - идите на оф.форум и заведите свою тему по поводу кол-ва "крабов" в игре, иначе придется подать на Вас жалобу модераторам.
- 3
- 1
-
На официальном форуме есть мой гайд с игрой в танки на геймпаде. Там же выложены мои мысли относительно управления в WoT в сравнении с шутерами. "Стата" - лучшее доказательство возможности так играть. Я не "цифродрочер" и играю без премиума, так что мои показатели ничем не лучше и не хуже других игроков. А Вы из тех, кто считает всех игроков "ракообразными", играющих для "пыщь-пыщь"?Играть на геймпаде в шуторо-подобные игры гейство. Любой более менее адекватный игрок на клаве и мыше вывертить гейпада в 0.
Хотите играть лежа на диване, купите X-box и не страдайте фигней.
- 2
- 1
-
Вчера вечером пробовал pygame, тестовый скрипт из раздела документации без проблем определил геймпад, захватывал значения стиков/тригеров нажатия кнопок.
Если я правильно понял - pygame использует библиотеку SDL, которая, в свою очередь, имеет реализацию для Python. К тому же с версии 2.0 поддерживается так же вибрационная связь с геймпадами. Направление наверное уже точно определено ;) Можно с помощью XPM заменить нужный метод и игра будет принимать значения от геймпада как от клавиатуры/мыши.
Просьба к форумчанам - кто нибудь подскажите, где лежат скрипты для клавиатуры/мыши в WoT?
P.S. Тестовый код для проверки работы pygame с геймпадами:
'testpygame.py'
# Sample Python/Pygame Programs # Simpson College Computer Science # http://programarcadegames.com/ # http://simpson.edu/computer-science/ import pygame # Define some colors BLACK = ( 0, 0, 0) WHITE = ( 255, 255, 255) # This is a simple class that will help us print to the screen # It has nothing to do with the joysticks, just outputing the # information. class TextPrint: def __init__(self): self.reset() self.font = pygame.font.Font(None, 20) def Print(self, screen, textString): textBitmap = self.font.render(textString, True, BLACK) screen.blit(textBitmap, [self.x, self.y]) self.y += self.line_height def reset(self): self.x = 10 self.y = 10 self.line_height = 15 def indent(self): self.x += 10 def unindent(self): self.x -= 10 pygame.init() # Set the width and height of the screen [width,height] size = [500, 700] screen = pygame.display.set_mode(size) pygame.display.set_caption("My Game") #Loop until the user clicks the close button. done = False # Used to manage how fast the screen updates clock = pygame.time.Clock() # Initialize the joysticks pygame.joystick.init() # Get ready to print textPrint = TextPrint() # -------- Main Program Loop ----------- while done==False: # EVENT PROCESSING STEP for event in pygame.event.get(): # User did something if event.type == pygame.QUIT: # If user clicked close done=True # Flag that we are done so we exit this loop # Possible joystick actions: JOYAXISMOTION JOYBALLMOTION JOYBUTTONDOWN JOYBUTTONUP JOYHATMOTION if event.type == pygame.JOYBUTTONDOWN: print("Joystick button pressed.") if event.type == pygame.JOYBUTTONUP: print("Joystick button released.") # DRAWING STEP # First, clear the screen to white. Don't put other drawing commands # above this, or they will be erased with this command. screen.fill(WHITE) textPrint.reset() # Get count of joysticks joystick_count = pygame.joystick.get_count() textPrint.Print(screen, "Number of joysticks: {}".format(joystick_count) ) textPrint.indent() # For each joystick: for i in range(joystick_count): joystick = pygame.joystick.Joystick(i) joystick.init() textPrint.Print(screen, "Joystick {}".format(i) ) textPrint.indent() # Get the name from the OS for the controller/joystick name = joystick.get_name() textPrint.Print(screen, "Joystick name: {}".format(name) ) # Usually axis run in pairs, up/down for one, and left/right for # the other. axes = joystick.get_numaxes() textPrint.Print(screen, "Number of axes: {}".format(axes) ) textPrint.indent() for i in range( axes ): axis = joystick.get_axis( i ) textPrint.Print(screen, "Axis {} value: {:>6.3f}".format(i, axis) ) textPrint.unindent() buttons = joystick.get_numbuttons() textPrint.Print(screen, "Number of buttons: {}".format(buttons) ) textPrint.indent() for i in range( buttons ): button = joystick.get_button( i ) textPrint.Print(screen, "Button {:>2} value: {}".format(i,button) ) textPrint.unindent() # Hat switch. All or nothing for direction, not like joysticks. # Value comes back in an array. hats = joystick.get_numhats() textPrint.Print(screen, "Number of hats: {}".format(hats) ) textPrint.indent() for i in range( hats ): hat = joystick.get_hat( i ) textPrint.Print(screen, "Hat {} value: {}".format(i, str(hat)) ) textPrint.unindent() textPrint.unindent() # ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT # Go ahead and update the screen with what we've drawn. pygame.display.flip() # Limit to 20 frames per second clock.tick(20) # Close the window and quit. # If you forget this line, the program will 'hang' # on exit if running from IDLE. pygame.quit ()
- 2
- 1
-
Нашел несколько интересных проектов, которые могут позволить подключать геймпады напрямую в WoT. Разумеется требуется "доработка напильником" но направления интересные.
1. ioHub.
3. Using XInput to access an Xbox 360 Controller in Managed Code.
4. Xbox 360 Controller Input in C++ with XInput.
Начинаю склоняться в сторону написанию своего эмулятора на Python, для вызова непосредственно в WoT способом который использовался для "мода вибраций".
- 2
- 1
-
Портативный клиент пробовали? Я, правда, не знаю, можно ли запустить 2 клиента одновременно.
Скачал, распаковал, попробовал - фигня :( fps при худших текстурах тот же, два клиента не запускается (я глубоко не копал, жду ответа от разаботчика), хотя использует функционал Sandboxie.
Пробовал в виртуальной машине создать свою портативную версию танков с помощью VMWare ThinApp. На голой Windows 7 все сделал, получился монстр в 12,5 ГБ. Я правда выбрал виртуализировать все приложения, что нашла утилита создания. Надо протестировать и потом уже пробовать сокращать размер "портативных танков thinapp".
Тестировал эмулятор FreePIE. От неё осталось какое-то двойственное впечатление.
1. За пару часов почти все настроил, кстати делюсь своим "черновым" скриптом:
'xboxtest1.py'
def update(): #LMouseClick Attack with weapon or cast spell in right hand (primary hand maps to primary mouse) mouse.leftButton = xbox360[0].rightTrigger #RMouseClick Attack with weapon or cast spell in left hand / Block if available mouse.rightButton = xbox360[0].rightShoulder #E Activate/use/hold to manipulate objects keyboard.setKey(Key.Q, xbox360[0].x) #Alt Sprint keyboard.setKey(Key.LeftShift, xbox360[0].rightThumb) #Shift Walk (slower and quieter than default movement) keyboard.setKey(Key.R, xbox360[0].b) #Ctrl Crouch/sneak mode keyboard.setKey(Key.LeftControl, xbox360[0].leftThumb) #Space Jump keyboard.setKey(Key.F, xbox360[0].a) #F Change views (1st and 3rd person) keyboard.setKey(Key.Z, xbox360[0].y) #Tab Character Menu keyboard.setKey(Key.Return, xbox360[0].start) #Esc Menu keyboard.setKey(Key.Escape, xbox360[0].back) #P Magic menu keyboard.setKey(Key.W, xbox360[0].up) #M Map keyboard.setKey(Key.A, xbox360[0].left) #I inventory keyboard.setKey(Key.S, xbox360[0].down) #T Wait keyboard.setKey(Key.D, xbox360[0].right) #Q Favorites - not supported #C Toggle Automove / Zoom item in inventory - not supported #/ Perk menu - not supported #Z Racial power/Dragon shout - not supported #Mwheel Scroll in menus or zoom while in 3rd person - not supported #1-8 Hotkeys (no numpad) - Not supported #` Open/close the console (~ key) - not supported if (xbox360[0].leftStickX) > 0.25: mouse.deltaX = (xbox360[0].leftStickX - 0.25) * 0.5 if (xbox360[0].leftStickX) < -0.25: mouse.deltaX = (xbox360[0].leftStickX + 0.25) * 0.5 if (xbox360[0].leftStickY) > 0.25: mouse.deltaY = -(xbox360[0].leftStickY - 0.25) * 0.5 if (xbox360[0].leftStickY) < -0.25: mouse.deltaY = -(xbox360[0].leftStickY + 0.25) * 0.5 #MouseLook if (xbox360[0].rightStickX) > 0.25: mouse.deltaX = (xbox360[0].rightStickX - 0.25) * 2 if (xbox360[0].rightStickX) < -0.25: mouse.deltaX = (xbox360[0].rightStickX + 0.25) * 2 if (xbox360[0].rightStickY) > 0.25: mouse.deltaY = -(xbox360[0].rightStickY - 0.25) * 2 if (xbox360[0].rightStickY) < -0.25: mouse.deltaY = -(xbox360[0].rightStickY + 0.25) * 2 if starting: freeTrack.update += update
Прошу прощения сразу код делался простым копипастом, из обрывков кода на форумах, необходимо добавить комбинации клавиш (лечение. ремонт, выбор снарядов), поменять алгоритм работы стиков (более правильное поведение мыши), прокомментировать.
2. Так же можно явно указывать для какого геймпада какие команды (в квадратных скобках номер геймпада).
3. Проект бесплатен и довольно активно развивается.
4. Программа при запуске отъедает более 50 МБ, что не есть хорошо (тот же Xpadder кушает в 10 раз меньше).
5. Пока не понял каким образом сделать автоматический запуск, есть ссылки на консольную версию эмулятора, что может пригодиться.
Пока все выложил, что есть нового у меня.
Пробовал запустить "монстра" thinapp, две копии приложения не захотели запускаться. Возможно надо сделать отдельное "тонкое приложение" под другим именем. Из плюсов - прорисовка картинки никак не отличалась от локально запущенного клиента.
Пробовал запустить один клиент как обычно, второй в "песочнице", могу сказать что можно играть на моем ноутбуке (A4-4300M, 4 ГБ ОЗУ 1600 Mhz). Настройки в минимум, клиенты запущены в оконном режиме с разрешением 1024х768, обычный клиент 15-25 fps, "песочный" 10-20 fps. Думаю что на домашнем A10-5700, 8 ГБ ОЗУ 1866 Mhz с SSD и более быстрым WD Black будет веселее.
Таким образом, могу сказать, что проблема запуска двух клиентов для одновременной игры решена. Я как бы и сразу полагался на этот способ ;) В принципе и цена не такая пугающая - 15 евро, два месяца не донатить Wargaming.
- 1
- 1
-
Статья на хабре получила бы более теплый приём, если бы в ней было больше технической информации, например описание проблем, с которыми пришлось столкнуться при разработке, и их решения. А в статье ни слова об этом, и ссылки на тему с "хотелкой", где можно посмотреть процесс борьбы за работоспособность там тоже не нашлось. + даже ссылка на XVM устаревшая(только гугл.код, а среднестатистическому хабраюзеру XVM может быть и неизвестен). Так что проблема не в моде, а в подаче информации. Если исправить эти недочёты в будущем, всё будет хорошо =)
Удачи в работе над сплит-скрином, подпишусь на тему, буду поглядывать =)
"И опыт, сын ошибок трудных" - А.С.Пушкин ©
Как бы пост писался "сгоряча" - согласен, что моя ошибка. К тому же, уже потом, было выяснено очень много деталей, которые очень подогрели бы интерес - но запал прошел у меня. Думаю, что будет версия 2 :)
- 1
- 1
-
сорри за оффтоп, но представил себе это действо... чертовски весело же :-))
Кстати я давно в гости к знакомому хожу с ноутбуком, проводным геймпадом и HDMI-кабелечком. Причем я играю на его ТВ в гостиной, он же скрючивается за ПК в соседней комнате. Уже начинает привыкать играть на контроллере - начинаем меняться местами. Для таких "покатушек" и держу танчики 1-2 уровня.
- 1
- 1
-
Портативный клиент пробовали? Я, правда, не знаю, можно ли запустить 2 клиента одновременно.
Спасибо за ссылку! Гуглил на днях портативный клиент - на эту тему не попадал. Протестирую - отпишусь.
- 1
- 1
-
Доброе время суток, уважаемые форумчане!
"С восторгом предаюсь в руки
родной милициифорума, надеюсь нанеенего и уповаю." - Иван Васильевич Бунша ©В прошлом году мною было опубликована "хотелка", которая блестяще была решена с помощью inj3ct0r, sirmax и другими. Должен сказать, что данный мод был довольно холодно воспринят интернет-сообществом (публикация на habrahabr хоть и набрала более 10k просмотров, но в минусе), после обновления 0.8.11 и обновления системного python в игре, ко мне достаточно много человек постучалось с просьбой поделиться обновленным модом. С этой целью я написал на официальном форуме подробную инструкцию.
Таким образом хочу снова выразить огромную благодарность всем, кто участвовал в создании.
Теперь перейдем к новым "хотелкам".
На официальном форуме WoT в теме "корпоративная игра на 1м танке" меня посетила мысль об игровом режиме "Разделенный экран", т.е. одновременной игре вдвоем на одном экране во взводе/роте/команде. Разумеется ни о каком "нагибе", "подставных ротах" и прочем речь не идет, только "игра для фана" и "пыщь-пыщь" под пивасик с другом на геймпадах.
Теория была мною опробована на виртуальных ПК под VMWare Player:
Все заработало - геймпады пробросились в ВМ, картинку настроил в портретный режим, вибрации работают. Но неиграбельно - fps в среднем в каждой ВМ от 8 до 15.
Более детальное изучение всех составляющих для танков вдвоем на ТВ привело к следующему:
1. Настроить клиент игры для возможного запуска двух копий
2. Необходимо разделить экран телевизора на два виртуальных.
3. Решить проблему отправки нажатий кнопок/отклонения стиков с геймпада в неактивное окно.
4. Отправить вибрацию в разные геймпады с разных клиентов.1. Запуск 2-х клиентов.
По-умолчанию, разработчики из Wargaming убрали возможность одновременного запуска двух копий. Не буду описывать все прелести «песочницы» — Sandboxie Вам в помощь.2. Разделение экрана телевизора на две части.
«WoT» в оконном режиме может иметь минимальное разрешение 1024х768, в случае разделения FullHD телевизора пополам, необходимо разрешение каждого окна минимум 960х1080, а учитывая рамки окна и заголовок и того меньше. Т.е. стандартными «горячими клавишами» через Snap разнеся окна в разные стороны мы получаем частичное перекрытие окон. Любые другие утилиты для разделения рабочего стола на две части используют похожий функционал и никаким образом не могут повлиять на минимальное разрешения игры по ширине.
Перепробовав огромное количество, натолкнулся на Virtual Display Manager, подкупило отсутствие в названии слова desktop.
Утилита сделала нужное — добавив конфигурацию двух виртуальных дисплеев и перемещая окно в нужный — игра принимает нужное нам значение, а именно занимает ровно половину экрана.3. Отправка нажатий клавиш в неактивное окно.
Это решение было для моего ума самым сложным. Два клиента запущены, окна разнесены в стороны и не перекрывают друг-дружку, но одно из окон активно, соответственно принимает нажатия кнопок и перемещения мышки, а вот второе не активно со всеми вытекающими.К решению этой проблемы меня подтолкнуло знакомство с AutoHotkey.
'Первый скрипт, позволяющий даже иногда ездить в бою'
#InstallKeybdHook w:: WinGet, wot, PID, WoT Client ControlSend,, {sc11 Down}, ahk_pid %wot% KeyWait, w ControlSend,, {sc11 Up}, ahk_pid %wot% Return a:: WinGet, wot, PID, WoT Client ControlSend,, {sc1E Down}, ahk_pid %wot% KeyWait, a ControlSend,, {sc1E Up}, ahk_pid %wot% Return s:: WinGet, wot, PID, WoT Client ControlSend,, {sc1F Down}, ahk_pid %wot% KeyWait, s ControlSend,, {sc1F Up}, ahk_pid %wot% Return d:: WinGet, wot, PID, WoT Client ControlSend,, {sc20 Down}, ahk_pid %wot% KeyWait, d ControlSend,, {sc20 Up}, ahk_pid %wot% Return
Причины, почему скрипт срабатывал, мне так и остались неизвестны.
После многих безуспешных попыток, решение нашлось. Через SendMessage сообщать окну, что оно активно и отправлять нажатия клавиш. Такой своеобразный обман.
'Скрипт отправляет стрелки, WASD и пробел (переназначеный на выстрел в игре) в неактивное окно'
#SingleInstance #InstallKeybdHook SetControlDelay -1 vk49:: SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk57 Down}, WoT Client KeyWait, vk49 ControlSend,, {vk57 Up}, WoT Client Return vk4A:: SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk41 Down}, WoT Client KeyWait, vk4A ControlSend,, {vk41 Up}, WoT Client Return vk4B:: SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk53 Down}, WoT Client KeyWait, vk4B ControlSend,, {vk53 Up}, WoT Client Return vk4C:: SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk44 Down}, WoT Client KeyWait, vk4C ControlSend,, {vk44 Up}, WoT Client Return numpadup:: SendMessage, 0x06, 1,,, WoT Client ControlSend,, {up Down}, WoT Client KeyWait, numpadup ControlSend,, {up Up}, WoT Client Return numpaddown:: SendMessage, 0x06, 1,,, WoT Client ControlSend,, {down Down}, WoT Client KeyWait, numpaddown ControlSend,, {down Up}, WoT Client Return numpadleft:: SendMessage, 0x06, 1,,, WoT Client ControlSend,, {left Down}, WoT Client KeyWait, numpadleft ControlSend,, {left Up}, WoT Client Return numpadright:: SendMessage, 0x06, 1,,, WoT Client ControlSend,, {right Down}, WoT Client KeyWait, numpadright ControlSend,, {right Up}, WoT Client Return NumpadEnter:: SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk20 Down}, WoT Client KeyWait, NumpadEnter ControlSend,, {vk20 Up}, WoT Client Return
Дальше пошло веселее, особенно хочу выразить благодарность Серому форуму, и отдельно модератору teadrinker. Спасибо!!!
'WoT Split Screen'
#Persistent JoyMultiplier = 5 JoyThreshold = 5 JoyThresholdUpper := 50 + JoyThreshold JoyThresholdLower := 50 - JoyThreshold SetTimer, WatchAxisFirstJoyMoveForwardAndZoom, 10 SetTimer, WatchAxisFirstJoyMoveRotate, 10 SetTimer, WatchAxisFirstJoyCameraRotateVert, 10 SetTimer, WatchAxisFirstJoyCameraRotateHoriz, 10 SetTimer, WatchAxisFirstJoyShoot, 10 SetTimer, WatchFirstJoyPOV, 10 SetTimer, WatchAxisSecondJoyMoveForwardAndZoom, 10 SetTimer, WatchAxisSecondJoyMoveRotate, 10 SetTimer, WatchAxisSecondJoyCameraRotate, 10 SetTimer, WatchAxisSecondJoyShoot, 10 SetTimer, WatchSecondJoyPOV, 10 return ;;;;;;;;;;;;SplitScreen LWIN & LButton:: { WinWait, WoT Client WinSet, Style, -0xC40000 WinMove, WoT Client,,960 ,0 ,960 ,1080 WinWait, [#] WoT Client [#] WinSet, Style, -0xC40000 WinMove, [#] WoT Client [#],,0 ,0 , 960 ,1080 } return ;;;;;;;;;;;;первый геймпад движение вперед/назад в неактивном окне и зум WatchAxisFirstJoyMoveForwardAndZoom: GetKeyState, 1JoyY, 1JoyY GetKeyState, 1JoyZ, 1JoyZ GetKeyState, 1Joy2, 1Joy2 GetKeyState, 1Joy3, 1Joy3 FirstJoyMoveForwardAndZoomPrev = %FirstJoyMoveForwardAndZoom% if 1Joy2 = D GoSub, FirstJoyConsumables else if 1Joy3 = D GoSub, FirstJoyConsumables else { if 1JoyZ > 70 { if 1JoyY < 30 FirstJoyMoveForwardAndZoom = PgDn else if 1JoyY > 70 FirstJoyMoveForwardAndZoom = PgUp else FirstJoyMoveForwardAndZoom = } else if 1JoyY < 30 FirstJoyMoveForwardAndZoom = vk57 else if 1JoyY > 70 FirstJoyMoveForwardAndZoom = vk53 else FirstJoyMoveForwardAndZoom = } if FirstJoyMoveForwardAndZoom = %FirstJoyMoveForwardAndZoomPrev% return SetKeyDelay -1 if FirstJoyMoveForwardAndZoom { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyMoveForwardAndZoom% down}, WoT Client } } if FirstJoyMoveForwardAndZoomPrev { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyMoveForwardAndZoomPrev% up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад движение влево/вправо в неактивном окне WatchAxisFirstJoyMoveRotate: GetKeyState, 1JoyX, 1JoyX GetKeyState, 1Joy2, 1Joy2 GetKeyState, 1Joy3, 1Joy3 FirstJoyMoveRotatePrev = %FirstJoyMoveRotate% if 1Joy2 = D GoSub, FirstJoyConsumables else if 1Joy3 = D GoSub, FirstJoyConsumables else { if 1JoyX > 80 FirstJoyMoveRotate = vk44 else if 1JoyX < 20 FirstJoyMoveRotate = vk41 else FirstJoyMoveRotate = } if FirstJoyMoveRotate = %FirstJoyMoveRotatePrev% return SetKeyDelay -1 if FirstJoyMoveRotate { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyMoveRotate% down}, WoT Client } } if FirstJoyMoveRotatePrev { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyMoveRotatePrev% up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад меню расходников в неактивном окне FirstJoyConsumables: FirstJoyConsumablesPrev = %FirstJoyConsumables% if 1JoyX < 20 { if 1JoyY < 20 FirstJoyConsumables = vk38 else if 1JoyY between 40 and 60 FirstJoyConsumables = vk37 else if 1JoyY > 80 FirstJoyConsumables = vk36 else FirstJoyConsumables = } else if 1JoyX between 40 and 60 { if 1JoyY < 10 FirstJoyConsumables = vk31 else if 1JoyY > 90 FirstJoyConsumables = vk35 else FirstJoyConsumables = } else if 1JoyX > 80 { if 1JoyY < 20 FirstJoyConsumables = vk32 else if 1JoyY between 40 and 60 FirstJoyConsumables = vk33 else if 1JoyY > 80 FirstJoyConsumables = vk34 else FirstJoyConsumables = } else FirstJoyConsumables = if FirstJoyConsumables = %SFirstJoyConsumablesPrev% return SetKeyDelay -1 if FirstJoyConsumables { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyConsumables% down}, WoT Client } } if FirstJoyConsumablesPrev { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyConsumablesPrev% up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад обзор влево/вправо в неактивном окне WatchAxisFirstJoyCameraRotateVert: GetKeyState, 1JoyU, 1JoyU GetKeyState, 1Joy5, 1Joy5 FirstJoyCameraRotateVertPrev = %FirstJoyCameraRotateVert% if 1Joy5 = D GoSub, FirstJoyCommandMenu else { if 1JoyU > 70 FirstJoyCameraRotateVert = Right else if 1JoyU < 30 FirstJoyCameraRotateVert = Left else FirstJoyCameraRotateVert = } if FirstJoyCameraRotateVert = %FirstJoyCameraRotateVertPrev% return SetKeyDelay -1 if FirstJoyCameraRotateVert { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyCameraRotateVert% down}, WoT Client } } if FirstJoyCameraRotateVertPrev { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyCameraRotateVertPrev% up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад обзор вверх/вниз в неактивном окне WatchAxisFirstJoyCameraRotateHoriz: GetKeyState, 1JoyR, 1JoyR GetKeyState, 1Joy5, 1Joy5 FirstJoyCameraRotateHorizPrev = %FirstJoyCameraRotateHoriz% if 1Joy5 = D GoSub, FirstJoyCommandMenu else { if 1JoyR > 70 FirstJoyCameraRotateHoriz = Down else if 1JoyR < 30 FirstJoyCameraRotateHoriz = Up else FirstJoyCameraRotateHoriz = } if FirstJoyCameraRotateHoriz = %FirstJoyCameraRotateHorizPrev% return SetKeyDelay -1 if FirstJoyCameraRotateHoriz { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyCameraRotateHoriz% down}, WoT Client } } if FirstJoyCameraRotateHorizPrev { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyCameraRotateHorizPrev% up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад меню приказов FirstJoyCommandMenu: FirstJoyCommandMenuPrev = %FirstJoyCommandMenu% if 1JoyU < 20 { if 1JoyR < 20 FirstJoyCommandMenu = Numpad8 else if 1JoyR between 40 and 60 FirstJoyCommandMenu = Numpad7 else if 1JoyR > 80 FirstJoyCommandMenu = Numpad6 else FirstJoyCommandMenu = } else if 1JoyU between 40 and 60 { if 1JoyR < 10 FirstJoyCommandMenu = vk54 else if 1JoyR > 90 FirstJoyCommandMenu = Numpad5 else FirstJoyCommandMenu = } else if 1JoyU > 80 { if 1JoyR < 20 FirstJoyCommandMenu = Numpad2 else if 1JoyR between 40 and 60 FirstJoyCommandMenu = Numpad3 else if 1JoyR > 80 FirstJoyCommandMenu = Numpad4 else FirstJoyCommandMenu = } else FirstJoyCommandMenu = if FirstJoyCommandMenu = %FirstJoyCommandMenuPrev% return SetKeyDelay -1 if FirstJoyCommandMenu { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyCommandMenu% down}, WoT Client } } if FirstJoyCommandMenuPrev { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyCommandMenuPrev% up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад выстрел в неактивном окне WatchAxisFirstJoyShoot: GetKeyState, 1JoyZ, 1JoyZ FirstJoyShootPrev = %FirstJoyShoot% if 1JoyZ < 30 FirstJoyShoot = LButton else FirstJoyShoot = if FirstJoyShoot = %FirstJoyShootPrev% return SetKeyDelay -1 if FirstJoyShoot { IfWinNotActive, WoT Client { SendMessage, 0x201,,,, WoT Client } } if FirstJoyShootPrev { IfWinNotActive, WoT Client { SendMessage, 0x202,,,, WoT Client } } return ;;;;;;;;;;;;;первый геймпад крестовина в неактивном окне WatchFirstJoyPOV: GetKeyState, 1JoyPOV, 1JoyPOV FirstJoyPOVPrev = %FirstJoyPOV% if 1JoyPOV = 0 FirstJoyPOV = vk52 else if 1JoyPOV = 18000 FirstJoyPOV = vk46 else if 1JoyPOV = 27000 FirstJoyPOV = vk58 else if 1JoyPOV = 9000 FirstJoyPOV = vk43 else FirstJoyPOV = if FirstJoyPOV = %FirstJoyPOVPrev% return SetKeyDelay -1 if FirstJoyPOV { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyPOV% down}, WoT Client } } if FirstJoyPOVPrev { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {%FirstJoyPOVprev% up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад LShift в неактивном окне 1Joy10:: { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vkA0 Down}, WoT Client KeyWait, 1Joy10 ControlSend,, {vkA0 Up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад Space в неактивном окне 1Joy9:: { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk20 Down}, WoT Client KeyWait, 1Joy9 ControlSend,, {vk20 Up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад выбор снарядов в неактивном окне 1Joy1:: Gosub, FirstSubToggle Return FirstSubToggle: FirstToggle++ If FirstToggle = 1 { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk31 down}, WoT Client Sleep, 10 ControlSend,, {vk31 up}, WoT Client Sleep, 10 SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk31 down}, WoT Client Sleep, 10 ControlSend,, {vk31 up}, WoT Client } } If FirstToggle = 2 { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk32 down}, WoT Client Sleep, 10 ControlSend,, {vk32 up}, WoT Client Sleep, 10 SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk32 down}, WoT Client Sleep, 10 ControlSend,, {vk32 up}, WoT Client } } If FirstToggle = 3 { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk33 down}, WoT Client Sleep, 10 ControlSend,, {vk33 up}, WoT Client Sleep, 10 SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk33 down}, WoT Client Sleep, 10 ControlSend,, {vk33 up}, WoT Client } FirstToggle = 0 } return ;;;;;;;;;;;;первый геймпад огнетушитель в неактивном окне 1Joy4:: { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk35 Down}, WoT Client KeyWait, 1Joy4 ControlSend,, {vk35 Up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад автоприцел в неактивном окне 1Joy6:: { IfWinNotActive, WoT Client { SendMessage, 0x204, 1,,, WoT Client KeyWait, 1Joy6 SendMessage, 0x205, 1,,, WoT Client } } return ;;;;;;;;;;;;первый геймпад меню в неактивном окне 1Joy8:: { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk1B Down}, WoT Client KeyWait, 1Joy8 ControlSend,, {vk1B Up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад скрыть мини карту в неактивном окне 1Joy7:: { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk4D Down}, WoT Client KeyWait, 1Joy7 ControlSend,, {vk4D Up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад ремонт в неактивном окне 1Joy3:: { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk34 Down}, WoT Client KeyWait, 1Joy3 ControlSend,, {vk34 Up}, WoT Client } } return ;;;;;;;;;;;;первый геймпад лечение в неактивном окне 1Joy2:: { IfWinNotActive, WoT Client { SendMessage, 0x06, 1,,, WoT Client ControlSend,, {vk36 Down}, WoT Client KeyWait, 1Joy2 ControlSend,, {vk36 Up}, WoT Client } } return ;;;;;;;;;;;;второй геймпад ;;;;;;;;;;;;второй геймпад движение вперед/назад в активном окне и зум WatchAxisSecondJoyMoveForwardAndZoom: GetKeyState, 2JoyY, 2JoyY GetKeyState, 2JoyZ, 2JoyZ GetKeyState, 2Joy2, 2Joy2 GetKeyState, 2Joy3, 2Joy3 SecondJoyMoveForwardAndZoomPrev = %SecondJoyMoveForwardAndZoom% if 2Joy2 = D GoSub, SecondJoyConsumables else if 2Joy3 = D GoSub, SecondJoyConsumables else { if 2JoyZ > 70 { if 2JoyY < 30 SecondJoyMoveForwardAndZoom = PgDn else if 2JoyY > 70 SecondJoyMoveForwardAndZoom = PgUp else SecondJoyMoveForwardAndZoom = } else if 2JoyY < 30 SecondJoyMoveForwardAndZoom = vk57 else if 2JoyY > 70 SecondJoyMoveForwardAndZoom = vk53 else SecondJoyMoveForwardAndZoom = } if SecondJoyMoveForwardAndZoom = %SecondJoyMoveForwardAndZoomPrev% return SetKeyDelay -1 if SecondJoyMoveForwardAndZoom { ControlSend,, {%SecondJoyMoveForwardAndZoom% down}, [#] WoT Client [#] } if SecondJoyMoveForwardAndZoomPrev { ControlSend,, {%SecondJoyMoveForwardAndZoomPrev% up}, [#] WoT Client [#] } return ;;;;;;;;;;;;второй геймпад движение влево/вправо в активном окне WatchAxisSecondJoyMoveRotate: GetKeyState, 2JoyX, 2JoyX GetKeyState, 2Joy2, 2Joy2 GetKeyState, 2Joy3, 2Joy3 SecondJoyMoveRotatePrev = %SecondJoyMoveRotate% if 2Joy2 = D GoSub, SecondJoyConsumables else if 2Joy3 = D GoSub, SecondJoyConsumables else { if 2JoyX > 80 SecondJoyMoveRotate = vk44 else if 2JoyX < 20 SecondJoyMoveRotate = vk41 else SecondJoyMoveRotate = } if SecondJoyMoveRotate = %SecondJoyMoveRotatePrev% return SetKeyDelay -1 if SecondJoyMoveRotate { ControlSend,, {%SecondJoyMoveRotate% down}, [#] WoT Client [#] } if SecondJoyMoveRotatePrev { ControlSend,, {%SecondJoyMoveRotatePrev% up}, [#] WoT Client [#] } return ;;;;;;;;;;;;второй геймпад меню расходников SecondJoyConsumables: SecondJoyConsumablesPrev = %SecondJoyConsumables% if 2JoyX < 20 { if 2JoyY < 20 SecondJoyConsumables = vk38 else if 2JoyY between 40 and 60 SecondJoyConsumables = vk37 else if 2JoyY > 80 SecondJoyConsumables = vk36 else SecondJoyConsumables = } else if 2JoyX between 40 and 60 { if 2JoyY < 10 SecondJoyConsumables = vk31 else if 2JoyY > 90 SecondJoyConsumables = vk35 else SecondJoyConsumables = } else if 2JoyX > 80 { if 2JoyY < 20 SecondJoyConsumables = vk32 else if 2JoyY between 40 and 60 SecondJoyConsumables = vk33 else if 2JoyY > 80 SecondJoyConsumables = vk34 else SecondJoyConsumables = } else SecondJoyConsumables = if SecondJoyConsumables = %SecondJoyConsumablesPrev% return SetKeyDelay -1 if SecondJoyConsumables { ControlSend,, {%SecondJoyConsumables% down}, [#] WoT Client [#] } if SecondJoyConsumablesPrev { ControlSend,, {%SecondJoyConsumablesPrev% up}, [#] WoT Client [#] } return ;;;;;;;;;;;;второй геймпад обзор и мышь в активном окне WatchAxisSecondJoyCameraRotate: MouseNeedsToBeMoved := false SetFormat, float, 03 GetKeyState, 2JoyU, 2JoyU GetKeyState, 2JoyR, 2JoyR GetKeyState, 2Joy5, 2Joy5 if 2Joy5 = D GoSub, SecondJoyCommandMenu else if 2Joy5 = U { if 2JoyU > %JoyThresholdUpper% { MouseNeedsToBeMoved := true DeltaU := 2JoyU - JoyThresholdUpper } else if 2JoyU < %JoyThresholdLower% { MouseNeedsToBeMoved := true DeltaU := 2JoyU - JoyThresholdLower } else DeltaU = 0 if 2JoyR > %JoyThresholdUpper% { MouseNeedsToBeMoved := true DeltaR := 2JoyR - JoyThresholdUpper } else if 2JoyR < %JoyThresholdLower% { MouseNeedsToBeMoved := true DeltaR := 2JoyR - JoyThresholdLower } else DeltaR = 0 } SetKeyDelay -1 if MouseNeedsToBeMoved { SetMouseDelay, -1 ; Makes movement smoother x := (DeltaU/30) * (ABS(DeltaU)/30) * JoyMultiplier y := (DeltaR/30) * (ABS(DeltaR)/30) * JoyMultiplier DllCall("mouse_event", uint, 1, int, x, int, y, uint, 0, int, 0) } return ;;;;;;;;;;;;второй геймпад меню приказов SecondJoyCommandMenu: SecondJoyCommandMenuPrev = %SecondJoyCommandMenu% if 2JoyU < 20 { if 2JoyR < 20 SecondJoyCommandMenu = Numpad8 else if 2JoyR between 40 and 60 SecondJoyCommandMenu = Numpad7 else if 2JoyR > 80 SecondJoyCommandMenu = Numpad6 else SecondJoyCommandMenu = } else if 2JoyU between 40 and 60 { if 2JoyR < 10 SecondJoyCommandMenu = vk54 else if 2JoyR > 90 SecondJoyCommandMenu = Numpad5 else SecondJoyCommandMenu = } else if 2JoyU > 80 { if 2JoyR < 20 SecondJoyCommandMenu = Numpad2 else if 2JoyR between 40 and 60 SecondJoyCommandMenu = Numpad3 else if 2JoyR > 80 SecondJoyCommandMenu = Numpad4 else SecondJoyCommandMenu = } else SecondJoyCommandMenu = if SecondJoyCommandMenu = %SecondJoyCommandMenuPrev% return SetKeyDelay -1 if SecondJoyCommandMenu { ControlSend,, {%SecondJoyCommandMenu% down}, [#] WoT Client [#] } if SecondJoyCommandMenuPrev { ControlSend,, {%SecondJoyCommandMenuPrev% up}, [#] WoT Client [#] } return ;;;;;;;;;;;;второй геймпад выстрел в активном окне WatchAxisSecondJoyShoot: GetKeyState, 2JoyZ, 2JoyZ SecondJoyShootPrev = %SecondJoyShoot% if 2JoyZ < 30 SecondJoyShoot = LButton else SecondJoyShoot = if SecondJoyShoot = %SecondJoyShootPrev% return SetKeyDelay -1 if SecondJoyShoot { Send, {%SecondJoyShoot% down} } if SecondJoyShootPrev { Send, {%SecondJoyShootPrev% up} } return ;;;;;;;;;;;;;второй геймпад крестовина в активном окне WatchSecondJoyPOV: GetKeyState, 2JoyPOV, 2JoyPOV SecondJoyPOVPrev = %SecondJoyPOV% if 2JoyPOV = 0 SecondJoyPOV = vk52 else if 2JoyPOV = 18000 SecondJoyPOV = vk46 else if 2JoyPOV = 27000 SecondJoyPOV = vk58 else if 2JoyPOV = 9000 SecondJoyPOV = vk43 else SecondJoyPOV = if SecondJoyPOV = %SecondJoyPOVPrev% return SetKeyDelay -1 if SecondJoyPOV { ControlSend,, {%SecondJoyPOV% down}, [#] WoT Client [#] } if SecondJoyPOVPrev { ControlSend,, {%SecondJoyPOVprev% up}, [#] WoT Client [#] } return ;;;;;;;;;;;;второй геймпад LShift в активном окне 2Joy10:: { ControlSend,, {vkA0 Down}, [#] WoT Client [#] KeyWait, 2Joy10 ControlSend,, {vkA0 Up}, [#] WoT Client [#] } return ;;;;;;;;;;;;второй геймпад Space в активном окне 2Joy9:: { ControlSend,, {vk20 Down}, [#] WoT Client [#] KeyWait, 2Joy9 ControlSend,, {vk20 Up}, [#] WoT Client [#] } return ;;;;;;;;;;;;второй геймпад выбор снарядов в неактивном окне 2Joy1:: Gosub, SecondSubToggle Return SecondSubToggle: SecondToggle++ If SecondToggle = 1 { ControlSend,, {vk31 down}, [#] WoT Client [#] Sleep, 10 ControlSend,, {vk31 up}, [#] WoT Client [#] Sleep, 10 ControlSend,, {vk31 down}, [#] WoT Client [#] Sleep, 10 ControlSend,, {vk31 up}, [#] WoT Client [#] } If SecondToggle = 2 { ControlSend,, {vk32 down}, [#] WoT Client [#] Sleep, 10 ControlSend,, {vk32 up}, [#] WoT Client [#] Sleep, 10 ControlSend,, {vk32 down}, [#] WoT Client [#] Sleep, 10 ControlSend,, {vk32 up}, [#] WoT Client [#] } If SecondToggle = 3 { ControlSend,, {vk33 down}, [#] WoT Client [#] Sleep, 10 ControlSend,, {vk33 up}, [#] WoT Client [#] Sleep, 10 ControlSend,, {vk33 down}, [#] WoT Client [#] Sleep, 10 ControlSend,, {vk33 up}, [#] WoT Client [#] SecondToggle = 0 } return ;;;;;;;;;;;;второй геймпад огнетушитель в активном окне 2Joy4:: { ControlSend,, {vk35 Down}, [#] WoT Client [#] KeyWait, 2Joy4 ControlSend,, {vk35 Up}, W[#] WoT Client [#] } return ;;;;;;;;;;;;второй геймпад автоприцел в активном окне 2Joy6:: { Send, {RButton Down} KeyWait, 2Joy6 Send, {RButton up} } return ;;;;;;;;;;;;второй геймпад меню в неактивном окне 2Joy8:: { ControlSend,, {vk1B Down}, [#] WoT Client [#] KeyWait, 2Joy8 ControlSend,, {vk1B Up}, [#] WoT Client [#] } return ;;;;;;;;;;;;второй геймпад скрыть мини карту в активном окне 2Joy7:: { ControlSend,, {vk4D Down}, [#] WoT Client [#] KeyWait, 2Joy7 ControlSend,, {vk4D Up}, [#] WoT Client [#] } return ;;;;;;;;;;;;второй геймпад скрыть мини карту в активном окне 2Joy5:: { ControlSend,, {vk5A Down}, [#] WoT Client [#] KeyWait, 2Joy5 ControlSend,, {vk5A Up}, [#] WoT Client [#] } return ;;;;;;;;;;;;второй геймпад ремонт 2Joy3:: { ControlSend,, {vk34 Down}, [#] WoT Client [#] KeyWait, 2Joy3 ControlSend,, {vk34 Up}, [#] WoT Client [#] } return ;;;;;;;;;;;;второй геймпад лечение 2Joy2:: { ControlSend,, {vk36 Down}, [#] WoT Client [#] KeyWait, 2Joy2 ControlSend,, {vk36 Up}, [#] WoT Client [#] } return
Разумеется, играть перед ТВ никто не собирался на клавиатурах/мышах. Управление танками происходит с помощью двух геймпадов от Xbox360. За основу было выбрано управление от версии для Xbox 360.
В общем, у меня получилось как-то так.
Выбор типа снарядов переключением — один раз нажал — 1-й тип, второй — 2-й, третий — третий и сброс в начало (1-2-3). снаряды применяются сразу — AHK отдает двукратное нажатие в игру.
Меню приказов — сочетание левого бампера и правого стика, лечение и ремонт кнопки «Х» и «В» в сочетании с левым стиком.
Видео геймплея
4. Настройка вибраций для геймпадов.
Так как данная модификация игры использует веб-сервис для отправки вибраций, то для отправки во второй геймпад, нужно было просто изменить порт Flask.Но, для игры в «Разделенном экране» на вибрирующих геймпадах нужно запускать в «песочнице» полную копию клиента (скопировать папку рядом с другим именем) со своим отдельным модом, также скопировать в «песочницу» Python27.
Хочу отдельно выразить особую огромнейшую благодарность inj3ct0r, за всесторонние консультации и помощь, а так же всем участвовавшим! Спасибо Вам всем, без Вашей помощи, подсказок и поддержки у меня ничего не получилось бы.
Думается, что данное решение можно попробовать применить ко многим играм. Решение получилось очень неудобным — много всяких «но». Но могу сказать что игра для «фана» удалась. Удачи всем в боях!
Во вложении моды для основного/"песочного" клиентов и скрипт.
- 8
- 1
-
Доброе время суток, просмотрел код - у меня возник вопрос. Пытаюсь, по возможности, решить проблему подключения к игре сторонних девайсов (сам в python новичок). Хочется прицепить в WoT геймпад Xbox 360 без сторонних программ, типа xpadder и т.п. Чтобы команды напрямую принимались игрой как бы от клавиатуры/мыши. В коде уважаемого cep62rus, вроде есть нужное направление. Если я правильно понимаю, то игра может принимать команды, но они не назначены, соответственно бесполезны. Есть идеи?
-
А к картохе в саппорт не писал?
Вибрация не вибронакидки, вибрация для геймпада - пошлют они меня "за картошкой".
Насколько я понимаю, они поменяли какой-то метод, но понять что именно пока умишком слаб.
Вот код из версии 0.8.09
def update(self, vehicle, isLeftTrackBroken, isRightTrackBroken): if not VibroManager.g_instance.canWork(): return self.__deathVibrationCtrl.update(vehicle.isAlive()) self.__updateEngine(vehicle) if vehicle.isAlive(): self.__trackBreakingVibrationCtrl.update(vehicle, isLeftTrackBroken, isRightTrackBroken) else: self.__fireVibrationCtrl.switch(False) VibroManager.g_instance.update()
-
После обновления 0.8.11 при использовании "вибромода", стали сыпаться ошибки:
'python.log'
[EXCEPTION] (scripts/client/VehicleAppearance.py, 1098):
Traceback (most recent call last):
File "scripts/client/VehicleAppearance.py", line 1096, in __onPeriodicTimer
File "scripts/client/VehicleAppearance.py", line 1405, in __updateVibrations
File "scripts/client/Vibroeffects/ControllersManager.py", line 41, in update
File "scripts/client/Vibroeffects/Controllers/TrackBreakingController.py", line 94, in update
File "scripts/client/Vibroeffects/Controllers/TrackBreakingController.py", line 35, in __breakWithDirection
AttributeError: 'BigWorld.HomingCamera' object has no attribute 'source'Декомпилировав игровые скрипты - выкладываю код.
'VehicleAppearance'
def __onPeriodicTimer(self): self.__periodicTimerID = None try: self.__update Vibrations() except Exception: LOG_CURRENT_EXCEPTION() try: if self.__lightFxCtrl is not None: self.__lightFxCtrl.update(self.__vehicle) if self.__auxiliaryFxCtrl is not None: self.__auxiliaryFxCtrl.update(self.__vehicle) self.__updateWaterStatus() except: LOG_CURRENT_EXCEPTION() if not self.__vehicle.isAlive(): self.__periodicTimerID = BigWorld.callback(_PERIODIC_TIME, self.__onPeriodicTimer) return else: try: self.__distanceFromPlayer = (BigWorld.camera().position - self.__vehicle.position).length for extraData in self.__vehicle.extras.values(): extra = extraData.get('extra', None) if isinstance(extra, vehicle_extras.Fire): extra.checkUnderwater(extraData, self.__vehicle, self.isUnderwater) break self.__updateCurrTerrainMatKinds() self.__updateMovementSounds() self.__updateBlockedMovement() self.__updateEffectsLOD() self.__trailEffects.update() except: LOG_CURRENT_EXCEPTION() self.__periodicTimerID = BigWorld.callback(_PERIODIC_TIME, self.__onPeriodicTimer) return
'VehicleAppearance'
def __updateVibrations(self): if self.__vibrationsCtrl is None: return else: vehicle = self.__vehicle crashedTrackCtrl = self.__crashedTracksCtrl self.__vibrationsCtrl.update(vehicle, crashedTrackCtrl.isLeftTrackBroken(), crashedTrackCtrl.isRightTrackBroken()) return
'ControllersManager'
def update(self, vehicle, isLeftTrackBroken, isRightTrackBroken): if self._TrackBreakingController__wasLeftTrackBroken == False and isLeftTrackBroken: self._TrackBreakingController__breakWithDirection(vehicle, True) elif self._TrackBreakingController__wasRightTrackBroken == False and isRightTrackBroken: self._TrackBreakingController__breakWithDirection(vehicle, False) self._TrackBreakingController__wasLeftTrackBroken = isLeftTrackBroken self._TrackBreakingController__wasRightTrackBroken = isRightTrackBroken
'TrackBreakingController'
def _TrackBreakingController__breakWithDirection(self, vehicle, isLeftTrackBroken): directionMatrix = Math.Matrix(BigWorld.camera().source) directionMatrix.setElement(3, 0, 0) directionMatrix.setElement(3, 1, 0) directionMatrix.setElement(3, 2, 0) cameraDirection = directionMatrix.applyToAxis(0) cameraDirection.y = 0 vehicleMatrix = Math.Matrix(vehicle.matrix) vehicleMatrix.setElement(3, 0, 0) vehicleMatrix.setElement(3, 1, 0) vehicleMatrix.setElement(3, 2, 0) vehicleMatrix.invert() cameraDirection = vehicleMatrix.applyVector(cameraDirection) brokenTrackAngle = 0 if isLeftTrackBroken: brokenTrackAngle = math.pi dirAngleRelative = math.atan2(cameraDirection.z, cameraDirection.x) minDirDelta = math.pi * 2 vibrationToPlay = '' for angleVibration in TrackBreakingController._TrackBreakingController__ANGLES_VIBRATIONS: curAngle = angleVibration[0] curAngle += dirAngleRelative if curAngle > math.pi * 2: curAngle -= math.pi * 2 if curAngle < 0: curAngle += math.pi * 2 curDirDelta = abs(curAngle - brokenTrackAngle) if curDirDelta > math.pi: curDirDelta = math.pi * 2 - curDirDelta if curDirDelta < minDirDelta: minDirDelta = curDirDelta vibrationToPlay = angleVibration[1] continue OnceController(vibrationToPlay)
'TrackBreakingController'
def update(self, vehicle, isLeftTrackBroken, isRightTrackBroken): if self._TrackBreakingController__wasLeftTrackBroken == False and isLeftTrackBroken: self._TrackBreakingController__breakWithDirection(vehicle, True) elif self._TrackBreakingController__wasRightTrackBroken == False and isRightTrackBroken: self._TrackBreakingController__breakWithDirection(vehicle, False) self._TrackBreakingController__wasLeftTrackBroken = isLeftTrackBroken self._TrackBreakingController__wasRightTrackBroken = isRightTrackBroken
Ошибки на вибрацию в игре никак не влияют, но мое мнение что это не есть хорошо. Может кто-то из форума откликнется и укажет нубу в python как и что сделать для правильной работы "вибромода".
-
Вряд ли я кому-то открою глаза, но существуют специальные вибронакидки для игры в WoT, которые официально поддерживаются разработчиками. Соответственно, под эти вибронакидки есть уже готовый модуль в игре для передачи обратной связи.
Покопав тему глубже, нашел следующие вводные данные:
На сайте производителей "виброжопки" есть SDK, т.е. очень просто понять что, как и почему работает.
Там же есть и стандартные, и усиленные эффекты для WoT, открывая которые обычным тестовым редактором понятно, как именно сделаны виброэффекты.
Полазив в папках самой WoT нашел папку с скриптами, написанными на Python, которые относятся именно к вибронакидке "X:\Games\World_of_Tanks\res\scripts\client\vibroeffects".
В интернетах нашелся нужный код. Из редактора IDLE все работает - то есть запуская этот скрипт, геймпад действительно начинает вибрировать в зависимости от заданной скорости моторов. При этом отработка скрипта никак не влияла на работу Xpadder.
С помощью этого форума была "запилена" обратная вибросвязь для геймпада, ссылка. Выражаю огромнейшую благодарность sirmax, inj3ct0r,В итоге все получилось - данные для двигателей берутся из родных файлов для вибронакидки *.uwv, работает смешивание эффектов (одновременная вибрация, например пожар/выстрел/рикошет), работают "ползунки" в настройках игры для вибронакидки (можно увеличить вибрации/уменьшить/отключить).
Должен сказать, что играть стало намного интереснее и теперь не нужны многие вспомогательные картинки (руками чувствуется когда зарядилось орудие, когда по тебе попали и каким снарядом). Я кстати понял, почему разработчики хвалятся тем, что эффекты делал звукорежиссер (пожар только чего стоит - как биение сердца).
Для установки вибромода для геймпада нужно:
1. Необходимо установить Python версий 2.7.х (у меня стоит 2.7.6).
2. Необходимо установить Flask, я делал по этой инструкции. Качаем файл distribute_setup.py в папку "C:\temp" (например), запускаем консоль "Win+R" - cmd и выполняем командуC:\Python27\python.exe C:\temp\distribute_setup.py
наблюдаем процесс загрузки нужных файлов в папку "C:\Python27\Scripts", далее в консоли запускаем команды по очереди и наблюдаем их выполнение:
C:\Python27\python.exe C:\Python27\Scripts\easy_install-2.7-script.py Flask
C:\Python27\python.exe C:\Python27\Scripts\easy_install-2.7-script.py Jinja2
C:\Python27\python.exe C:\Python27\Scripts\easy_install-2.7-script.py Werkzeug
C:\Python27\python.exe C:\Python27\Scripts\easy_install-2.7-script.py Virtualenv
3. Распаковать мод в нужную папку.
4. Играть.Всем удачи в боях!
- 1
Нужна помощь по Python
in ActionScript & Python
Posted
Неужели ни у кого нет никаких идей?