Analog Triggers - AL2009man/JoyShockMapper GitHub Wiki

The following section does not apply to Joycons and Switch Pro controllers because they only have digital triggers.

Analog to digital

Analog triggers report a value between 0% and 100% representing how far you are pulling the trigger. Binding a digital button to an analog trigger is done using a threashold value. The button press is sent when the trigger value crosses the threashold value, sitting between 0% and 100%. The default threashold value is 0, meaning the slightest press of the trigger sends the button press. This is great for responsiveness, but could result in accidental presses. The threashold can be customized by running the following command:

TRIGGER_THRESHOLD = 0.5   #Send Trigger values at half press

The same threashold value is used for both triggers. A value of 1.0 or higher makes the binding impossible to reach.

Hair trigger is also implemented: to enable it, assign a value of -1 as the trigger threshold. When hair trigger is used, the binding is enabled when the trigger is being pressed and held, and released when the trigger is being released. This allows quick tap shooting by pulsing the trigger.

Full pull and modes

JoyShockMapper can assign different bindings to the full pull of the trigger, allowing you to double the number of bindings put on the triggers. The way the trigger handles these bindings is set with the variables ZR_MODE and ZL_MODE, for R2 and L2 triggers. Once set, you can assign keys to ZRF and ZLF to make use of the R2 and L2 full pull bindings respectively. In this context, ZL and ZR are called the soft pull binding because they activate before the full pull binding does at 100%. Here is the list of all possible trigger modes.

NO_FULL (default): Ignore full pull binding. This mode is enforced on controllers who have digital triggers.
NO_SKIP: Never skip the soft pull binding. Full pull binding activates anytime the trigger is fully pressed.
NO_SKIP_EXCLUSIVE: Never skip the soft pull binding. When Full pull binding is active, the soft pull binding isn't.
MUST_SKIP: Only send full pull binding on a quick full press of the trigger, ignoring soft pull binding.
MAY_SKIP: Combines NO_SKIP and MUST_SKIP: Soft binding may be skipped on a quick full press, and full pull can be activated on top of soft pull binding.
MUST_SKIP_R: Responsive version of MUST_SKIP. See below.
MAY_SKIP_R: Responsive version of MAY_SKIP. See below.

For example, in Call of Duty you have a binding to hold your breath when aiming with a sniper. You can bind ADS on a soft trigger press and hold breath on the full press like this:

ZL_MODE = NO_SKIP   # Enable full pull binding, never skip ADS
ZL = RMOUSE         # Aim Down Sights
ZLF = LSHIFT        # Hold breath

Using NO_SKIP mode makes it so that LSHIFT is only active if RMOUSE is active as well. Then on the right trigger, you can bind your different attack bindings: use the skipping functionality to avoid having them conflict with eachother like this:

TRIGGER_THRESHOLD = -1 # Use hair trigger for primary fire
ZR_MODE = MUST_SKIP    # Enable full pull binding, soft and full bindings are mutually exclusive
ZR = LMOUSE            # Primary Fire
ZRF = V G              # Quick full tap to melee; Quick hold full press to unpin grenade and throw on release

Using MUST_SKIP mode makes sure that once you start firing, reaching the full pull will not make you stop firing to melee.

The "Responsive" variants of the skip modes enable a different behaviour that can give you a better experience than the original versions in specific circumstances. A typical example is when the soft binding is a mode-like binding like ADS or crouch, and there is no hold or simultaneous press binding on that soft press. The difference is that the soft binding is actived as soon as the trigger crosses the threshold, giving the desired responsive feeling, but gets removed if the full press is reached quickly, thus still allowing you to hip fire for example. This will result in a hopefully negligeable scope glitch but grants a snappier ADS activation.

Adaptive Triggers

The Dualsense controller features adaptive trigger that allow software to control the force feedback applies on the triggers. JoyShockMapper makes use of this feature to provide useful feedback depending on the trigger mode and position of the trigger. If you don't want JSM to use this feature, it can be disbaled across the board with the following command:

ADAPTIVE_TRIGGER = OFF # Don't use force feedback in my triggers

While adaptive triggers are enabled, the Dualsense controller will ignore hair trigger threshold, and consider it to be simply threshold zero. This is because the adaptive triggers fulfill the purpose of hair triggers by restricting uneccessary travelling distance. With adaptive triggers turned off, regular hair trigger is then accessible.

Each trigger and each devices might have slightly different trigger properties, which causes a mismatch between the reported trigger position and the position setting in the resistance packet. Each trigger thus gets 2 new settings, an offset and a range, that can be determined through a single-time calibration procedure. You can start this procedure by entering the command CALIBRATE_TRIGGERS : you will be required to gently press on a trigger just until you feel the resistance push back. Then you press a button and you will feel the trigger slowly lower : make sure you press gently. Once you reach full press JSM will display to you the calculated offset and range for your trigger. The same procedure is done on the other trigger after.

You should set these values in your OnReset.txt file so that they are always set properly for your controller.

LEFT_TRIGGER_OFFSET = 20     # My DS trigger calibration values
LEFT_TRIGGER_RANGE = 167
RIGHT_TRIGGER_OFFSET = 31
RIGHT_TRIGGER_RANGE = 175

User Nielk1 has reverse engineered the adaptive trigger data and developped a C# utility for it. With his permission (and under MIT licence) I've C++-ified the code and integrated it into JSM. Two new settings are then available LEFT_TRIGGER_EFFECT and RIGHT_TRIGGER_EFFECT. They can be set to OFF or ON (JSM handling) or be provided with one of Nielk1's functions.

RESISTANCE start[0 9] force[0 8]: Some resistance starting at point
BOW start[0 8] end[0 8] forceStart[0 8] forceEnd[0 8]: increasingly strong resistance
GALLOPING start[0 8] end[0 9] foot1[0 6] foot2[0 7] freq[Hz]: Two pulses repeated periodically
SEMI_AUTOMATIC start[2 7] end[0 8] force[0 8]: Trigger effect
AUTOMATIC start[0 9] strength[0 8] freq[Hz]: Regular pulse effect
MACHINE start[0 9] end[0 9] force1[0 7] force2[0 7] freq[Hz] period: Irregular pulsing