Overriding mouse is much better than overriding client angles

This commit is contained in:
rackover 2021-05-04 18:09:37 +02:00
parent 1df84f7536
commit bac2afa028
3 changed files with 653 additions and 117 deletions

View File

@ -9,8 +9,8 @@ namespace Components
bool XInput::isHoldingMaxLookX = false;
float XInput::lockedSensitivityMultiplier = 0.45f;
float XInput::generalXSensitivityMultiplier = 1.5f;
float XInput::generalYSensitivityMultiplier = 0.8f;
float XInput::generalXSensitivityMultiplier = 3 * 1.5f;
float XInput::generalYSensitivityMultiplier = 4 * 0.8f;
float XInput::lastMenuNavigationDirection = .0f;
std::chrono::milliseconds XInput::lastNavigationTime = 0ms;
@ -18,6 +18,8 @@ namespace Components
std::chrono::milliseconds XInput::msBeforeUnlockingSensitivity = 350ms;
float sensitivityMultiplier = 1.0f;
std::vector<XInput::ActionMapping> mappings = {
XInput::ActionMapping(XINPUT_GAMEPAD_A, "gostand"),
XInput::ActionMapping(XINPUT_GAMEPAD_B, "stance"),
@ -101,49 +103,23 @@ namespace Components
float moveStickX = abs(xiState->Gamepad.sThumbLX) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ? xiState->Gamepad.sThumbLX / (float)std::numeric_limits<SHORT>().max() : .0f;
float moveStickY = abs(xiState->Gamepad.sThumbLY) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ? xiState->Gamepad.sThumbLY / (float)std::numeric_limits<SHORT>().max() : .0f;
float viewStickX = abs(xiState->Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ? xiState->Gamepad.sThumbRX / (float)std::numeric_limits<SHORT>().max() : .0f;
float viewStickY = abs(xiState->Gamepad.sThumbRY) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ? xiState->Gamepad.sThumbRY / (float)std::numeric_limits<SHORT>().max() : .0f;
if (moveStickX != 0 || moveStickY != 0) {
// We check for 0:0 again so we don't overwrite keyboard input in case the user doesn't feel like using their gamepad, even though its plugged in
cmd->rightmove = moveStickX * std::numeric_limits<char>().max();
cmd->forwardmove = moveStickY * std::numeric_limits<char>().max();
}
// Gamepad horizontal acceleration on view
if (abs(viewStickX) > 0.9f) {
if (!XInput::isHoldingMaxLookX) {
XInput::isHoldingMaxLookX = true;
XInput::timeAtFirstHeldMaxLookX = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
}
else {
std::chrono::milliseconds hasBeenHoldingLeftXForMs = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()) - XInput::timeAtFirstHeldMaxLookX;
#ifdef STEP_SENSITIVITY
if (hasBeenHoldingLeftXForMs < XInput::msBeforeUnlockingSensitivity) {
viewStickX *= XInput::lockedSensitivityMultiplier;
}
#else
float coeff = std::clamp(hasBeenHoldingLeftXForMs.count() / (float)XInput::msBeforeUnlockingSensitivity.count(), 0.0F, 1.0F);
viewStickX *= XInput::lockedSensitivityMultiplier + coeff * (1.0f - XInput::lockedSensitivityMultiplier);
#endif
}
}
else {
XInput::isHoldingMaxLookX = false;
XInput::timeAtFirstHeldMaxLookX = 0ms;
}
Game::cl_angles[0] -= viewStickY * generalYSensitivityMultiplier;
Game::cl_angles[1] -= viewStickX * generalXSensitivityMultiplier;
bool pressingLeftTrigger = xiState->Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD ? true : false;
if (pressingLeftTrigger != XInput::lastXiState.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
{
if (pressingLeftTrigger)
if (pressingLeftTrigger) {
Command::Execute("+toggleads_throw");
Command::Execute("+speed");
else
}
else {
Command::Execute("-toggleads_throw");
Command::Execute("-speed");
}
}
bool pressingRightTrigger = xiState->Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD ? true : false;
@ -348,7 +324,7 @@ namespace Components
menuMappings[i].wasPressed = false;
}
}
else if(xiState->Gamepad.wButtons & mapping.input){
else if (xiState->Gamepad.wButtons & mapping.input) {
Game::UI_KeyEvent(0, mapping.keystroke, 1);
menuMappings[i].wasPressed = true;
}
@ -357,6 +333,84 @@ namespace Components
}
}
void XInput::MouseOverride(Game::clientActive_t* clientActive, float* mx, float* my) {
XInput::CL_GetMouseMovementCl(clientActive, mx, my);
if (XInput::xiPlayerNum != -1)
{
XINPUT_STATE* xiState = &xiStates[xiPlayerNum];
float viewSensitivityMultiplier = Dvar::Var("xinput_sensitivity").get<float>();
float viewStickX = abs(xiState->Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ? xiState->Gamepad.sThumbRX / (float)std::numeric_limits<SHORT>().max() : .0f;
float viewStickY = abs(xiState->Gamepad.sThumbRY) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ? xiState->Gamepad.sThumbRY / (float)std::numeric_limits<SHORT>().max() : .0f;
// Gamepad horizontal acceleration on view
if (abs(viewStickX) > 0.9f) {
if (!XInput::isHoldingMaxLookX) {
XInput::isHoldingMaxLookX = true;
XInput::timeAtFirstHeldMaxLookX = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
}
else {
std::chrono::milliseconds hasBeenHoldingLeftXForMs = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()) - XInput::timeAtFirstHeldMaxLookX;
#ifdef STEP_SENSITIVITY
if (hasBeenHoldingLeftXForMs < XInput::msBeforeUnlockingSensitivity) {
viewStickX *= XInput::lockedSensitivityMultiplier;
}
#else
float coeff = std::clamp(hasBeenHoldingLeftXForMs.count() / (float)XInput::msBeforeUnlockingSensitivity.count(), 0.0F, 1.0F);
viewStickX *= XInput::lockedSensitivityMultiplier + coeff * (1.0f - XInput::lockedSensitivityMultiplier);
#endif
}
}
else {
XInput::isHoldingMaxLookX = false;
XInput::timeAtFirstHeldMaxLookX = 0ms;
}
if (viewStickX != 0 || viewStickY != 0) {
*(my) = viewStickX * viewSensitivityMultiplier * generalXSensitivityMultiplier;
*(mx) = -viewStickY * viewSensitivityMultiplier * generalYSensitivityMultiplier;
}
}
}
// Game -> Client DLL
__declspec(naked) void CL_GetMouseMovementStub()
{
__asm
{
push edx;
push ecx;
push eax;
call XInput::MouseOverride;
add esp, 0xC;
ret;
}
}
// Client DLL -> Game
void XInput::CL_GetMouseMovementCl(Game::clientActive_t* result, float* mx, float* my)
{
__asm
{
push ebx;
push ecx;
push edx;
mov eax, result;
mov ecx, mx;
mov edx, my;
mov ebx, 5A60E0h;
call ebx;
pop edx;
pop ecx;
pop ebx;
}
}
XInput::XInput()
{
// poll xinput devices every client frame
@ -376,6 +430,10 @@ namespace Components
Utils::Hook(0x492127, XInput::MSG_ReadDeltaUsercmdKeyStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x492009, XInput::MSG_ReadDeltaUsercmdKeyStub2, HOOK_JUMP).install()->quick();
Utils::Hook(0x5A617D, CL_GetMouseMovementStub, HOOK_CALL).install()->quick();
Game::Dvar_RegisterFloat("xinput_sensitivity", 1.0f, 0.01f, 10.0f, Game::DVAR_FLAG_SAVED, "View sensitivity for XInput-compatible gamepads");
PollXInputDevices();
if (xiPlayerNum >= 0) {

View File

@ -51,6 +51,10 @@ namespace Components
static std::chrono::milliseconds msBetweenNavigations;
static float lastMenuNavigationDirection;
static void CL_GetMouseMovementCl(Game::clientActive_t* result, float* mx, float* my);
static void MouseOverride(Game::clientActive_t* clientActive, float* my, float* mx);
static char MovementOverride(int a1, Game::usercmd_s* cmd);
static void Vibrate(int leftVal = 0, int rightVal = 0);
static void CL_FrameStub();

View File

@ -706,6 +706,562 @@ namespace Game
MaterialShaderArgument *args;
};
enum OffhandClass
{
OFFHAND_CLASS_NONE = 0x0,
OFFHAND_CLASS_FRAG_GRENADE = 0x1,
OFFHAND_CLASS_SMOKE_GRENADE = 0x2,
OFFHAND_CLASS_FLASH_GRENADE = 0x3,
OFFHAND_CLASS_THROWINGKNIFE = 0x4,
OFFHAND_CLASS_OTHER = 0x5,
OFFHAND_CLASS_COUNT = 0x6,
};
enum ViewLockTypes
{
PLAYERVIEWLOCK_NONE = 0x0,
PLAYERVIEWLOCK_FULL = 0x1,
PLAYERVIEWLOCK_WEAPONJITTER = 0x2,
PLAYERVIEWLOCKCOUNT = 0x3,
};
struct SprintState
{
int sprintButtonUpRequired;
int sprintDelay;
int lastSprintStart;
int lastSprintEnd;
int sprintStartMaxLength;
};
/* 1018 */
struct MantleState
{
float yaw;
int timer;
int transIndex;
int flags;
};
/* 1019 */
struct PlayerActiveWeaponState
{
int weapAnim;
int weaponTime;
int weaponDelay;
int weaponRestrictKickTime;
int weaponState;
int weapHandFlags;
unsigned int weaponShotCount;
};
/* 1020 */
struct PlayerEquippedWeaponState
{
bool usedBefore;
bool dualWielding;
char weaponModel;
bool needsRechamber[2];
};
/* 1021 */
struct GlobalAmmo
{
int ammoType;
int ammoCount;
};
/* 1022 */
struct ClipAmmo
{
int clipIndex;
int ammoCount[2];
};
enum PlayerHandIndex
{
WEAPON_HAND_RIGHT = 0x0,
WEAPON_HAND_LEFT = 0x1,
NUM_WEAPON_HANDS = 0x2,
WEAPON_HAND_DEFAULT = 0x0,
};
/* 1023 */
struct PlayerWeaponCommonState
{
int offHandIndex;
OffhandClass offhandPrimary;
OffhandClass offhandSecondary;
unsigned int weapon;
unsigned int primaryWeaponForAltMode;
int weapFlags;
float fWeaponPosFrac;
float aimSpreadScale;
int adsDelayTime;
int spreadOverride;
int spreadOverrideState;
PlayerHandIndex lastWeaponHand;
GlobalAmmo ammoNotInClip[15];
ClipAmmo ammoInClip[15];
int weapLockFlags;
int weapLockedEntnum;
float weapLockedPos[3];
int weaponIdleTime;
};
enum ActionSlotType
{
ACTIONSLOTTYPE_DONOTHING = 0x0,
ACTIONSLOTTYPE_SPECIFYWEAPON = 0x1,
ACTIONSLOTTYPE_ALTWEAPONTOGGLE = 0x2,
ACTIONSLOTTYPE_NIGHTVISION = 0x3,
ACTIONSLOTTYPECOUNT = 0x4,
};
/* 1024 */
struct ActionSlotParam_SpecifyWeapon
{
unsigned int index;
};
/* 1025 */
struct ActionSlotParam
{
ActionSlotParam_SpecifyWeapon specifyWeapon;
};
enum objectiveState_t
{
OBJST_EMPTY = 0x0,
OBJST_ACTIVE = 0x1,
OBJST_INVISIBLE = 0x2,
OBJST_DONE = 0x3,
OBJST_CURRENT = 0x4,
OBJST_FAILED = 0x5,
OBJST_NUMSTATES = 0x6,
};
/* 1026 */
struct objective_t
{
objectiveState_t state;
float origin[3];
int entNum;
int teamNum;
int icon;
};
/* 104 */
enum he_type_t
{
HE_TYPE_FREE = 0x0,
HE_TYPE_TEXT = 0x1,
HE_TYPE_VALUE = 0x2,
HE_TYPE_PLAYERNAME = 0x3,
HE_TYPE_MAPNAME = 0x4,
HE_TYPE_GAMETYPE = 0x5,
HE_TYPE_MATERIAL = 0x6,
HE_TYPE_TIMER_DOWN = 0x7,
HE_TYPE_TIMER_UP = 0x8,
HE_TYPE_TIMER_STATIC = 0x9,
HE_TYPE_TENTHS_TIMER_DOWN = 0xA,
HE_TYPE_TENTHS_TIMER_UP = 0xB,
HE_TYPE_TENTHS_TIMER_STATIC = 0xC,
HE_TYPE_CLOCK_DOWN = 0xD,
HE_TYPE_CLOCK_UP = 0xE,
HE_TYPE_WAYPOINT = 0xF,
HE_TYPE_COUNT = 0x10,
};
struct hud_color
{
char r;
char g;
char b;
char a;
};
/* 1028 */
union hudelem_color_t
{
hud_color __s0;
int rgba;
};
struct hudelem_s
{
he_type_t type;
float x;
float y;
float z;
int targetEntNum;
float fontScale;
float fromFontScale;
int fontScaleStartTime;
int fontScaleTime;
int font;
int alignOrg;
int alignScreen;
hudelem_color_t color;
hudelem_color_t fromColor;
int fadeStartTime;
int fadeTime;
int label;
int width;
int height;
int materialIndex;
int fromWidth;
int fromHeight;
int scaleStartTime;
int scaleTime;
float fromX;
float fromY;
int fromAlignOrg;
int fromAlignScreen;
int moveStartTime;
int moveTime;
int time;
int duration;
float value;
int text;
float sort;
hudelem_color_t glowColor;
int fxBirthTime;
int fxLetterTime;
int fxDecayStartTime;
int fxDecayDuration;
int soundID;
int flags;
};
struct $3EB5F037EADAEE8E2FA2A1F9FFF31312
{
hudelem_s current[31];
hudelem_s archival[31];
};
struct playerState_s
{
int commandTime;
int pm_type;
int pm_time;
int pm_flags;
int otherFlags;
int linkFlags;
int bobCycle;
float origin[3];
float velocity[3];
int grenadeTimeLeft;
int throwbackGrenadeOwner;
int throwbackGrenadeTimeLeft;
unsigned int throwbackWeaponIndex;
int remoteEyesEnt;
int remoteEyesTagname;
int remoteControlEnt;
int foliageSoundTime;
int gravity;
float leanf;
int speed;
float delta_angles[3];
int groundEntityNum;
float vLadderVec[3];
int jumpTime;
float jumpOriginZ;
int legsTimer;
int legsAnim;
int torsoTimer;
int torsoAnim;
int legsAnimDuration;
int torsoAnimDuration;
int damageTimer;
int damageDuration;
int flinchYawAnim;
int corpseIndex;
int movementDir;
int eFlags;
int eventSequence;
int events[4];
unsigned int eventParms[4];
int oldEventSequence;
int unpredictableEventSequence;
int unpredictableEventSequenceOld;
int unpredictableEvents[4];
unsigned int unpredictableEventParms[4];
int clientNum;
int viewmodelIndex;
float viewangles[3];
int viewHeightTarget;
float viewHeightCurrent;
int viewHeightLerpTime;
int viewHeightLerpTarget;
int viewHeightLerpDown;
float viewAngleClampBase[2];
float viewAngleClampRange[2];
int damageEvent;
int damageYaw;
int damagePitch;
int damageCount;
int damageFlags;
int stats[4];
float proneDirection;
float proneDirectionPitch;
float proneTorsoPitch;
ViewLockTypes viewlocked;
int viewlocked_entNum;
float linkAngles[3];
float linkWeaponAngles[3];
int linkWeaponEnt;
int loopSound;
int cursorHint;
int cursorHintString;
int cursorHintEntIndex;
int cursorHintDualWield;
int iCompassPlayerInfo;
int radarEnabled;
int radarBlocked;
int radarMode;
int locationSelectionInfo;
SprintState sprintState;
float holdBreathScale;
int holdBreathTimer;
float moveSpeedScaleMultiplier;
MantleState mantleState;
PlayerActiveWeaponState weapState[2];
unsigned int weaponsEquipped[15];
PlayerEquippedWeaponState weapEquippedData[15];
PlayerWeaponCommonState weapCommon;
float meleeChargeYaw;
int meleeChargeDist;
int meleeChargeTime;
unsigned int perks[2];
unsigned int perkSlots[8];
ActionSlotType actionSlotType[4];
ActionSlotParam actionSlotParam[4];
int weaponHudIconOverrides[6];
int animScriptedType;
int shellshockIndex;
int shellshockTime;
int shellshockDuration;
float dofNearStart;
float dofNearEnd;
float dofFarStart;
float dofFarEnd;
float dofNearBlur;
float dofFarBlur;
float dofViewmodelStart;
float dofViewmodelEnd;
objective_t objective[32];
int deltaTime;
int killCamEntity;
int killCamLookAtEntity;
int killCamClientNum;
$3EB5F037EADAEE8E2FA2A1F9FFF31312 hud;
unsigned int partBits[6];
int recoilScale;
int diveDirection;
int stunTime;
};
struct clSnapshot_t
{
playerState_s ps;
int valid;
int snapFlags;
int serverTime;
int messageNum;
int deltaNum;
int ping;
int cmdNum;
int numEntities;
int numClients;
int parseEntitiesIndex;
int parseClientsIndex;
int serverCommandNum;
};
enum StanceState
{
CL_STANCE_STAND = 0x0,
CL_STANCE_CROUCH = 0x1,
CL_STANCE_PRONE = 0x2,
};
struct ClientArchiveData
{
int serverTime;
float origin[3];
float velocity[3];
int bobCycle;
int movementDir;
float viewangles[3];
int locationSelectionInfo;
float selectedLocation[2];
float selectedLocationAngle;
};
struct outPacket_t
{
int p_cmdNumber;
int p_serverTime;
int p_realtime;
};
enum team_t
{
TEAM_FREE = 0x0,
TEAM_AXIS = 0x1,
TEAM_ALLIES = 0x2,
TEAM_SPECTATOR = 0x3,
TEAM_NUM_TEAMS = 0x4,
};
struct clientState_s
{
int clientIndex;
team_t team;
int modelindex;
int dualWielding;
int riotShieldNext;
int attachModelIndex[6];
int attachTagIndex[6];
char name[16];
float maxSprintTimeMultiplier;
int rank;
int prestige;
unsigned int perks[2];
int diveState;
int voiceConnectivityBits;
unsigned int playerCardIcon;
unsigned int playerCardTitle;
unsigned int playerCardNameplate;
};
#pragma pack(push, 4)
struct usercmd_s
{
int serverTime;
int buttons;
int angles[3];
unsigned __int16 weapon;
unsigned __int16 primaryWeaponForAltMode;
unsigned __int16 offHandIndex;
char forwardmove;
char rightmove;
float meleeChargeYaw;
char meleeChargeDist;
char selectedLoc[2];
char selectedLocAngle;
char remoteControlAngles[2];
};
#pragma pack(pop)
struct LerpEntityState
{
char pad[0x70];
};
struct clientLinkInfo_t
{
__int16 parentId;
char tagName;
char flags;
};
struct entityState_s
{
int number;
int eType;
LerpEntityState lerp;
int time2;
int otherEntityNum;
int attackerEntityNum;
int groundEntityNum;
int loopSound;
int surfType;
union
{
int brushModel;
int triggerModel;
int item;
int xmodel;
int primaryLight;
} index;
int clientNum;
int iHeadIcon;
int iHeadIconTeam;
int solid;
unsigned int eventParm;
int eventSequence;
int events[4];
unsigned int eventParms[4];
unsigned __int16 weapon;
int legsAnim;
int torsoAnim;
int un1;
int un2;
clientLinkInfo_t clientLinkInfo;
unsigned int partBits[6];
int clientMask[1];
};
struct clientActive_t
{
bool usingAds;
int timeoutcount;
clSnapshot_t snap;
bool alwaysFalse;
int serverTime;
int oldServerTime;
int oldFrameServerTime;
int serverTimeDelta;
int oldSnapServerTime;
int extrapolatedSnapshot;
int newSnapshots;
int serverId;
char mapname[64];
int parseEntitiesIndex;
int parseClientsIndex;
int mouseDx[2];
int mouseDy[2];
int mouseIndex;
bool stanceHeld;
StanceState stance;
StanceState stancePosition;
int stanceTime;
int cgameUserCmdWeapon;
int cgameUserCmdOffHandIndex;
float cgameFOVSensitivityScale;
float cgameMaxPitchSpeed;
float cgameMaxYawSpeed;
float cgameKickAngles[3];
float cgameOrigin[3];
float cgameVelocity[3];
float cgameViewangles[3];
int cgameBobCycle;
int cgameMovementDir;
int cgameExtraButtons;
int cgamePredictedDataServerTime;
float clViewangles[3];
usercmd_s cmds[128];
int cmdNumber;
ClientArchiveData clientArchive[256];
int clientArchiveIndex;
int packetBackupCount;
int packetBackupMask;
int parseEntitiesCount;
int parseClientsCount;
outPacket_t outPackets[32];
clSnapshot_t snapshots[32];
entityState_s parseEntities[19200];
clientState_s parseClients[576];
int corruptedTranslationFile;
char translationVersion[256];
};
struct MaterialTechnique
{
const char *name;
@ -2822,18 +3378,6 @@ namespace Game
WEAPON_FIRETYPE_BURSTFIRE_FIRST = 0x2,
WEAPON_FIRETYPE_BURSTFIRE_LAST = 0x4,
};
enum OffhandClass
{
OFFHAND_CLASS_NONE = 0x0,
OFFHAND_CLASS_FRAG_GRENADE = 0x1,
OFFHAND_CLASS_SMOKE_GRENADE = 0x2,
OFFHAND_CLASS_FLASH_GRENADE = 0x3,
OFFHAND_CLASS_THROWINGKNIFE = 0x4,
OFFHAND_CLASS_OTHER = 0x5,
OFFHAND_CLASS_COUNT = 0x6,
};
enum weapStance_t
{
WEAPSTANCE_STAND = 0x0,
@ -4082,25 +4626,6 @@ namespace Game
};
#pragma pack(pop)
#pragma pack(push, 4)
struct usercmd_s
{
int serverTime;
int buttons;
int angles[3];
unsigned __int16 weapon;
unsigned __int16 primaryWeaponForAltMode;
unsigned __int16 offHandIndex;
char forwardmove;
char rightmove;
float meleeChargeYaw;
char meleeChargeDist;
char selectedLoc[2];
char selectedLocAngle;
char remoteControlAngles[2];
};
#pragma pack(pop)
typedef char mapname_t[40];
struct traceWork_t
@ -4580,57 +5105,6 @@ namespace Game
char pad3[724];
} gclient_t;
struct LerpEntityState
{
char pad[0x70];
};
struct clientLinkInfo_t
{
__int16 parentId;
char tagName;
char flags;
};
struct entityState_s
{
int number;
int eType;
LerpEntityState lerp;
int time2;
int otherEntityNum;
int attackerEntityNum;
int groundEntityNum;
int loopSound;
int surfType;
union
{
int brushModel;
int triggerModel;
int item;
int xmodel;
int primaryLight;
} index;
int clientNum;
int iHeadIcon;
int iHeadIconTeam;
int solid;
unsigned int eventParm;
int eventSequence;
int events[4];
unsigned int eventParms[4];
unsigned __int16 weapon;
int legsAnim;
int torsoAnim;
int un1;
int un2;
clientLinkInfo_t clientLinkInfo;
unsigned int partBits[6];
int clientMask[1];
};
struct EntHandle
{
unsigned __int16 number;