A FA-off relative mouse toggle program to rule them all

Over the past few weeks I've sunk some time into addressing a fundamental problem this game has when it comes to flying FA-off as a keyboard-mouse user. Relative mouse mode works wonderfully when in FA-off, but the moment you jump into supercruise or flip FA back on, you're screwed! Dragging your mouse is no fun nor is diving into menus to toggle relative mouse every time, and accordingly programs have been made to attempt to address it.
The issue! (imgur album)

The two prominent threads that come to mind are two iterations of the same program:
CMDR Spadino's
jackblack_2001's

jackblack_2001's guide is comprehensive when it comes to setting up the utilities required (FreePIE and vJoy), but his implementation of this program leaves something to be desired. It effectively allows the user to toggle a single virtual joystick to be used for absolute mouse mode. The issue here, though, is that you cannot disable the in-game mouse input! This leaves you with a functional toggle hampered by the fact that you have a minor "burst" from the relative mouse on top of the absolute motion.

CMDR Spadino's version features two independent virtual joysticks, one delegated to absolute and the other to relative mode. This is the superior way to approach this issue; as stated before, you can't outright disable mouse input in the game, and this approach allows you to have two separate input "modes" that do not interfere with one another. However, Spadino's approach to emulating relative mouse has a variety of issues, detailed below in the copy-pasted description from my edited program:
Edited dual-axis output program for E: D, by lemurcan, credit to Andrea Spada for original program
# Requirements: vJoy and freePie
# This edit fixes a few fundamental issues with Andrea's program, most notably the behavior of the
# relative-mouse emulation.
# 1. Previously in the program, relative mouse was emulated with a "fixed" return to center rate. This meant that for
# minor movements amounting to less than this fixed value, they would be cancelled out by the next poll of the program.
# This severely hindered fine control and combined with the following flaw, did not accurately emulate the game's
# relative mouse function.
# 2. The previous relative mouse implementation incorporated an "idle check" that would make it so the return force only
# activated when there was no new movement. It did this by having alternating checks, one at a 30ms poll and another 60ms;
# this effectively meant that the return motion would only occur once your mouse had been still for 30ms. This, as per my
# own experimental testing with the official in-game relative mouse, is also inaccurate. The ingame return force is always
# active and has no waiting-for-idle component.
# 3. This is a relatively minor flaw but the previous program only polled at a 4ms rate; I have upped this to 1ms to improve
# input delay and be on-par with the standard for most "gaming-grade" mice. This also helps account, in my view, for Python's
# timing inconsistencies. Do note that the logarithmic curve implemented for relative mouse is scaled accordingly, and
# adjusting this poll rate will necessitate an inverse multiplication of rel_factor.
This is quite the handful of issues. One may ask, then, how did CMDR lemurcan come across the "correct" way to emulate relative mouse?
The answer to this question would be: the scientific process. In less vague terms, though, I recorded a video of the cursor's behavior when flying with relative mouse maxed out; swinging my mouse far to one side to "max out" the cursor for some time, then releasing it and watching the pattern it traced as it receded to center. This required much pixel counting and then graphing to try and find a pattern:

1663496737468.png


This is an image of the raw data;
x_1 being the time in milliseconds (pertinent as the program polls once every millisecond), which is the reason for all the odd divisions. 1000/60 is equal to the time one frame takes in milliseconds (1000ms in a second, 60 frames a second).
y_1 being the raw pixel location of the tip of the arrow, with k being the offset to make it effectively distance from center, and the division over 174 bringing it to a fractional percent; 1 being farthest from center and 0 being at center.

The primary limitations of this trial were:
  • The arrow fades as you get closer to center and I can't easily count pixels that way
  • I am a human counting pixels with a mouse location tool and there is inherent inaccuracy there
  • I am a human also controlling the direction of the measured mouse and I don't necessarily have it perfectly parallel

You can see the impacts of this after ~225ms, where this nice curve we've found starts to "wiggle" a bit. Regardless of this, my intuition declared this as a logarithmic curve, and I set off to model this with an equation as to be able to have a common dividing factor for practical use in the program. Logarithmic curves apply to many things in life; one example that comes to mind is nuclear decay and half-lives. Per every half-life, half the remaining fissile material will decay, and as time goes on the amount decaying per half-life decreases accordingly; 1/2 to 1/4 to 1/8 etc. Of course, this "factor of division" doesn't have to be the same; it could be 1/5, or 1/18, or 1/200th! The way this is modelled in my version of the program is as-so:

1663498093687.png


rel_factor is the key variable, which determines the factor by which the joystick position is reduced every poll. If it were two, the joystick position would shrink just as the half life example above; from full deflection it would be 1, then 1ms later 1/2, 2ms 1/4, 3ms 1/8...the pattern goes on. Relating this pattern to an equation is most intuitive to me by establishing a simple differential equation: dy/dx = -y/C. In ordinary terms, the rate of change of the joystick (dy/dx) = the negative of the current position of the joystick divided by a constant factor C. C, in our case, is rel_factor; as the equation is polled once every millisecond, our rate of change per millisecond is laid out simply with this equation. Eliminating the differential part of this equation yields y = e^(-x/C). We can then plug that equation into our graphing tool, and adjust C to the data collected before:
1663498601982.png

1663498613543.png

This graph is remarkably close to the data, with discrepancies that (in my opinion) can be dismissed as simply non-perceptible and/or accounted for by measurement error. The value of 190 aligns with my relative mouse slider in-game; I had it at "almost max" as that was what I found most comfortable in regular use. Extrapolating this to a rel_factor value of 200 as being equivalent to maxing out the in-game slider is reasonable in my book.

That was a lot of math and pointless explanation, but I figured it best I document my reasoning here for future reference. All that aside, here are key links and usage information:

There are two utilities required to use this program correctly: FreePIE and vJoy. The setup of both of these is covered in jackblack's guide linked above.

The program itself will be linked below. Before launching this program, usage guidelines are:
  • There are two virtual joysticks established through vJoy. x/y, and Rx/Ry. x/y handles absolute output, while Rx/Ry handles relative output.
  • The way you should configure your controls in-game is through the use of alternate flight mode toggles. Have one flight mode handle absolute input, and the other handle relative input. I have not tested this myself as I am still playing around with the project as I write this, but you should be able to bind both flight mode and flight assist toggles to the same key, to have them change inputs and flight assist mode in harmony. This will likely not apply to jumping into supercruise and it may be good practice to switch FA back on before jumping accordingly.
  • Sensitivity and other curve controls are inside the program. Read the comments at the head and throughout the program to understand where/what to change.
  • Joystick centering keybinds are inside the program. Read the comments at the head and throughout the program to understand where/what to change.
  • The program itself is linked below. As with any unsigned program from any stranger, please read through it to make sure nothing malicious is going on, just for safety's sake; and to repeat, read the comments at the head and throughout the program to understand where/what to change.

Program pastebin; hit download, should be a .py file. Run with FreePIE

This is my first post here as I've never had much involvement with the forum, so please let me know if there's anything to change or make clear! Enjoy, lemurcan
 
A very interesting read. I'm going to have to have a play around with some of these settings. Not for the relative mouse aspect but since relative mouse is "emulated" here I'm wondering if the same can be achieved for the pitch and yaw of a joystick setup, giving the advantages of FAoff movement but FAon aiming.
 
Installing third party software, one of which essentially hooks into your OS as a driver is just icky.
I've done it, and it sort-of just works but requires a lot of workarounds and Win32 api calls within FreePie for ClipCursor, etc when you're using more then one monitor.

It's just... ugh.

All of that mess could be avoided if a Relative/Absolute Mouse toggle hotkey was available -- all neatly contained within the game.
 
A very interesting read. I'm going to have to have a play around with some of these settings. Not for the relative mouse aspect but since relative mouse is "emulated" here I'm wondering if the same can be achieved for the pitch and yaw of a joystick setup, giving the advantages of FAoff movement but FAon aiming.
The closest to this functionality I can imagine is having a similar program treat the "return stroke" of the physical joystick as a negative-offset movement on the software side; this way whatever momentum from the initial motion FA-off is then cancelled out on physical return. The issue with this is turnrate behavior in-game; if you got up to angular speed in the blue zone and then decided to steady yourself at a different translational speed, the return turn rate would differ from the initial impulse. Similarly, if your initial impulse pushed your ship to its max turnrate, the return stroke would overcorrect and leave you turning the opposite way. I could go into how the concept of relative mouse on its own is effectively removing an order of separation between controller and ship behavior (with FA-off, think absolute mouse being mouse position -> ship angular acceleration, vs. relative mouse as mouse position -> ship angular velocity; for a joystick flying FA-off, it is joystick position -> ship angular acceleration, and your goal would be joystick position -> ship angular velocity), but these practical issues are what would be the primary obstacle to any program aiming to emulate FA-on joystick input behavior while in FA-off. Something to note is that a joystick always has a physical return force, while a mouse requires a force from you to return to "center"; this is why most people consider FA-off relative mouse to be analogous to FA-off joystick, as they require the same user motions/inputs for the same ship responses.
 
Installing third party software, one of which essentially hooks into your OS as a driver is just icky.
I've done it, and it sort-of just works but requires a lot of workarounds and Win32 api calls within FreePie for ClipCursor, etc when you're using more then one monitor.

It's just... ugh.

All of that mess could be avoided if a Relative/Absolute Mouse toggle hotkey was available -- all neatly contained within the game.
As a keyboard/mouse user, this is certainly one of the more frustrating issues.
It's odd to me that FDev did not include something like this in the options.
That's the tragedy of it all--none of this work would be necessitated if FDev took some time aside during however many years of development to pay attention to people using the most common peripherals on their most common platform--PC. I can somewhat understand the oversight given that this is a "sim"-like game and most people will want HOTAS/HOSAS setups for the sake of immersion, but after however many years of community requests? That's another story.
 
As a sidenote I've realized that I've neglected to include an option to outright toggle the functionality of the program; this is essential for functions like headlook and really any other non-cockpit interface that uses the mouse. Should have a new pastebin up shortly
 
It is quite amazing how much extra game dev ED requires to be decent. I could never be bothered with the 3rd party stuff. It's not supported, so you end up with stuff that stops working at some point and then youhave to bother about replacement.
 
It is quite amazing how much extra game dev ED requires to be decent. I could never be bothered with the 3rd party stuff. It's not supported, so you end up with stuff that stops working at some point and then youhave to bother about replacement.
The main concern with this implementation is all the libraries behind it Windows-side; all elite needs to do is support analog joystick devices, the same way it would have to for all the HOTAS users out there. The bigger question remains why so many different third-party tools need to go into the game in the first place--I've only been with the game for a year or two now, but it certainly seems to be a trend of the studio neglecting key quality-of-life or borderline essential tools (such as INARA or other trade/inventory trackers) in favor of the bare minimum to save face.
 
I just bound space for pitch up... and i have Roll LR on QE.
And in supecruise i just roll / pitch (and it works almost as good in FA On in normal space)

🤷‍♂️
 
Solution seeking a problem. Just map keyboard controls for supercruise. You don’t need precision for supercruise.
And what of players that wish to use both FA-off and on? There's no reason to dismiss a solution solely because it does not fit your exact use case.
There's also the simple matter of one not wanting to have to switch to an entire different control scheme for supercruise.
 
For what it's worth, there is now an issue tracker ticket opened on this problem.

This is also a hugely helpful tool and I think the first one that truly addresses the previous iterations' flaws. Thank you!
 
Last edited:
Just to check and probably as an obvious drawback of relying on two vjoy axis while the game isn't capable of completely turning out mouse control when registering analog inputs : it isn't possible at all to use the in-game moues controls for absolute mode, nor is there a way to display the in-game vjoy cursor?

It's a bit of a problem, especially in absolute mode, which makes recentering without overshooting the neutral center a bit painful.
 
Just to check and probably as an obvious drawback of relying on two vjoy axis while the game isn't capable of completely turning out mouse control when registering analog inputs : it isn't possible at all to use the in-game moues controls for absolute mode, nor is there a way to display the in-game vjoy cursor?

It's a bit of a problem, especially in absolute mode, which makes recentering without overshooting the neutral center a bit painful.
Late reply, but:
1. You can still use the ingame mouse alongside any sort of virtual-joystick implementation, but the issue remains in any configuration (yours included) of the in-game mouse always affecting input and not properly toggling. (this does bring thoughts of an implementation that had absolute-in-game-mouse always on and counteracted it with a virtual joystick input, but I don't entirely see the utility outside of having an always-on mouse widget)
2. There are third party tools that allow you to display the status/position of analog inputs; while no specifics come to mind past tools for OBS/recording software, I wonder if a tool like this could be overlaid elite to give you a pseudo-widget. Unfortunately this is also adding just another layer of third party work to the solution 🙃
3. Sensitivity and centering radius values are adjustable for reasons like this, too. While my defaults are pretty conservative and give a ~2 deg/s threshold for the "centering pull" to kick in, this can certainly be ramped up to make it much easier for the cursor to snap back to center. All I can say is play with the values to see how they adjust performance, and shoot me any questions if you need clarification on any variables/functionality. Best wishes!
 
Late reply, but:
1. You can still use the ingame mouse alongside any sort of virtual-joystick implementation, but the issue remains in any configuration (yours included) of the in-game mouse always affecting input and not properly toggling. (this does bring thoughts of an implementation that had absolute-in-game-mouse always on and counteracted it with a virtual joystick input, but I don't entirely see the utility outside of having an always-on mouse widget)
2. There are third party tools that allow you to display the status/position of analog inputs; while no specifics come to mind past tools for OBS/recording software, I wonder if a tool like this could be overlaid elite to give you a pseudo-widget. Unfortunately this is also adding just another layer of third party work to the solution 🙃
3. Sensitivity and centering radius values are adjustable for reasons like this, too. While my defaults are pretty conservative and give a ~2 deg/s threshold for the "centering pull" to kick in, this can certainly be ramped up to make it much easier for the cursor to snap back to center. All I can say is play with the values to see how they adjust performance, and shoot me any questions if you need clarification on any variables/functionality. Best wishes!
Late reply to your late reply, but I wanted to say that I appreciate it a lot. I've tinkered a good deal and seeing the mouse widget would have been my last major want. I understand your point in 1), and have experienced it myself when I tried.

One thing I have observed is that the pradius doesn't feel like it does anything. I ended up defining a device deadzone in Elite itself to achieve what I wanted.

FDev finally tackling this issue would be ideal, of course, but then again I've given up on that sort of common sense.

Thanks again and have a great remainder of your week-end!
 
Back
Top Bottom