kharlashkin 239 Posted August 21, 2014 (edited) Небольшое отступление сначала. После многократных попыток написания модов для WoT, я пришел к выводу что нифига у меня не получиться и переучиваться поздновато. Наверное лучше направлять время, проводимое в копании скриптов, в другое русло. Конечно опыт, полученный за все это время не лишний, но все таки я доверюсь людям которые в этом более "поднаторели" и "съели пару собак". Итак, мой главный партнер по "Разделенному экрану" вернулся домой после летних каникул от бабушки и опять насущны вопросы управления клиентом в неактивном окне. Самый острый из них - управление клавишами камерой в бою. Теми самыми стрелками, с заданным параметром ускорения, тут подробнее. Что мною сделано, расковырял много скриптов оригинальных, нашел отсылки на управление клавишами в скриптах control_modes.pyc и videocamera.pyc. Первый криво декомпилируется (обратная компиляция сыпет ошибки и бой не загружается), второй - не могу понять что там к чему (кстати его не проверял на ошибки). Мне видится два варианта реализации динамического управление камерой клавишами. Первый - менять коэффициент ускорения по нажатию дополнительных кнопок, но есть проблема разделения этого коэфициента по горизонтали и вертикали, т.е. нажимая например Num8 коэффициент для вертикали увеличивается до 2,5, нажимая Num2 уменьшается до 0,3, по аналогии нажимая Num4 уменьшение для горизонтали 0,3 и Num6 увеличение до 2,5. Второй - попробовать жестко задать клавиши, например Num8/Num6/Num4/Num2 (вверх/вправо/влево/вниз) с коэффициентом 2,5 и Num7/Num9/Num3/Num1 с коэффициентом 0,3. Каким образом отдавать это в игру через AutoHotkey - я уже сам осилю :) Что скажете, уважаемые? Edited August 21, 2014 by kharlashkin Share this post Link to post Short link Share on other sites
PinkElfant 25 #208787 Posted August 21, 2014 (edited) функции Win Api GetTickCount(время). А так поиск по smoth camera move time multiply/ также помню поднималась тема про камеру в dirt на forum.gamehacklab.ru Вообще какие функции нужны по пунктам, управление чем и чего кнопки на джойстике показать(изображение). Возможно напишу. Джойстик есть. Пишу на C++ Edited August 21, 2014 by nykaH_CTATucTA Share this post Link to post Short link Share on other sites
kharlashkin 239 #208790 Posted August 21, 2014 функции Win Api GetTickCount(время). А так поиск по smoth camera move time multiply/ также помню поднималась тема про камеру в dirt на forum.gamehacklab.ru Вообще какие функции нужны по пунктам, управление чем и чего кнопки на джойстике показать(изображение). Возможно напишу. Джойстик есть. Пишу на C++ "Не понятно..." Мы с Вами уже сталкивались, когда я пробовал сделать "Разделенный экран". Тогда Вы решили проблемы относительно отправки перемещений мыши в неактивное окно, но с танками это не работает - так как *.exe принимает перемещения мыши напрямую из драйвера, а не от Control окна, как paint. Сейчас в не активное окно "танчиков" я отправляю для перемещений камеры стрелки, но они имеют постоянную скорость перемещения камеры, скорость задается коэффициентом в файлике. Идея сделать или этот коэффициент динамическим в игре (по нажатию кнопок) или сразу задать нажатия на какие кнопки будет приниматься игрой как стрелки с нужным коэффициентом. Но теперь - чего мне хочется, со второго геймпада правый стик отдавать в неактивное окно танчиков как перемещения мыши, или набор стрелок с заданными коэфициентами. Я не совсем представляю как это организовать на более нзком уровне - подменять системный драйвер мыши для экземпляра танков в песочнице? Не сильно ли сложно? Share this post Link to post Short link Share on other sites
PinkElfant 25 #208795 Posted August 21, 2014 Если коэф в файле, то в память он подгружается, найти инструкцию что читает/редактирует/обращается и изменить ее 2 Share this post Link to post Short link Share on other sites
kharlashkin 239 #208796 Posted August 21, 2014 (edited) Если коэф в файле, то в память он подгружается, найти инструкцию что читает/редактирует/обращается и изменить ее Относительно перемещений мыши в игре, вот так работает в AutoHotkey: SetKeyDelay -1 if MouseNeedsToBeMoved { SetMouseDelay, -1 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 Ну вот что-то похожее на коэффициент игровой в python: class KeySensor: def __init__(self, keyMappings, sensitivity, sensitivityIncDecKeys = None, sensitivityAcceleration = None): self.keyMappings = keyMappings self.sensitivity = sensitivity self.__sensitivityKeys = {} if sensitivityIncDecKeys is not None: self.__sensitivityKeys[sensitivityIncDecKeys[0]] = sensitivityAcceleration self.__sensitivityKeys[sensitivityIncDecKeys[1]] = -sensitivityAcceleration self.currentVelocity = None self.__currentKeys = set() return def addVelocity(self, velocity): if self.currentVelocity is None: self.currentVelocity = velocity else: self.currentVelocity += velocity return def reset(self, defaultVelocity): self.__currentKeys.clear() self.currentVelocity = defaultVelocity def handleKeyEvent(self, key, isDown): for senseKey, acceleration in self.__sensitivityKeys.iteritems(): if senseKey == key: if isDown: self.__currentKeys.add(key) else: self.__currentKeys.discard(key) return True for mappingKey, shift in self.keyMappings.iteritems(): if mappingKey == key: if isDown: self.__currentKeys.add(key) else: self.__currentKeys.discard(key) return True return False def update(self, delta): for senseKey, acceleration in self.__sensitivityKeys.iteritems(): if senseKey in self.__currentKeys: self.sensitivity += acceleration * delta for mappingKey, shift in self.keyMappings.iteritems(): if mappingKey in self.__currentKeys: addValue = shift * self.sensitivity if self.currentVelocity is None: self.currentVelocity = addValue * self.sensitivity else: self.currentVelocity += addValue * self.sensitivity return Edited August 21, 2014 by kharlashkin Share this post Link to post Short link Share on other sites
yaotzinv 145 #208843 Posted August 21, 2014 (edited) держи мож поможет. \0.9.2\res\scripts\client\avatarinputhandler\dynamiccameras\arcadecamera.py \0.9.2\res\scripts\client\avatarinputhandler\dynamiccameras\snipercamera.py \0.9.2\res\scripts\client\avatarinputhandler\dynamiccameras\strategiccamera.py файлы.zip dynamiccameras.rar Edited August 21, 2014 by yaotzinv 2 Share this post Link to post Short link Share on other sites
kharlashkin 239 #208846 Posted August 21, 2014 (edited) держи мож поможет. \0.9.2\res\scripts\client\avatarinputhandler\dynamiccameras\arcadecamera.py \0.9.2\res\scripts\client\avatarinputhandler\dynamiccameras\snipercamera.py \0.9.2\res\scripts\client\avatarinputhandler\dynamiccameras\strategiccamera.py Ух ты блин, скомпилированный control_modes.py не повесил игру :) Как было до этого... Спасибо!!! Напиши, если не трудно, чем и как декомпилировал, какая версия python стоит и т.д. P.S. "УРАААА!!! Заработало!!!" (Кот Матроскин). Я с самого начала пробовал сделать что-то такое, но как оказалось подсовывая в оригинальные скрипты свои значения - у меня в логах сыпали ошибки и "В Бой!" не пускало. Итак, я заменил: if cmdMap.isFiredList((CommandMapping.CMD_CM_CAMERA_ROTATE_LEFT, CommandMapping.CMD_CM_CAMERA_ROTATE_RIGHT, CommandMapping.CMD_CM_CAMERA_ROTATE_UP, CommandMapping.CMD_CM_CAMERA_ROTATE_DOWN, CommandMapping.CMD_CM_INCREASE_ZOOM, CommandMapping.CMD_CM_DECREASE_ZOOM), key): dx = dy = dz = 0.0 if cmdMap.isActive(CommandMapping.CMD_CM_CAMERA_ROTATE_LEFT): dx = -0.1 if cmdMap.isActive(CommandMapping.CMD_CM_CAMERA_ROTATE_RIGHT): dx = 0.1 if cmdMap.isActive(CommandMapping.CMD_CM_CAMERA_ROTATE_UP): dy = -0.1 if cmdMap.isActive(CommandMapping.CMD_CM_CAMERA_ROTATE_DOWN): dy = 0.1 if cmdMap.isActive(CommandMapping.CMD_CM_INCREASE_ZOOM): dz = 1.0 if cmdMap.isActive(CommandMapping.CMD_CM_DECREASE_ZOOM): dz = -1.0 self.__cam.update(dx, dy, dz, True, True, False if dx == dy == dz == 0.0 else True) return True И камера, управляющаяся кнопками стала поворачиваться оочень медленно!!! Так же ставил значения dx = 5, dy = 5, тогда очень быстро начала крутиться. Блин, я на пол пути к написанию своего первого мода ;) Потому добавлять на нажатия кнопок методы я уже знаю ;) Edited August 21, 2014 by kharlashkin Share this post Link to post Short link Share on other sites
kharlashkin 239 #208917 Posted August 22, 2014 (edited) Просидел пол-ночи сегодня, что-от наваял - но кнопки делают как надо, но в аркадном режиме больше никакие не работают вообще. from AvatarInputHandler.control_modes import ArcadeControlMode import Keys from debug_utils import * orig_handleKeyEvent = ArcadeControlMode.handleKeyEvent def mod_handleKeyEvent(self, isDown, key, mods, event = None): orig_handleKeyEvent(self, isDown, key, mods, event = None) if isDown: dx = dy = dz = 0.0 if key == Keys.KEY_NUMPAD4: dx = -4.0 if key == Keys.KEY_NUMPAD6: dx = 4.0 if key == Keys.KEY_NUMPAD8: dy = -4.0 if key == Keys.KEY_NUMPAD2: dy = 4.0 self._ArcadeControlMode__cam.update(dx, dy, dz, True, True, False if dx == dy == dz == 0.0 else True) return True elif key == Keys.KEY_NUMPAD4 or Keys.KEY_NUMPAD6 or Keys.KEY_NUMPAD8 or Keys.KEY_NUMPAD2: self._ArcadeControlMode__cam.update(0, 0, 0, False) return True return False ArcadeControlMode.handleKeyEvent = mod_handleKeyEvent Ткните носом где посмотреть что-то... Edited August 22, 2014 by kharlashkin Share this post Link to post Short link Share on other sites
yaotzinv 145 #208924 Posted August 22, 2014 (edited) да типа в key приходят только определённые кнопки, если прописать в методе другие то оно не видит их нажатия. Я с таким сталкивался но не стал копать почему, надо смотреть кто этот метод вызывает и что там, как по мне. вообще не плохо бы найти метод в танках куда приходят все кнопки и переопределить его. искать так же, handleKeyEvent присутствует в большинстве файлов мира танков - думаю найдёте нужный. Edited August 22, 2014 by yaotzinv 1 Share this post Link to post Short link Share on other sites
kharlashkin 239 #208928 Posted August 22, 2014 да типа в key приходят только определённые кнопки, если прописать в методе другие то оно не видит их нажатия. Я с таким сталкивался но не стал копать почему, надо смотреть кто этот метод вызывает и что там, как по мне. вообще не плохо бы найти метод в танках куда приходят все кнопки и переопределить его. искать так же, handleKeyEvent присутствует в большинстве файлов мира танков - думаю найдёте нужный. Попробовал if BigWorld.isKeyDown(Keys.KEY_NUMPAD4) - так лучше работает, все сразу, но как сказать что клавиша отпущена? Share this post Link to post Short link Share on other sites
yaotzinv 145 #208929 Posted August 22, 2014 kharlashkin т.е. вместо этого if key == Keys.KEY_NUMPAD6: dx = 4.0 можно писать if BigWorld.isKeyDown(Keys.KEY_NUMPAD4) т.е. даже не смотреть на key ? получается. if not BigWorld.isKeyDown(keyCode): берет на прямую из BigWorld. выходит нажатия. предлагаю вынести всё в отдельный поток, там в бесконечном цикле отслеживать все BigWorld.isKeyDown(keyCode): и в зависимости от этого что то делать. Может ошибаюсь и можно как по другому или это решение ошибочно :) Share this post Link to post Short link Share on other sites
kharlashkin 239 #208937 Posted August 22, 2014 kharlashkin т.е. вместо этого if key == Keys.KEY_NUMPAD6: dx = 4.0 можно писать if BigWorld.isKeyDown(Keys.KEY_NUMPAD4) т.е. даже не смотреть на key ? получается. if not BigWorld.isKeyDown(keyCode): берет на прямую из BigWorld. выходит нажатия. предлагаю вынести всё в отдельный поток, там в бесконечном цикле отслеживать все BigWorld.isKeyDown(keyCode): и в зависимости от этого что то делать. Может ошибаюсь и можно как по другому или это решение ошибочно :) Ну логично, что нажатия отслеживает BigWorld. Надо порыскать - может есть BigWorld.isKeyUp(keyCode)... Share this post Link to post Short link Share on other sites
yaotzinv 145 #208938 Posted August 22, 2014 (edited) а зачем если BigWorld.isKeyDown(Keys.KEY_NUMPAD4) возвращает тру, значит если отпущена то вернёт фальш? я так думаю) not после ифа ставите оно инвертирует и пойдёт по условию - отпускания кнопки. Edited August 22, 2014 by yaotzinv 1 Share this post Link to post Short link Share on other sites
kharlashkin 239 #208940 Posted August 22, 2014 а зачем если BigWorld.isKeyDown(Keys.KEY_NUMPAD4) возвращает тру, значит если отпущена то вернёт фальш? я так думаю) not после ифа ставите оно инвертирует и пойдёт по условию - отпускания кнопки. Действительно, надо попробовать. Share this post Link to post Short link Share on other sites
kharlashkin 239 #208995 Posted August 22, 2014 Всю голову сломал уже, вот код: import BigWorld, Keys from AvatarInputHandler.control_modes import ArcadeControlMode from debug_utils import * orig_handleKeyEvent = ArcadeControlMode.handleKeyEvent def mod_handleKeyEvent(self, isDown, key, mods, event = None): orig_handleKeyEvent(self, isDown, key, mods, event = None) dx = dy = 0.0 if BigWorld.isKeyDown(Keys.KEY_NUMPAD4): dx = -4.0 if BigWorld.isKeyDown(Keys.KEY_NUMPAD6): dx = 4.0 if BigWorld.isKeyDown(Keys.KEY_NUMPAD8): dy = -4.0 if BigWorld.isKeyDown(Keys.KEY_NUMPAD2): dy = 4.0 self._ArcadeControlMode__cam.update(dx, dy, 0, True, True, False if dx == dy == 0.0 else True) return True if BigWorld.isKeyUp(Keys.KEY_NUMPAD4): dx = 0.0 if BigWorld.isKeyUp(Keys.KEY_NUMPAD6): dx = 0.0 if BigWorld.isKeyUp(Keys.KEY_NUMPAD8): dy = 0.0 if BigWorld.isKeyUp(Keys.KEY_NUMPAD2): dy = 0.0 self._ArcadeControlMode__cam.update(dx, dy, 0, True, True, False if dx == dy == 0.0 else True) return True ArcadeControlMode.handleKeyEvent = mod_handleKeyEvent Ошибок не сыпет, но никакие клавиши в бою не работают вообще кроме этих нумпадов... Share this post Link to post Short link Share on other sites
DrWebber 5 #208999 Posted August 22, 2014 (edited) orig_handleKeyEvent(self, isDown, key, mods, event) Edited August 22, 2014 by DrWebber 1 Share this post Link to post Short link Share on other sites
kharlashkin 239 #209002 Posted August 22, 2014 orig_handleKeyEvent(self, isDown, key, mods, event) Спасибо, конечно, но или я не понял что к чему или ошибка - потому как не сработало... Share this post Link to post Short link Share on other sites
yaotzinv 145 #209009 Posted August 22, 2014 (edited) return True что в середине делает? да и зачем установка 2 раза, один раз self._ArcadeControlMode__cam.update(dx, dy, 0, True, True, False if dx == dy == 0.0 else True) оно так работать не удет и кто сказал что этот метод вызывается при isKeyUp проверь или приходит туда в метод if BigWorld.isKeyUp(Keys.KEY_NUMPAD4): LOG_NOTE("KEY_NUMPAD4") т.е. даже нет проверь в оригинальном (ArcadeControlMode.handleKeyEvent) сначало вставь if BigWorld.isKeyUp(Keys.KEY_NUMPAD4): LOG_NOTE("KEY_NUMPAD4") и посмотри в питон логе потом. если туда не приходит тогда это уже другая песня. я имел ввиду что данный метод вызывается только при нажатии кнопки - т.е. вы ну ни как не проверете отпускание кнопки в этом методе если попросту этот метод не вызывается - при отпускании кнопки. Ну вы поняли. ------------------------------------------------------------ хотя нет оно будет проверять отпускание клавиши в этом методе но только после нажатия какой либо клавиши. if BigWorld.isKeyDown(Keys.KEY_NUMPAD4): dx = -4.0 if BigWorld.isKeyUp(Keys.KEY_NUMPAD4): dx = 0.0 Edited August 22, 2014 by yaotzinv 1 Share this post Link to post Short link Share on other sites
kharlashkin 239 #209030 Posted August 23, 2014 ------------------------------------------------------------ хотя нет оно будет проверять отпускание клавиши в этом методе но только после нажатия какой либо клавиши. if BigWorld.isKeyDown(Keys.KEY_NUMPAD4): dx = -4.0 if BigWorld.isKeyUp(Keys.KEY_NUMPAD4): dx = 0.0 Так как в python совсем не силен, то иду методом проб и ошибок.... Примерно понимая что к чему. Код метода: 'control_modes.py' def handleKeyEvent(self, isDown, key, mods, event = None): assert self.__isEnabled cmdMap = CommandMapping.g_instance if self.__cam.handleKeyEvent(isDown, key, mods, event): return True if BigWorld.isKeyDown(Keys.KEY_CAPSLOCK) and constants.IS_DEVELOPMENT and isDown and key == Keys.KEY_F1: self.__aih.onControlModeChanged('debug', prevModeName='arcade', camMatrix=self.__cam.camera.matrix) return True if BigWorld.isKeyDown(Keys.KEY_CAPSLOCK) and constants.IS_DEVELOPMENT and isDown and key == Keys.KEY_F2: self.__aih.onControlModeChanged('cat', camMatrix=self.__cam.camera.matrix) return True if BigWorld.isKeyDown(Keys.KEY_CAPSLOCK) and isDown and key == Keys.KEY_F3 and BattleReplay.g_replayCtrl.isPlaying and self.__videoControlModeAvailable: self.__aih.onControlModeChanged('video', prevModeName='arcade', camMatrix=self.__cam.camera.matrix) return True isFiredFreeCamera = cmdMap.isFired(CommandMapping.CMD_CM_FREE_CAMERA, key) isFiredLockTarget = cmdMap.isFired(CommandMapping.CMD_CM_LOCK_TARGET, key) and isDown if isFiredFreeCamera or isFiredLockTarget: if isFiredFreeCamera: self.setAimingMode(isDown, AIMING_MODE.USER_DISABLED) if isFiredLockTarget: BigWorld.player().autoAim(BigWorld.target()) if cmdMap.isFired(CommandMapping.CMD_CM_SHOOT, key) and isDown: BigWorld.player().shoot() return True if cmdMap.isFired(CommandMapping.CMD_CM_LOCK_TARGET_OFF, key) and isDown: BigWorld.player().autoAim(None) return True if cmdMap.isFired(CommandMapping.CMD_CM_VEHICLE_SWITCH_AUTOROTATION, key) and isDown: self.__aih.switchAutorotation() return True if cmdMap.isFiredList((CommandMapping.CMD_CM_CAMERA_ROTATE_LEFT, CommandMapping.CMD_CM_CAMERA_ROTATE_RIGHT, CommandMapping.CMD_CM_CAMERA_ROTATE_UP, CommandMapping.CMD_CM_CAMERA_ROTATE_DOWN, CommandMapping.CMD_CM_INCREASE_ZOOM, CommandMapping.CMD_CM_DECREASE_ZOOM), key): dx = dy = dz = 0.0 if cmdMap.isActive(CommandMapping.CMD_CM_CAMERA_ROTATE_LEFT): dx = -1.0 if cmdMap.isActive(CommandMapping.CMD_CM_CAMERA_ROTATE_RIGHT): dx = 1.0 if cmdMap.isActive(CommandMapping.CMD_CM_CAMERA_ROTATE_UP): dy = -1.0 if cmdMap.isActive(CommandMapping.CMD_CM_CAMERA_ROTATE_DOWN): dy = 1.0 if cmdMap.isActive(CommandMapping.CMD_CM_INCREASE_ZOOM): dz = 1.0 if cmdMap.isActive(CommandMapping.CMD_CM_DECREASE_ZOOM): dz = -1.0 self.__cam.update(dx, dy, dz, True, True, False if dx == dy == dz == 0.0 else True) return True if cmdMap.isFired(CommandMapping.CMD_CM_ALTERNATE_MODE, key) and isDown: self.__activateAlternateMode() return True if cmdMap.isFired(CommandMapping.CMD_CM_CAMERA_RESTORE_DEFAULT, key) and isDown: self.__cam.restoreDefaultsState() return True return False Ну Вы мне его и дали - код этот. Перепробовав много вариантов остановился пока на том что выше - потому как он ближе всего в реализации. Но отваливаются все остальные клавиши - кроме мыши. ХЗ почему. Попробую вставить этот код напрямую в оригинальные скрипты - посмотрим. Share this post Link to post Short link Share on other sites
DrWebber 5 #209054 Posted August 23, 2014 (edited) Во-первых, нужно сохранять результат хукаемой функции, а потом после выполнения своих действий возвращать его. def mod_handleKeyEvent(self, isDown, key, mods, event = None): retVal = orig_handleKeyEvent(self, isDown, key, mods, event) ..... ..... return retVal Во-вторых, зачем тебе BigWorld.isKeyDown и BigWorld.isKeyUp, если у тебя в handleKeyEvent передается key и isDown: if isDown: if key == Keys.KEY_NUMPAD4: .... else: if key == Keys.KEY_NUMPAD4: .... Edited August 23, 2014 by DrWebber 1 Share this post Link to post Short link Share on other sites