TV with friends, playing on consoles. It was always especially pleasant to play at the same time together, not waiting for their turn.
Nostalgia.
Unfortunately, nowadays many game developers do not add such a mode - new splitscreen games can be counted almost on the fingers of one hand. One spring evening, I got the idea to try to get around the limitation imposed by the developers and make the game mode with screen sharing more accessible.
1. The ability to play together, this mode is called "
".
2. Playing at minimum settings is not demanding enough - any average PC performance should pull 2 ​​copies.
3. The gameplay of tanks is fairly straightforward, although the developers are positioning themselves as “a massively multiplayer online game in the genre of action with elements of a role-playing game, shooter and strategy” (
). But as for me - an arcade
.
4. Probably the most basic reason - I, several hours a week, and my youngest son love to shoot. With the older we sometimes run to Portal2, there is a split screen mode for TV.
A more detailed study of all the components for tanks together on TV led to the following:
1. Configure the game client to launch two copies
2. It is necessary to divide the TV screen into two virtual ones.
3. Solve the problem of sending keystrokes / deflecting sticks from a gamepad to an inactive window.
4. Send
to different gamepads from different clients.
1. Run 2 clients.
By default, the developers of Wargaming have removed the ability to simultaneously run two copies. I will not describe all the delights of the "sandbox" -
to help you.
2. The division of the TV screen into two parts.
“WoT” in windowed mode can have a minimum resolution of 1024x768, in the case of dividing FullHD TV in half, the resolution of each window must be at least 960x1080, and taking into account the window frames and the title and even less. Those. using standard “hot keys” through
splitting the windows in different directions, we get a partial overlap of the windows. Any other utilities to split the desktop into two parts use similar functionality and in no way can affect the minimum resolution of the game in width.
, bribed the lack of the word desktop in the title.
The utility did the right thing - by adding the configuration of two virtual displays and moving the window to the right one - the game takes the value we need, namely, it takes exactly half of the screen.
3. Send keystrokes to an inactive window.
. Two clients are running, the windows are spaced apart and do not overlap each other, but one of the windows is active, respectively, accepts button presses and mouse movements, but the second is not active with all the consequences.
The resolution is 1366x768.
. Truly, “AutoHotkey is a free open source Windows-based utility and a scripting language with great features, in principle, not even requiring installation.” (
The reasons why the script worked, I still remain unknown.
After many unsuccessful attempts, the solution was found. Via SendMessage, inform the window that it is active and send keystrokes. Such a kind of deception.
The script sends arrows, WASD and space (reassigned to a shot in the game) in an inactive window.#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
Then it went more fun.
.
World_Of_Tanks_Split_screenJoyMultiplier = 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
;;;;;;;;;;;; remove windows header
^! + s ::
WinWait, WoT Client
WinSet, Style, -0xC00000
WinWait, [#] WoT Client [#]
WinSet, Style, -0xC00000
return
;;;;;;;;;;;; first gamepad forward / backward in an inactive window and zoom
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
;;;;;;;;;;;; first gamepad movement left / right in an inactive window
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
;;;;;;;;;;;; the first gamepad menu consumables in an inactive window
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
;;;;;;;;;;;; first gamepad review left / right in an inactive window
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
;;;;;;;;;;;; first gamepad review up / down in an inactive window
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
;;;;;;;;;;;; first gamepad menu orders
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
;;;;;;;;;;;; first gamepad shot in an inactive window
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
;;;;;;;;;;;;; first gamepad spider in an inactive window
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
;;;;;;;;;;;; first LShift gamepad in an inactive window
1Joy10 ::
{
IfWinNotActive, WoT Client
{
SendMessage, 0x06, 1 ,,, WoT Client
ControlSend ,, {vkA0 Down}, WoT Client
KeyWait, 1Joy10
ControlSend ,, {vkA0 Up}, WoT Client
}
}
return
;;;;;;;;;;;; Space's first gamepad in an inactive window
1Joy9 ::
{
IfWinNotActive, WoT Client
{
SendMessage, 0x06, 1 ,,, WoT Client
ControlSend ,, {vk20 Down}, WoT Client
KeyWait, 1Joy9
ControlSend ,, {vk20 Up}, WoT Client
}
}
return
;;;;;;;;;;;; first gamepad selection of shells in the inactive window
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
;;;;;;;;;;;; the first gamepad fire extinguisher in an inactive window
1Joy4 ::
{
IfWinNotActive, WoT Client
{
SendMessage, 0x06, 1 ,,, WoT Client
ControlSend ,, {vk35 Down}, WoT Client
KeyWait, 1Joy4
ControlSend ,, {vk35 Up}, WoT Client
}
}
return
;;;;;;;;;;;; the first gamepad auto-aim in an inactive window
1Joy6 ::
{
IfWinNotActive, WoT Client
{
SendMessage, 0x204, 1 ,,,, WoT Client
KeyWait, 1Joy6
SendMessage, 0x205, 1 ,,, WoT Client
}
}
return
;;;;;;;;;;;; first gamepad menu in an inactive window
1Joy8 ::
{
IfWinNotActive, WoT Client
{
SendMessage, 0x06, 1 ,,, WoT Client
ControlSend ,, {vk1B Down}, WoT Client
KeyWait, 1Joy8
ControlSend ,, {vk1B Up}, WoT Client
}
}
return
;;;;;;;;;;;; first gamepad hide mini map in inactive window
1Joy7 ::
{
IfWinNotActive, WoT Client
{
SendMessage, 0x06, 1 ,,, WoT Client
ControlSend ,, {vk4D Down}, WoT Client
KeyWait, 1Joy7
ControlSend ,, {vk4D Up}, WoT Client
}
}
return
;;;;;;;;;;;; first gamepad repair in an inactive window
1Joy3 ::
{
IfWinNotActive, WoT Client
{
SendMessage, 0x06, 1 ,,, WoT Client
ControlSend ,, {vk34 Down}, WoT Client
KeyWait, 1Joy3
ControlSend ,, {vk34 Up}, WoT Client
}
}
return
;;;;;;;;;;;; first gamepad treatment in an inactive window
1Joy2 ::
{
IfWinNotActive, WoT Client
{
SendMessage, 0x06, 1 ,,, WoT Client
ControlSend ,, {vk36 Down}, WoT Client
KeyWait, 1Joy2
ControlSend ,, {vk36 Up}, WoT Client
}
}
return
;;;;;;;;;;;; second gamepad
;;;;;;;;;;;; the second gamepad moves forward / backward in the active window and zoom
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
;;;;;;;;;;;; second gamepad movement left / right in the active window
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
;;;;;;;;;;;; second gamepad menu consumables
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
;;;;;;;;;;;; second gamepad review and mouse in the active window
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
;;;;;;;;;;;; second gamepad menu orders
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
;;;;;;;;;;;; second gamepad shot in active window
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
;;;;;;;;;;;;; second gamepad spider in the active window
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
;;;;;;;;;;;; second LShift gamepad in the active window
2Joy10 ::
{
ControlSend ,, {vkA0 Down}, [#] WoT Client [#]
KeyWait, 2Joy10
ControlSend ,, {vkA0 Up}, [#] WoT Client [#]
}
return
;;;;;;;;;;;; the second gamepad Space in the active window
2Joy9 ::
{
ControlSend ,, {vk20 Down}, [#] WoT Client [#]
KeyWait, 2Joy9
ControlSend ,, {vk20 Up}, [#] WoT Client [#]
}
return
;;;;;;;;;;;; second gamepad selection of shells in the inactive window
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
;;;;;;;;;;;; second gamepad fire extinguisher in the active window
2Joy4 ::
{
ControlSend ,, {vk35 Down}, [#] WoT Client [#]
KeyWait, 2Joy4
ControlSend ,, {vk35 Up}, [#] WoT Client [#]
}
return
;;;;;;;;;;;; the second gamepad avtopritsel in the active window
2Joy6 ::
{
Send, {RButton Down}
KeyWait, 2Joy6
Send, {RButton up}
}
return
;;;;;;;;;;;; second gamepad menu in an inactive window
2Joy8 ::
{
ControlSend ,, {vk1B Down}, [#] WoT Client [#]
KeyWait, 2Joy8
ControlSend ,, {vk1B Up}, [#] WoT Client [#]
}
return
;;;;;;;;;;;; second gamepad hide mini map in active window
2Joy7 ::
{
ControlSend ,, {vk4D Down}, [#] WoT Client [#]
KeyWait, 2Joy7
ControlSend ,, {vk4D Up}, [#] WoT Client [#]
}
return
;;;;;;;;;;;; second gamepad hide mini map in active window
2Joy5 ::
{
ControlSend ,, {vk5A Down}, [#] WoT Client [#]
KeyWait, 2Joy5
ControlSend ,, {vk5A Up}, [#] WoT Client [#]
}
return
;;;;;;;;;;;; second gamepad repair
2Joy3 ::
{
ControlSend ,, {vk34 Down}, [#] WoT Client [#]
KeyWait, 2Joy3
ControlSend ,, {vk34 Up}, [#] WoT Client [#]
}
return
;;;;;;;;;;;; second gamepad treatment
2Joy2 ::
{
ControlSend ,, {vk36 Down}, [#] WoT Client [#]
KeyWait, 2Joy2
ControlSend ,, {vk36 Up}, [#] WoT Client [#]
}
return
Of course, no one was going to play in front of the TV on keyboards / mice. Management of tanks occurs with the help of two gamepads from the Xbox360. The basis was chosen from the management version for the Xbox 360.
In general, I did something like that.
The video was recorded with a draft script - when there was only control of the tank, turret, sniper mode and a space shot.
4. Adjustment of vibrations for gamepads.
I already wrote about adding vibrations to the game on a gamepad. Since this modification of the game uses a web service to send vibrations, in order to send to the second gamepad, you just had to change the Flask port.
But, to play in the "Split Screen" on vibrating gamepads, you need to run a full copy of the client in the sandbox (copy the folder next to another name) with its own mod, and also copy it into the sandbox Python27.
It seems that this solution can be tried to apply to many games. The solution turned out to be very inconvenient - there are a lot of “but”. But I can say that the game for the "fan" was a success. Good luck to everyone in the battles!
and separately inj3ct0r. Thank!!! And also to all those who advised, helped and supported me.
(menu orders, switching sniper mode and vibro) for the main and sand clients. Also in the archive is a script with a complete removal of the frame around the clients by pressing the WinL + LButton key combination.