Jump to content
Korean Random
kharlashkin

[Заказ] Модернизация управления камерой

Recommended Posts

Небольшое отступление сначала.

После многократных попыток написания модов для 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 by kharlashkin

Share this post


Link to post

Short link
Share on other sites

функции Win Api GetTickCount(время). А так поиск по smoth camera move time multiply/ также помню поднималась тема про камеру в dirt на forum.gamehacklab.ru

Вообще какие функции нужны по пунктам, управление чем и чего кнопки на джойстике показать(изображение). Возможно напишу. Джойстик есть. Пишу на C++

Edited by nykaH_CTATucTA

Share this post


Link to post

Short link
Share on other sites

функции 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

Если коэф в файле, то в память он подгружается, найти инструкцию что читает/редактирует/обращается и изменить ее

  • Upvote 2

Share this post


Link to post

Short link
Share on other sites

Если коэф в файле, то в память он подгружается, найти инструкцию что читает/редактирует/обращается и изменить ее

Относительно перемещений мыши в игре, вот так работает в 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 by kharlashkin

Share this post


Link to post

Short link
Share on other sites

держи мож поможет.


\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 by yaotzinv
  • Upvote 2

Share this post


Link to post

Short link
Share on other sites

держи мож поможет.

\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 by kharlashkin

Share this post


Link to post

Short link
Share on other sites

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

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 by kharlashkin

Share this post


Link to post

Short link
Share on other sites

да типа в key приходят только определённые кнопки, если прописать в методе другие то оно не видит их нажатия. Я с таким сталкивался но не стал копать почему, надо смотреть кто этот метод вызывает и что там, как по мне.


вообще не плохо бы найти метод в танках куда приходят все кнопки и переопределить его.

 

искать так же, handleKeyEvent присутствует в большинстве файлов мира танков - думаю найдёте нужный.

Edited by yaotzinv
  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

да типа в key приходят только определённые кнопки, если прописать в методе другие то оно не видит их нажатия. Я с таким сталкивался но не стал копать почему, надо смотреть кто этот метод вызывает и что там, как по мне.

вообще не плохо бы найти метод в танках куда приходят все кнопки и переопределить его.

 

искать так же, handleKeyEvent присутствует в большинстве файлов мира танков - думаю найдёте нужный.

Попробовал if BigWorld.isKeyDown(Keys.KEY_NUMPAD4) - так лучше работает, все сразу, но как сказать что клавиша отпущена?

Share this post


Link to post

Short link
Share on other sites

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

т.е. вместо этого

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

а зачем

если BigWorld.isKeyDown(Keys.KEY_NUMPAD4)  возвращает тру, значит если отпущена то вернёт фальш? я так думаю)

not после ифа ставите оно инвертирует и пойдёт по условию - отпускания кнопки.

Edited by yaotzinv
  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

а зачем

если BigWorld.isKeyDown(Keys.KEY_NUMPAD4)  возвращает тру, значит если отпущена то вернёт фальш? я так думаю)

not после ифа ставите оно инвертирует и пойдёт по условию - отпускания кнопки.

Действительно, надо попробовать.

Share this post


Link to post

Short link
Share on other sites

Всю голову сломал уже, вот код:

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
orig_handleKeyEvent(self, isDown, key, mods, event)

Спасибо, конечно, но или я не понял что к чему или ошибка - потому как не сработало...

Share this post


Link to post

Short link
Share on other sites

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 by yaotzinv
  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

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

 

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

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

Во-первых, нужно сохранять результат хукаемой функции, а потом после выполнения своих действий возвращать его.

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 by DrWebber
  • Upvote 1

Share this post


Link to post

Short link
Share on other sites
Guest
This topic is now closed to further replies.

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...