Coffees_Fa_Off_Advanced_V1: Joystick emulates mouse through [part] of it's range. Must have for FA OFF T16000 or Warthog users.
So, I've been avoiding using mouse for FA Off for the longest time (years), and I thought I'd try out to see what mouse emulation is like on Thrustmaster TARGET Script Software. So my find: it's absolutely awesome! I feel like this works better than mouse and keyboard, and it's all joystick! I've very excited, and just wanted to share in hopes you all have fun with this too.
This picture illustrates the range of motion (for Mouse and Joystick):
Here's the TMC file code:
So, I've been avoiding using mouse for FA Off for the longest time (years), and I thought I'd try out to see what mouse emulation is like on Thrustmaster TARGET Script Software. So my find: it's absolutely awesome! I feel like this works better than mouse and keyboard, and it's all joystick! I've very excited, and just wanted to share in hopes you all have fun with this too.
This picture illustrates the range of motion (for Mouse and Joystick):
Here's the TMC file code:
C:
include "target.tmh"
///////////////////////////////////////////////////////////////////////////////
// Coffees_Fa_Off_Advanced_V1
// Version: 1.0
// Author: MrCoffee76
// Date: 2022 02 01
//
// description:
//
// A Thrustmaster T16000 stick script that has a (roughly)50% deadzone for
// joystick and makes pitch and yaw (not roll) function like a mouse within
// this deadzone with micro trim.
// This substantially stabilizes aiming of fixed weapons during Flight Assist
// maneuvers.
//
// Installation:
//
// 1) Install Thrustmaster Target Script Editor 3.0.18.028 (or later?)
// 2) Place this text into a .tmc file (if you copy pasted). Otherwise, just
// save this file somewhere on your drive.
// 3) Run the .tmc file you created or saved in step 2
// 4) Make sure your yaw axis is set up properly in DEFAULT SETTINGS below
// 5) Check Elite Dangerous mouse settings:
// Mouse X: Yaw
// Relative Mouse X-Axis: On
// Mouse Y: Pitch Inverted
// Relative Mouse Y-Axis: On
// Mouse Sensitivity: low (your choice, start at low settings imo)
// Relative Mouse Rate: full
// Mouse Deadzone: 0
// Mouse Power Curve: 0
// Mouse Widget: your choice
//
//
// Issues: after some rolls, pitches and yaws, you will most likely have to
// constantly to get on target. Doing a quick 55% pitch/yaw move usually
// cancels most of the stray. Future versions will probably have a trim
// function that reduces stray within a second or two.
//
// Why: This little experiment/find changed my FA off aiming. No mouse needed
// and I prefer aiming with the joystick now.
// So, all of those people who gave up their Thrustmaster sticks for mouse
// can potentially benefit as much as I have. Good luck!
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// DEFAULT SETTINGS
// REQUIRED for Script
///////////////////////////////////////////////////////////////////////////////
// NOTE: if you use left and right on stick for yawing in ship, change RUDDER
// to DX_X_AXIS below. For example: define ED_YAW_AXIS RUDDER
define ED_YAW_AXIS RUDDER
define KEY_TOGGLE_MOUSE TS4
// if your trigger is broken and clicks off and on, try
// define USE_TRIGGER_FIX_HACK 1
define USE_TRIGGER_FIX_HACK 0
///////////////////////////////////////////////////////////////////////////////
// END OF DEFAULT SETTINGS
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// DO NOT change these unless you want to change
define NOSE_DOWN_THRESHOLD -2048
define NOSE_UP_THRESHOLD 16384
define NOSE_LEFT_THRESHOLD -16384
define NOSE_RIGHT_THRESHOLD 16384
// these values below are pre calculated. If you change the thresholds
// above, you will most likely need to recalculate these values below
// to get maximum pitch/yaw authority.
// for example, since we only use half the range for yaw, 32767 / 16384 = 2
// A divider is used to for nosing down so we reduce bounce effect
define NOSE_DOWN_OFFSET_MULT 2
define NOSE_UP_TRIM_DIVIDER 2
define NOSE_YAW_OFFSET_MULT 2
// trim cutoff levels and max trim authority
// max joystick deflection usually is 32767 so a value of 32 or -32 is a very small
// amount of adjustment.
define TRIM_CUTOFF_POS 1024
define TRIM_CUTOFF_NEG -1024
define MAX_TRIM_AUTHORITY_POS 32
define MAX_TRIM_AUTHORITY_NEG -32
define ED_MOUSE_CONFIG 2
int g_default_config = 1;
int g_config = g_default_config;
///////////////////////////////////////////////////////////////////////////////
// END REQUIRED
///////////////////////////////////////////////////////////////////////////////
//program startup
int main()
{
Configure(&HCougar, MODE_EXCLUDED);
Configure(&Joystick, MODE_EXCLUDED);
// Configure(&Throttle, MODE_EXCLUDED);
Configure(&LMFD, MODE_EXCLUDED);
Configure(&RMFD, MODE_EXCLUDED);
if(Init(&EventHandle)) return 1;
SetKBRate(32, 50);
SetKBLayout(KB_ENG);
SetShiftButton(0, 0, 0, 0, 0, 0);
// hat switch
MapKeyIOUMD(&T16000, H1D, DOWN+F9, DOWN+F9, DOWN+F9, DOWN+F9, DOWN+F9, DOWN+F9);
MapKeyRIOUMD(&T16000, H1D, UP+F9, UP+F9, UP+F9, UP+F9, UP+F9, UP+F9);
MapKeyIOUMD(&T16000, H1U, DOWN+F8, DOWN+F8, DOWN+F8, DOWN+F8, DOWN+F8, DOWN+F8);
MapKeyRIOUMD(&T16000, H1U, UP+F8, UP+F8, UP+F8, UP+F8, UP+F8, UP+F8);
MapKeyIOUMD(&T16000, H1R, DOWN+F12, DOWN+F12, DOWN+F12, DOWN+F12, DOWN+F12, DOWN+F12);
MapKeyRIOUMD(&T16000, H1R, UP+F12, UP+F12, UP+F12, UP+F12, UP+F12, UP+F12);
MapKeyIOUMD(&T16000, H1L, DOWN+F11, DOWN+F11, DOWN+F11, DOWN+F11, DOWN+F11, DOWN+F11);
MapKeyRIOUMD(&T16000, H1L, UP+F11, UP+F11, UP+F11, UP+F11, UP+F11, UP+F11);
MapKey(&T16000, TS2, DX2 );
if ( USE_TRIGGER_FIX_HACK == 1 )
{
MapKey(&T16000, TG1, EXEC( "MainTrigger(1);" ) );
MapKeyR(&T16000, TG1, EXEC( "MainTrigger(0);" ) );
}
// REQUIRED for ED_fa_off_stick_mouse_advanced
MapKey(&T16000, KEY_TOGGLE_MOUSE, EXEC( "ToggleMouse( 1 ); " ) );
MapJoystickAxes();
// END REQUIRED
// TWCS initialization
SetKBLayout(KB_ENG);
SetShiftButton(0, 0, 0, 0, 0, 0);
// TWCS axes and buttons. Most of these are left as their default buttons. See next section for changes.
MapKey(&TWCSThrottle, TBTN2, DX22 );
MapKey(&TWCSThrottle, TBTN3, DX23 );
MapKey(&TWCSThrottle, TBTN4, DX24 );
MapKey(&TWCSThrottle, TBTN5, DX25 );
MapKey(&TWCSThrottle, TLOCK, DX26); // Analog stick click.
MapKey(&TWCSThrottle, THAT1U, DX27); // THAT1 is the U-shaped hat. RIGHT is forward/away from you on the hat, LEFT is backward/toward you.
MapKey(&TWCSThrottle, THAT1R, DX28);
MapKey(&TWCSThrottle, THAT1D, DX29);
MapKey(&TWCSThrottle, THAT1L, DX30);
MapKey(&TWCSThrottle, THAT3U, DX31); // THAT3 is the castle hat. RIGHT is forward/away from you on the hat, LEFT is backward/toward you.
MapKey(&TWCSThrottle, THAT3R, DX32);
MapKey(&TWCSThrottle, THAT3D, DX17);
MapKey(&TWCSThrottle, THAT3L, DX18);
MapKey(&TWCSThrottle, THAT2U, DXHATUP); // THAT2 is the conical POV hat.
MapKey(&TWCSThrottle, THAT2R, DXHATRIGHT);
MapKey(&TWCSThrottle, THAT2D, DXHATDOWN);
MapKey(&TWCSThrottle, THAT2L, DXHATLEFT);
// TWCS axes. These are the default settings.
MapAxis(&TWCSThrottle, TTHR, DX_THROTTLE_AXIS, AXIS_NORMAL, MAP_ABSOLUTE); // normal
MapAxis(&TWCSThrottle, TANT, DX_SLIDER_AXIS, AXIS_NORMAL, MAP_ABSOLUTE); // normal
MapAxis(&TWCSThrottle, TRDR, DX_Z_AXIS, AXIS_NORMAL, MAP_ABSOLUTE); // normal
SetSCurve(&TWCSThrottle, TRDR, 2, 2, 2, 6, 0 );
MapAxis(&TWCSThrottle, TMSTX, DX_XROT_AXIS, AXIS_NORMAL, MAP_ABSOLUTE);
SetSCurve(&TWCSThrottle, TMSTX, 0, 3, 0, 4, 0);
MapAxis(&TWCSThrottle, TMSTY, DX_YROT_AXIS, AXIS_NORMAL, MAP_ABSOLUTE);
SetSCurve(&TWCSThrottle, TMSTY, 0, 0, 0, 4, 0);
// Rudder axes, if you have the rudder plugged into the throttle, instead of into the computer directly. These are all disabled here.
MapAxis(&TWCSThrottle, TCSRIGHT, 0, AXIS_NORMAL, MAP_ABSOLUTE);
SetSCurve(&TWCSThrottle, TCSRIGHT, 0, 0, 0, 0, 0);
MapAxis(&TWCSThrottle, TCSRUDDER, 0, AXIS_NORMAL, MAP_ABSOLUTE);
SetSCurve(&TWCSThrottle, TCSRUDDER, 0, 0, 0, 0, 0);
MapAxis(&TWCSThrottle, TCSLEFT, 0, AXIS_NORMAL, MAP_ABSOLUTE);
SetSCurve(&TWCSThrottle, TCSLEFT, 0, 0, 0, 0, 0);
}
///////////////////////////////////////////////////////////////////////////////
//event handler
int EventHandle(int type, alias o, int x)
{
DefaultMapping(&o, x);
// REQUIRED for ED_fa_off_stick_mouse_advanced
// check to see if we're in mouse mode and using T16000
if ( &o == &T16000 )
{
if ( x == JOYY )
ApplyEdgeJoystickInputY(); // check to see if we need pitch authority
else if ( x == ED_YAW_AXIS )
ApplyEdgeJoystickInputZ(); // check to see if we need yaw authority
}
// END REQUIRED
}
////////////////////////////////////////////////////////////////////////////////
// REQUIRED for ED_fa_off_stick_mouse_advanced
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// int ApplyEdgeJoystickInputY()
// purpose: when the joystick is in mouse mode and is moved 50% back or
// forward (> 0%), this function helps pitch rate by adding
// joystick input.
// Any amount of forward pitch (nosing down) will cause this
// function to apply nose down joystick inputs. Throughout the
// entire pitch range, this function will apply tiny trim amounts
// however if the joystick is moved back to 50% the function will
// start to apply joystick inputs - 1% input at the 50% pitch mark
// and 100% input at the 100% pitch mark.
////////////////////////////////////////////////////////////////////////////////
int ApplyEdgeJoystickInputY()
{
int pos = T16000[ JOYY ];
int new_val = 0;
if ( g_config != ED_MOUSE_CONFIG )
return 0;
if ( pos >= NOSE_UP_THRESHOLD ) // does the pitch need lots of help?
new_val = ( pos - NOSE_UP_THRESHOLD ) * NOSE_DOWN_OFFSET_MULT;
else if ( pos <= NOSE_DOWN_THRESHOLD ) // does the pitch need lots of help?
new_val = ( pos - NOSE_DOWN_THRESHOLD );
else if ( pos > TRIM_CUTOFF_POS ) // tiny trim help
new_val = MAX_TRIM_AUTHORITY_POS;
else if ( pos < TRIM_CUTOFF_NEG )
new_val = MAX_TRIM_AUTHORITY_NEG;
else if ( pos > MAX_TRIM_AUTHORITY_POS )
new_val = pos / MAX_TRIM_AUTHORITY_POS;
else if ( pos < MAX_TRIM_AUTHORITY_NEG )
new_val = pos / ( MAX_TRIM_AUTHORITY_POS / NOSE_UP_TRIM_DIVIDER );
DXAxis( DX_Y_AXIS, new_val );
printf( "ApplyEdgeJoystickInputY(), new_val: %d\xa", new_val );
return 1;
}
////////////////////////////////////////////////////////////////////////////////
// int ApplyEdgeJoystickInputZ()
// purpose: when the joystick is in mouse mode and is moved 50% left or
// right, this function helps yaw rate by adding joystick input.
// This function always trims by small amounts.
////////////////////////////////////////////////////////////////////////////////
int ApplyEdgeJoystickInputZ()
{
int pos = T16000[ ED_YAW_AXIS ];
int new_val = 0;
if ( g_config != ED_MOUSE_CONFIG )
return 0;
if ( pos >= NOSE_RIGHT_THRESHOLD )
new_val = ( pos - NOSE_RIGHT_THRESHOLD ) * NOSE_YAW_OFFSET_MULT;
else if ( pos <= NOSE_LEFT_THRESHOLD )
new_val = ( pos - NOSE_LEFT_THRESHOLD ) * NOSE_YAW_OFFSET_MULT;
else if ( pos > TRIM_CUTOFF_POS )
new_val = MAX_TRIM_AUTHORITY_POS;
else if ( pos < TRIM_CUTOFF_NEG )
new_val = MAX_TRIM_AUTHORITY_NEG;
else if ( pos > MAX_TRIM_AUTHORITY_POS )
new_val = pos / MAX_TRIM_AUTHORITY_POS;
else if ( pos < MAX_TRIM_AUTHORITY_NEG )
new_val = pos / MAX_TRIM_AUTHORITY_POS;
DXAxis( DX_ZROT_AXIS, new_val );
printf( "ApplyEdgeJoystickInputZ(), new_val: %d\xa", new_val );
return 1;
}
///////////////////////////////////////////////////////////////////////////////
int ToggleMouse( int cmd ) // 0 = reset, otherwise increment
{
if ( g_config == g_default_config )
{
g_config = ED_MOUSE_CONFIG;
MapMouseAxes();
}
else
{
g_config = g_default_config;
MapJoystickAxes();
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////
int MapMouseAxes()
{
DXAxis( MOUSE_X_AXIS, 0 );
DXAxis( MOUSE_Y_AXIS, 0 );
MapAxis(&T16000, ED_YAW_AXIS, DX_X_AXIS, 0, 0);
MapAxis(&T16000, JOYY, DX_Y_AXIS, 0, 0);
MapAxis(&T16000, ED_YAW_AXIS, MOUSE_X_AXIS, AXIS_NORMAL, MAP_ABSOLUTE);
MapAxis(&T16000, JOYY, MOUSE_Y_AXIS, AXIS_NORMAL, MAP_ABSOLUTE);
SetSCurve(&T16000, ED_YAW_AXIS, 0, 0, 0, -1, -10);
SetSCurve(&T16000, JOYY, 0, 0, 0, -1, -10);
return 0;
}
///////////////////////////////////////////////////////////////////////////////
int MapJoystickAxes()
{
MapAxis(&T16000, JOYX, DX_X_AXIS, AXIS_NORMAL, MAP_ABSOLUTE);
SetSCurve(&T16000, JOYX, 2, 5, 2, 2, 0);
MapAxis(&T16000, JOYY, DX_Y_AXIS, AXIS_NORMAL, MAP_ABSOLUTE);
SetSCurve(&T16000, JOYY, 2, 2, 2, 3, 0);
MapAxis(&T16000, RUDDER, DX_ZROT_AXIS, AXIS_NORMAL, MAP_ABSOLUTE);
SetSCurve(&T16000, RUDDER, 2, 2, 2, 5, 0);
return 0;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// END REQUIRED
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Extras
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int MainTrigger( int v )
{
int i = 0;
int j;
if ( v == 0 ) // released?
{
g_trigger1 = 1; // about to depress
while ( i < 17179869184 && g_trigger1 < 2 ); // polling loop or times out
if ( g_trigger1 == 1 ) // are we still in the same g_trigger1 depress state?
{
KeyU( DX1 );
g_trigger1 = 0;
}
}
else // pressed down
{
KeyD( DX1 );
g_trigger1 = 2;
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////