STAR WARS™: X-Wing Alliance™

STAR WARS™: X-Wing Alliance™

Not enough ratings
Just another Joystick/Controller fix using e.g. your mouse as input
By Chaos "Fox" Overlord
Like many others, I had two problems playing X-Wing Alliance with and without TFTC:

1. no joystick, just a mouse
2. constant drifting to the left after I solved #1.

I solved the problem with a solution that is not limited to X-Wing Alliance or even gaming.
   
Award
Favorite
Favorited
Unfavorite
Install Prerequisites
Install
  1. vJoy [sourceforge.net] (alternatively here [github.com]) as virtual Joystick driver and
  2. FreePIE [andersmalmgren.github.io] as bridge between vJoy and your input device.
Configure vJoy
After installing vJoy, run "Configure vJoy" from your Start Menu or "C:\Program Files\vJoy\x64\vJoyConf.exe" directly. A Window similar as shown on screenshot should appear.
Be sure to choose tab "1", click "Add Device". This should lead to the virtual Joystick showing up.
I configured vJoy Device No. 1 as follows:


After configuring, click "Apply" (already grayed out in my screenshot, because I already clicked it when tacking the screenshot).

This will allow you to play games that require a joystick, but you won't have the ability to input anything since vJoy is just a virtual driver plus a programming interface. But problem #1 is basically solved.
Configure FreePIE
FreePIE is very useful when it comes to input or changing inputs.

Start FreePIE, select "File -> New" to open a new editor window.

FreePie understands Python, so you will need a Python script to manage your input and output.
For our use case, insert the script below. FreePIE is basically a text editor, thus copy and paste the script inside the editor window. It is based on a simple example code-snippet, which can be found here [gist.github.com]):

# X-Wing Alliance FreePIE / vJoy Script v1.4 # # based on a simple example code-snippet, which can be found here: # https://gist.github.com/jake-lewis/e89207690cbc777fa82e9ae248b683ab # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # Chaos "Fox" Overlord 2024 ###################### ### Initialization ### ###################### if starting: rmbKey = Key.X #Key bound to right mouse botton #Higher values = faster centering centreX = 0.015 centreY = 0.03 #Sensitivities sensX = 50 sensY = 50 sensZ = 10 viewSens = 50 #Timings system.setThreadTiming(TimingTypes.HighresSystemTimer) system.threadExecutionInterval = 20 #Initial values of axis / latches /etc. x = 0 y = 0 rx = 0 ry = 0 #For unknown reasons XWA max. Throttle is reached @ -15.933, # whilst abs(vJoy[0].axisMax) is 16382 (~ 2^15/2) for vJoy-Devices maxZ = 15933 #For reasons also unknown, only a deltaZ of >= 772 is recognized in XWA, # thus sufficient to reset the throttle to 100% after e.g. matching target velocity deltaZ = 772 z = -maxZ timeKeyPressed = 0 freelook = False viewLatch = False moveLatch = False rmbLatch = False ############################################################################# ### Freelook via Numpad mapped to mouse while middle mouse button pressed ### ############################################################################# if freelook: x = 0 y = 0 if timeKeyPressed <= 0: timeKeyPressed = viewSens #rx += mouse.deltaX * viewSens if mouse.deltaX > 0: keyboard.setKey(Key.NumberPad6, True) keyboard.setKey(Key.NumberPad6, False) if mouse.deltaX < 0: keyboard.setKey(Key.NumberPad4, True) keyboard.setKey(Key.NumberPad4, False) #ry += mouse.deltaY * viewSens if mouse.deltaY > 0: keyboard.setKey(Key.NumberPad2, True) keyboard.setKey(Key.NumberPad2, False) if mouse.deltaY < 0: keyboard.setKey(Key.NumberPad8, True) keyboard.setKey(Key.NumberPad8, False) else: timeKeyPressed -= system.threadExecutionInterval if timeKeyPressed < 0: timeKeyPressed = 0 else: ############################################## ### Mouse axis as Joystick via vJoy-Driver ### ############################################## if mouse.deltaX: moveLatch = True x += mouse.deltaX * sensX if abs(x) > vJoy[0].axisMax: x = vJoy[0].axisMax * x / abs(x) else: x /= (1.0 + centreX) if mouse.deltaY: moveLatch = True y += mouse.deltaY * sensY if abs(y) > vJoy[0].axisMax: y = vJoy[0].axisMax * y / abs(y) else: y /= (1.0 + centreY) ################### ### Pre mapping ### ################### # recenter if (not freelook and viewLatch): rx = 0 ry = 0 viewLatch = False #right mouse button if (mouse.getPressed(1) or mouse.rightButton): if (not rmbLatch): keyboard.setKey(rmbKey, True) keyboard.setKey(rmbKey, False) rmbLatch = True else: rmbLatch = False #code for hold freelock freelook = mouse.getButton(2) or mouse.middleButton #Throttle via Z-Axis mapped to mouse wheel if (mouse.wheel): z += mouse.wheel * sensZ if abs(z) > maxZ - deltaZ: #Minus deltaZ to prevent Throttel "hang" after matching targets velocity z = (maxZ - deltaZ) * z / abs(z) #################### ### vJoy mapping ### #################### ### FYI: Standard mapping ### #vJoy[0].rx = rx #vJoy[0].ry = ry #vJoy[0].x = x #vJoy[0].y = y #vJoy[0].z = -z ### X-Wing Alliance default "weird" mapping ### vJoy[0].rx = 0 vJoy[0].ry = 0 vJoy[0].rz = x vJoy[0].x = 0 vJoy[0].y = -y vJoy[0].z = -z #Joystick buttons mapped to mouse buttons vJoy[0].setButton(0, mouse.getButton(0) or mouse.leftButton) ## Joystick Button 2 (referenced here as 1 because the count starts at 0) without function, ## therefore right mouse button set on top of this script, e.g. "x"(rmbKey = Key.X) #vJoy[0].setButton(1, mouse.getButton(1) or mouse.rightButton) #################### ### Post mapping ### #################### #Prevent Throttle "hang" after matching targets velocity if (mouse.wheel and abs(z) == maxZ-deltaZ): z = z = maxZ * z / abs(z) ################### ### Diagnostics ### ################### diagnostics.watch(vJoy[0].x) diagnostics.watch(vJoy[0].y) diagnostics.watch(vJoy[0].z) diagnostics.watch(vJoy[0].rx) diagnostics.watch(vJoy[0].ry) diagnostics.watch(vJoy[0].rz) diagnostics.watch(freelook) diagnostics.watch(moveLatch) diagnostics.watch(mouse.getButton(0) or mouse.leftButton) diagnostics.watch(mouse.getButton(1) or mouse.rightButton) diagnostics.watch(mouse.getButton(2) or mouse.middleButton) diagnostics.watch(vJoy[0].axisMax)

Save it with "File -> Save as" to a location of your choice and then start it with F5. You should now see the raw values in the lower part of the FreePIE window:


Have a closer look at the three tabs at the bottom:
Watch should show altering numbers, as in the last screenshot.
The Error-tab should be empty (if not, feel free to post it)
Console may show something like "vJoy version of Driver (219) does NOT match DLL Version (218)". I ignored that successfully.

You can stop the script by pressing Shift-F5 in FreePIE
Conclusion
Once you have completed the above steps, you should be able to control your ship with your mouse movements, use the mouse wheel as throttle, fire your weapons with the left mouse button, (un)link your weapons using the right mouse button and free-look while holding the middle mouse button.

What I like about this solution is that it is not limited to a specific game or even gaming. With FreePIE you can work with the RAW inputs and have full control over all operations. Of course, you can change the example script to make the inputs softer by setting centerX and/or centerY to lower values - or discard automatic centering altogether.

According to the FreePIE documentation, you can also use this method to modify the inputs of your hardware joystick, transfer them to vJoy and thus solve problems such as wrong axes or other inconveniences. Other examples using FreePIE can be found in the Steam Community, e.g. here.

What can be inconvenient with this solution is that you need some programming knowledge to make customizations.
Links
Gist for this script[gist.github.com]
Base sample script[gist.github.com]
9 Comments
NucaCola Apr 16 @ 7:06pm 
I'm trying to use this for TFTC, and I followed your instructions easily. But I'm still drifting to the left out of control. I'm not sure what to do.
Chaos "Fox" Overlord  [author] Mar 24 @ 2:27pm 
#Throttle via Z-Axis mapped to W/S
if (keyboard.getKeyDown(Key.W)):
->z += sensZ * 10
->if abs(z) > maxZ - deltaZ: #Minus deltaZ to prevent Throttel "hang" after matching targets velocity
->->z = (maxZ - deltaZ) * z / abs(z)

if (keyboard.getKeyDown(Key.S)):
->z -= sensZ * 10
->if abs(z) > maxZ - deltaZ: #Minus deltaZ to prevent Throttel "hang" after matching targets velocity
->->z = (maxZ - deltaZ) * z / abs(z)

#Rolling mapped to A/D
if (keyboard.getKeyDown(Key.A)):
->x -= sensX * 10
->if abs(x) > vJoy[0].axisMax:
->->x = vJoy[0].axisMax * x / abs(x)

if (keyboard.getKeyDown(Key.D)):
->x += sensX * 10
->if abs(x) > vJoy[0].axisMax:
->->x = vJoy[0].axisMax * x / abs(x)
Chaos "Fox" Overlord  [author] Mar 24 @ 2:27pm 
@SW-Fan 1138 : I could barely test it, but something like this **may** work for you; one cannot use code blocks in the comments (which in my opinion is totally screwed up), so please replace each “->” with a tab before pasting it in FreePie. I hope this works for you; some function seem to be mapped to W/A/S/D, which may or may not be solveable.
SW-Fan1138 Mar 18 @ 11:08am 
Hi!

@Chaos: Thanks a lot for this guide. This helps a lot. As I'm currently playing Squadrons with Mouse and Keyboard, I would like to adapt the configuration from Squadrons to XWA. Like Kendicus, I have already modified your script a bit to use X-axis for yawing instead of rolling, but now I'm not able to roll wich is not so nice. I would like to use AD for rolling and WS for throttle, but I'm struggleing to get this running. Can you help me with this please?

Thanks in advance!
Chaos "Fox" Overlord  [author] Apr 1, 2024 @ 6:09am 
EDIT: Description extended based on CrisGers hint
Chaos "Fox" Overlord  [author] Apr 1, 2024 @ 5:53am 
@CrisGer: You are right, my description is somewhat lacking in detail:

After installing vJoy, running "Configure vJoy" from your Start Menu or "C:\Program Files\vJoy\x64\vJoyConf.exe" directly, a Window similar as shown on the first Screenshot should appear.
Be sure to choose tab "1", click "Add Device". This should lead to the virtual Joystick showing up.
Then configure it as shown above.
After configuring, click "Apply" (already greyed out in my screenshot, because I already clicked it when tacking the screenshot).


FreePIE is basically a text editor, thus copy and paste the script inside the editor window. Save it wherever you like and press F5.
Have a close look at the three tabs at the bottom:
Watch should show altering numbers, as in the last screenshot.
The Error-tab should be empty (if not, feel free to post it)
Console may show something like "vJoy version of Driver (219) does NOT match DLL Version (218)". I ignored that.
CrisGer Apr 1, 2024 @ 2:22am 
I am trying to use your instructions but cannot get the virtual joy stick to show up on my system, i installed both Vjoy and free and still cant use F5 and see the script working not sure where to put the script or how to turn it on..can you help with a few more details really hope to get this working
Kendicus Jan 22, 2024 @ 7:37pm 
Update: Managed to change from Roll to Yaw through using XWAU's Joystick configurator by Swapping Roll and Yaw's Axis Index
Kendicus Jan 22, 2024 @ 7:28pm 
This helped me plenty with not having to buy a controller :steamthis:

I have one issue being that you can only aim vertically in turret mode, I'm assuming its because traverse is tied to Yaw and not Roll. Good thing I can still do some basic gleaning with the .py