Багато з нас проводили вечори перед теплим ламповим телевізором з друзями, граючи на приставках. Завжди особливо приємно було грати одночасно вдвох, не чекаючи своєї черги.
Ностальгія.
На жаль, в даний час багато розробників ігор не додають подібного режиму - нові ігри зі 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
Загалом, у мене вийшло якось так.
