Режим «Розділений екран» або Split Screen своїми руками

Багато з нас проводили вечори перед теплим ламповим телевізором з друзями, граючи на приставках. Завжди особливо приємно було грати одночасно вдвох, не чекаючи своєї черги.

Ностальгія.

На жаль, в даний час багато розробників ігор не додають подібного режиму - нові ігри зі splitscreen можна перерахувати мало не на пальцях однієї руки. В один весняний вечір прийшла ідея в голову спробувати обійти обмеження, що накладається розробниками, і зробити ігровий режим з поділом екрану більш доступним.

В якості піддослідного кролика гри мною була обрана «World of Tanks» з кількох причин:

1. Можливість грати удвох, даний режим називається "Взвод" ".

2. Гра на мінімальних налаштуваннях достатня не вимоглива - будь-який середній за продуктивністю ПК повинен тягнути 2 копії.

3. Геймплей танків досить невигадливий, хоча розробниками і позиціонується як «масова багатокористувацька онлайн-гра в жанрі action з елементами рольової гри, шутера і стратегії» (Wikipedia). Але як на мене - аркада для пыщь-пыщь.

4. Напевно, найголовніша причина - я, по кілька годин на тиждень, і мій молодший син любимо постріляти. Зі старшим ми іноді бігаємо в Portal2, там режим розділеного екрану для ТБ є.

Ці хлопці сподіваюся багатьом знайомі;)

Більш детальне вивчення всіх складових для танків удвох на ТБ призвело до наступного:

1. Налаштувати клієнт гри для можливого запуску двох копій

2. Необхідно розділити екран телевізора на два віртуальних.

3. Вирішити проблему надсилання натискань кнопок/відхилення стіків з геймпада в неактивне вікно.

4. Відправити вібрацію в різні геймпади з різних клієнтів.

Детальніше про процес рішення.

1. Запуск 2-х клієнтів.

За замовчуванням, розробники з Wargaming прибрали можливість одночасного запуску двох копій. Не буду описувати всі принади «пісочниці» - Sandboxie Вам на допомогу.

2. Поділ екрану телевізора на дві частини.

«WoT» у віконному режимі може мати мінімальну роздільну здатність 1024х768, у разі поділу FullHD телевізора навпіл, необхідна роздільна здатність кожного вікна мінімум 960х1080, а враховуючи рамки вікна і заголовок і того менше. Тобто. стандартними «гарячими клавішами» через Snap рознісши вікна в різні боки ми отримуємо часткове перекриття вікон. Будь-які інші утиліти для поділу стільниці на дві частини використовують схожий функціонал і ніяким чином не можуть вплинути на мінімальну роздільну здатність гри за шириною.

Перепробувавши величезну кількість, наштовхнувся на Virtual Display Manager, підкупило відсутність у назві слова desktop.

Утиліта зробила потрібне - додавши конфігурацію двох віртуальних дисплеїв і переміщуючи вікно в потрібний - гра приймає потрібне нам значення, а саме займає рівно половину екрану. До речі треба перевірити поділ на більшу кількість.

3. Надсилання клавіш до неактивного вікна.

Це рішення було для мого розуму найскладнішим. Два клієнти запущені, вікна рознесені в сторони і не перекривають один-дружку, але одне з вікон активно, відповідно приймає натискання кнопок і переміщення мишки, а ось друге не активно з усіма витікаючими.

Роздільна здатність 1366х768.

До вирішення цієї проблеми мене підштовхнуло знайомство з AutoHotkey. Ось вже справді «AutoHotkey - це вільна утиліта під Windows з відкритими вихідними кодами і скриптова мова з величезними можливостями, в принципі навіть не вимагає установки». (посилання)

Перший скрипт, що дозволяє навіть іноді їздити в бою

#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

Далі пішло веселіше.

Прошу конструктивно критикувати код досконалості немає межі.

World_Of_Tanks_Split_screen

JoyMultiplier = 5

JoyThreshold = 5

JoyThresholdUpper := 50 + JoyThreshold

JoyThresholdLower := 50 — JoyThreshold

#Persistent

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

;;;;;;;;;;;; прибираємо загловок вікон

^!+s::

WinWait, WoT Client

WinSet, Style, -0xC00000

WinWait, [#] WoT Client [#]

WinSet, Style, -0xC00000

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, SecondJoyConsumables

else if 1Joy3 = D

GoSub, SecondJoyConsumables

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}, [#] 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.

Параметри керування Xbox 360

Загалом, у мене вийшло якось так.

Параметри керування PC