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:
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:
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:
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:
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:
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:
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
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:
This is quite the handful of issues. One may ask, then, how did CMDR lemurcan come across the "correct" way to emulate relative mouse?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.
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:
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:
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:
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