From f0d839b38fbbdb8575154a35dabb766b9915d1a8 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 26 Aug 2020 10:01:48 +0100 Subject: [PATCH] two handed pistol stabilisation Draw iron sight lock mode as mono --- Projects/Android/jni/RTCWVR/VrClientInfo.h | 7 ++- Projects/Android/jni/RTCWVR/VrInput.h | 1 + Projects/Android/jni/RTCWVR/VrInputCommon.c | 8 +-- Projects/Android/jni/RTCWVR/VrInputDefault.c | 50 +++++++++++-------- .../Android/jni/RTCWVR/VrInputWeaponAlign.c | 8 +-- Projects/Android/jni/rtcw/src/cgame/cg_draw.c | 4 +- .../Android/jni/rtcw/src/cgame/cg_weapons.c | 27 +++++++--- Projects/Android/jni/rtcw/src/game/bg_misc.c | 10 ++-- Projects/Android/jni/rtcw/src/game/g_weapon.c | 11 ++-- 9 files changed, 79 insertions(+), 47 deletions(-) diff --git a/Projects/Android/jni/RTCWVR/VrClientInfo.h b/Projects/Android/jni/RTCWVR/VrClientInfo.h index 606f474..d4ac2b7 100644 --- a/Projects/Android/jni/RTCWVR/VrClientInfo.h +++ b/Projects/Android/jni/RTCWVR/VrClientInfo.h @@ -29,11 +29,14 @@ typedef struct { vec3_t weaponangles_last; // Don't use this, it is just for calculating delta! vec3_t weaponangles_delta; - vec3_t weaponoffset; - float weaponoffset_timestamp; + vec3_t current_weaponoffset; + vec3_t calculated_weaponoffset; + float current_weaponoffset_timestamp; vec3_t weaponoffset_history[NUM_WEAPON_SAMPLES]; float weaponoffset_history_timestamp[NUM_WEAPON_SAMPLES]; + qboolean pistol; // True if the weapon is a pistol + //Lots of scope weapon stuff qboolean scopeengaged; // Scope has been engaged on a scoped weapon qboolean scopedweapon; // Weapon scope is available diff --git a/Projects/Android/jni/RTCWVR/VrInput.h b/Projects/Android/jni/RTCWVR/VrInput.h index cfd50f9..aab36c0 100644 --- a/Projects/Android/jni/RTCWVR/VrInput.h +++ b/Projects/Android/jni/RTCWVR/VrInput.h @@ -7,6 +7,7 @@ //New control scheme definitions to be defined L1VR_SurfaceView.c enumeration enum control_scheme; +#define STABILISATION_DISTANCE 0.5 #define SCOPE_ENGAGE_DISTANCE 0.25 #define VSTOCK_ENGAGE_DISTANCE 0.25 #define BINOCULAR_ENGAGE_DISTANCE 0.25 diff --git a/Projects/Android/jni/RTCWVR/VrInputCommon.c b/Projects/Android/jni/RTCWVR/VrInputCommon.c index cb93ea5..be70ebe 100644 --- a/Projects/Android/jni/RTCWVR/VrInputCommon.c +++ b/Projects/Android/jni/RTCWVR/VrInputCommon.c @@ -134,14 +134,14 @@ void updateScopeAngles() if (vr.vstock_engaged) { //Copy weapon offset X - vr.weaponoffset[0] = vr.vstock_weapon_offset[1]; - vr.weaponoffset[1] = vr.vstock_weapon_offset[2]; - vr.weaponoffset[2] = vr.vstock_weapon_offset[0]; + vr.calculated_weaponoffset[0] = vr.vstock_weapon_offset[1]; + vr.calculated_weaponoffset[1] = vr.vstock_weapon_offset[2]; + vr.calculated_weaponoffset[2] = vr.vstock_weapon_offset[0]; } else { //Clear weapon offset - VectorSet(vr.weaponoffset, 0, 0, 0); + VectorSet(vr.calculated_weaponoffset, 0, 0, 0); } VectorSet(currentScopeAngles, vr.weaponangles[PITCH], vr.weaponangles[YAW], vr.hmdorientation[ROLL]); diff --git a/Projects/Android/jni/RTCWVR/VrInputDefault.c b/Projects/Android/jni/RTCWVR/VrInputDefault.c index ca6599b..6c6715e 100644 --- a/Projects/Android/jni/RTCWVR/VrInputDefault.c +++ b/Projects/Android/jni/RTCWVR/VrInputDefault.c @@ -166,21 +166,20 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, powf(vr.hmdposition[2] - pWeapon->HeadPose.Pose.Position.z, 2)); //Turn on weapon stabilisation? - if ((pOffTrackedRemoteNew->Buttons & ovrButton_GripTrigger) != - (pOffTrackedRemoteOld->Buttons & ovrButton_GripTrigger)) { - - if (pOffTrackedRemoteNew->Buttons & ovrButton_GripTrigger) + qboolean stabilised = qfalse; + if (vr.pistol) + { + //For pistols, it is simply a case of holding the two controllers close together + if (distance < (STABILISATION_DISTANCE / 2.0f)) { - if (distance < 0.50f) - { - vr.weapon_stabilised = qtrue; - } - } - else - { - vr.weapon_stabilised = qfalse; + stabilised = qtrue; } } + else if ((pOffTrackedRemoteNew->Buttons & ovrButton_GripTrigger) && (distance < STABILISATION_DISTANCE)) + { + stabilised = qtrue; + } + vr.weapon_stabilised = stabilised; //Engage scope / virtual stock if conditions are right qboolean scopeready = vr.weapon_stabilised && (distanceToHMD < SCOPE_ENGAGE_DISTANCE); @@ -239,14 +238,17 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, VectorCopy(vr.weaponoffset_history[i-1], vr.weaponoffset_history[i]); vr.weaponoffset_history_timestamp[i] = vr.weaponoffset_history_timestamp[i-1]; } - VectorCopy(vr.weaponoffset, vr.weaponoffset_history[0]); - vr.weaponoffset_history_timestamp[0] = vr.weaponoffset_timestamp; + VectorCopy(vr.current_weaponoffset, vr.weaponoffset_history[0]); + vr.weaponoffset_history_timestamp[0] = vr.current_weaponoffset_timestamp; ///Weapon location relative to view - vr.weaponoffset[0] = pWeapon->HeadPose.Pose.Position.x - vr.hmdposition[0]; - vr.weaponoffset[1] = pWeapon->HeadPose.Pose.Position.y - vr.hmdposition[1]; - vr.weaponoffset[2] = pWeapon->HeadPose.Pose.Position.z - vr.hmdposition[2]; - vr.weaponoffset_timestamp = Sys_Milliseconds( ); + vr.current_weaponoffset[0] = pWeapon->HeadPose.Pose.Position.x - vr.hmdposition[0]; + vr.current_weaponoffset[1] = pWeapon->HeadPose.Pose.Position.y - vr.hmdposition[1]; + vr.current_weaponoffset[2] = pWeapon->HeadPose.Pose.Position.z - vr.hmdposition[2]; + vr.current_weaponoffset_timestamp = Sys_Milliseconds( ); + + //Lerp (stabilises pistol) - Won't have any effect on any other weapons + VectorLerp(vr.weaponoffset_history[1], (vr.pistol && vr.weapon_stabilised) ? 0.25f : 1.0f, vr.current_weaponoffset, vr.calculated_weaponoffset); //Does weapon velocity trigger attack (knife) and is it fast enough static qboolean velocityTriggeredAttack = false; @@ -273,12 +275,13 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, sendButtonAction("+attack", velocityTriggeredAttack); } - if (vr.weapon_stabilised || vr.dualwield) + //Don't do this for pistols + if (!vr.pistol && (vr.weapon_stabilised || vr.dualwield)) { if (vr.scopeengaged || vr.vstock_engaged) { float x = pOff->HeadPose.Pose.Position.x - vr.hmdposition[0]; - float y = pOff->HeadPose.Pose.Position.y - vr.hmdposition[1]; + float y = pOff->HeadPose.Pose.Position.y - (vr.hmdposition[1] - 0.1f); // Use a point lower float z = pOff->HeadPose.Pose.Position.z - vr.hmdposition[2]; float zxDist = length(x, z); @@ -301,11 +304,16 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, else { VectorSet(vr.weaponangles, -degrees(atanf(y / zxDist)), - -degrees(atan2f(x, -z)), vr.weaponangles[ROLL]); + -degrees(atan2f(x, -z)), vr.weaponangles[ROLL] / 2.0f); //Dampen roll on stabilised weapon } } } } + else if (vr.pistol && vr.weapon_stabilised) + { + //No roll if pistol is being stabilised with off-hand + vr.weaponangles[ROLL] = 0; + } static bool finishReloadNextFrame = false; if (finishReloadNextFrame) diff --git a/Projects/Android/jni/RTCWVR/VrInputWeaponAlign.c b/Projects/Android/jni/RTCWVR/VrInputWeaponAlign.c index cdfd1c3..f552edb 100644 --- a/Projects/Android/jni/RTCWVR/VrInputWeaponAlign.c +++ b/Projects/Android/jni/RTCWVR/VrInputWeaponAlign.c @@ -81,10 +81,10 @@ void HandleInput_WeaponAlign( ovrInputStateTrackedRemote *pDominantTrackedRemote //dominant hand stuff first { ///Weapon location relative to view - vr.weaponoffset[0] = pDominantTracking->HeadPose.Pose.Position.x - vr.hmdposition[0]; - vr.weaponoffset[1] = pDominantTracking->HeadPose.Pose.Position.y - vr.hmdposition[1]; - vr.weaponoffset[2] = pDominantTracking->HeadPose.Pose.Position.z - vr.hmdposition[2]; - vr.weaponoffset_timestamp = Sys_Milliseconds( ); + vr.current_weaponoffset[0] = pDominantTracking->HeadPose.Pose.Position.x - vr.hmdposition[0]; + vr.current_weaponoffset[1] = pDominantTracking->HeadPose.Pose.Position.y - vr.hmdposition[1]; + vr.current_weaponoffset[2] = pDominantTracking->HeadPose.Pose.Position.z - vr.hmdposition[2]; + vr.current_weaponoffset_timestamp = Sys_Milliseconds( ); } float controllerYawHeading = 0.0f; diff --git a/Projects/Android/jni/rtcw/src/cgame/cg_draw.c b/Projects/Android/jni/rtcw/src/cgame/cg_draw.c index 889abef..6767d37 100644 --- a/Projects/Android/jni/rtcw/src/cgame/cg_draw.c +++ b/Projects/Android/jni/rtcw/src/cgame/cg_draw.c @@ -3681,9 +3681,11 @@ void CG_DrawActive( int stereoView ) { // offset vieworg appropriately if we're doing stereo separation VectorCopy( cg.refdef.vieworg, baseOrg ); + int vStock = trap_Cvar_VariableIntegerValue("vr_virtual_stock"); int vr_cinematic_stereo = trap_Cvar_VariableIntegerValue( "vr_cinematic_stereo"); if ( !cgVR->scopeengaged && - (!cg.cameraMode || (cg.cameraMode && vr_cinematic_stereo))) { + (!cg.cameraMode || (cg.cameraMode && vr_cinematic_stereo)) && + !cgVR->vstock_engaged) { VectorMA( cg.refdef.vieworg, -separation, cg.refdef.viewaxis[1], cg.refdef.vieworg ); } diff --git a/Projects/Android/jni/rtcw/src/cgame/cg_weapons.c b/Projects/Android/jni/rtcw/src/cgame/cg_weapons.c index 14d4317..54a66ea 100644 --- a/Projects/Android/jni/rtcw/src/cgame/cg_weapons.c +++ b/Projects/Android/jni/rtcw/src/cgame/cg_weapons.c @@ -276,26 +276,26 @@ int weapBanksMultiPlayer[MAX_WEAP_BANKS_MP][MAX_WEAPS_IN_BANK_MP] = { //These are in real world units (metres) float virtualStockOffsets[WP_SILENCER][3] = { - //Right Up Forward + //Yaw Adjust Up Forward {0, 0, 0} ,//WP_NONE, {0, 0, 0} ,//WP_KNIFE, {0, 0, 0} ,//WP_LUGER, {0, 0, 0} ,//WP_MP40, - {0.03f, -0.08f, -0.35f} ,//WP_MAUSER, - {0.03f, -0.12f, -0.25f} ,//WP_FG42, + {0, -0.08f, -0.35f} ,//WP_MAUSER, + {0.4f, -0.12f, -0.25f} ,//WP_FG42, - needs a slight yaw tweak {0, 0, 0} ,//WP_GRENADE_LAUNCHER, {0, 0, 0} ,//WP_PANZERFAUST, {0, 0, 0} ,//WP_VENOM, {0, 0, 0} ,//WP_FLAMETHROWER, {0, 0, 0} ,//WP_TESLA, {0, 0, 0} ,//WP_COLT, - {0.03f, -0.108f, -0.3f} ,//WP_THOMPSON, + {0, -0.108f, -0.3f} ,//WP_THOMPSON, {0, 0, 0} ,//WP_GARAND, {0, 0, 0} ,//WP_GRENADE_PINEAPPLE, {0, 0, 0} ,//WP_SNIPERRIFLE, {0, 0, 0} ,//WP_SNOOPERSCOPE, {0, 0, 0} ,//WP_FG42SCOPE, - {0.0325f, -0.06f, -0.24f}//WP_STEN, + {0, -0.06f, -0.24f}//WP_STEN, }; /* @@ -2003,7 +2003,7 @@ void CG_CalculateVRWeaponPosition( int weaponNum, vec3_t origin, vec3_t angles ) if (weaponNum != WP_AKIMBO || BG_AkimboFireSequence(weaponNum, cg.predictedPlayerState.ammoclip[WP_AKIMBO], cg.predictedPlayerState.ammoclip[WP_COLT] )) { - convertFromVR(cgVR->weaponoffset, cg.refdef.vieworg, origin); + convertFromVR(cgVR->calculated_weaponoffset, cg.refdef.vieworg, origin); } else{ convertFromVR(cgVR->offhandoffset, cg.refdef.vieworg, origin); } @@ -2091,6 +2091,10 @@ static float CG_CalculateWeaponPositionAndScale( playerState_t *ps, vec3_t origi &(adjust[PITCH]), &(adjust[YAW]), &(adjust[ROLL])); VectorScale(temp_offset, scale, offset); + if (cgVR->vstock_engaged) { + adjust[YAW] += virtualStockOffsets[ps->weapon][0]; + } + if (!cgVR->right_handed) { //yaw needs to go in the other direction as left handed model is reversed @@ -3657,12 +3661,21 @@ void CG_AddViewWeapon( playerState_t *ps ) { //Set some important flags based on the current weapon cgVR->mountedgun = qfalse; + cgVR->pistol = qfalse; switch ( ps->weapon ) { case WP_KNIFE: cgVR->velocitytriggered = qtrue; cgVR->scopedweapon = qfalse; cgVR->vstock_weapon = qfalse; break; + case WP_LUGER: + case WP_SILENCER: + case WP_COLT: + cgVR->velocitytriggered = qfalse; + cgVR->scopedweapon = qfalse; + cgVR->vstock_weapon = qfalse; + cgVR->pistol = qtrue; + break; case WP_FG42: case WP_MAUSER: cgVR->velocitytriggered = qfalse; @@ -3707,7 +3720,7 @@ void CG_AddViewWeapon( playerState_t *ps ) { vec3_t forward, right, up; AngleVectors(orientation, forward, right, up); - VectorMA(offset, virtualStockOffsets[ps->weapon][0] * multiplier, right, offset); + //VectorMA(offset, (cg_stereoSeparation.value / 2.0f) * multiplier, right, offset); VectorMA(offset, virtualStockOffsets[ps->weapon][1], up, offset); VectorMA(offset, virtualStockOffsets[ps->weapon][2], forward, offset); diff --git a/Projects/Android/jni/rtcw/src/game/bg_misc.c b/Projects/Android/jni/rtcw/src/game/bg_misc.c index 3e978e1..e59611b 100644 --- a/Projects/Android/jni/rtcw/src/game/bg_misc.c +++ b/Projects/Android/jni/rtcw/src/game/bg_misc.c @@ -59,7 +59,7 @@ extern vmCvar_t g_gametype; // these defines are matched with the character torso animations #define DELAY_LOW 100 // machineguns, tesla, spear, flame #define DELAY_HIGH 100 // mauser, garand -#define DELAY_PISTOL 100 // colt, luger, sp5, cross +#define DELAY_PISTOL 75 // colt, luger, sp5, cross #define DELAY_SHOULDER 50 // rl #define DELAY_THROW 250 // grenades, dynamite #define DELAY_THROW_VR 15 // grenades, dynamite @@ -92,7 +92,7 @@ ammotable_t ammoTable[] = { { 999, 0, 999, 0, 50, 200, 0, 0, MOD_KNIFE }, // WP_KNIFE // 1 - { MAX_AMMO_9MM, 1, 8, 1500, DELAY_PISTOL, 400, 0, 0, MOD_LUGER }, // WP_LUGER // 2 // NOTE: also 32 round 'snail' magazine + { MAX_AMMO_9MM, 1, 8, 1500, DELAY_PISTOL, 250, 0, 0, MOD_LUGER }, // WP_LUGER // 2 // NOTE: also 32 round 'snail' magazine { MAX_AMMO_9MM, 1, 32, 2600, DELAY_LOW, 100, 0, 0, MOD_MP40 }, // WP_MP40 // 3 { MAX_AMMO_MAUSER,1, 10, 2500, DELAY_HIGH, 1200, 0, 0, MOD_MAUSER }, // WP_MAUSER // 4 // NOTE: authentic clips are 5/10/25 rounds { MAX_AMMO_FG42, 1, 20, 2000, DELAY_LOW, 200, 0, 0, MOD_FG42 }, // WP_FG42 // 5 @@ -105,7 +105,7 @@ ammotable_t ammoTable[] = { // { 50, 1, 50, 1000, DELAY_LOW, 1200, 0, 0, MOD_SPEARGUN }, // WP_SPEARGUN // 11 // { 999, 0, 999, 0, 50, 200, 0, 0, MOD_KNIFE2 }, // WP_KNIFE2 // 12 - { MAX_AMMO_45, 1, 8, 1500, DELAY_PISTOL, 400, 0, 0, MOD_COLT }, // WP_COLT // 13 + { MAX_AMMO_45, 1, 8, 1500, DELAY_PISTOL, 250, 0, 0, MOD_COLT }, // WP_COLT // 13 { MAX_AMMO_45, 1, 30, 2400, DELAY_LOW, 120, 0, 0, MOD_THOMPSON }, // WP_THOMPSON // 14 // NOTE: also 50 round drum magazine { MAX_AMMO_GARAND,1, 5, 2500, DELAY_HIGH, 1200, 0, 0, MOD_GARAND }, // WP_GARAND // 15 // NOTE: always 5 round clips // { MAX_AMMO_BAR, 1, 20, 2000, DELAY_LOW, 200, 0, 0, MOD_BAR }, // WP_BAR // 16 @@ -121,8 +121,8 @@ ammotable_t ammoTable[] = { { MAX_AMMO_FG42, 1, 20, 2000, DELAY_LOW, 200, 0, 0, MOD_FG42SCOPE }, // WP_FG42SCOPE // 23 // { MAX_AMMO_BAR, 1, 20, 2000, DELAY_LOW, 90, 0, 0, MOD_BAR }, // WP_BAR2 // 24 { MAX_AMMO_9MM, 1, 32, 3100, DELAY_LOW, 110, 700, 300, MOD_STEN }, // WP_STEN // 25 - { MAX_AMMO_9MM, 1, 8, 1500, DELAY_PISTOL, 400, 0, 0, MOD_SILENCER }, // WP_SILENCER // 26 - { MAX_AMMO_45, 1, 8, 2700, DELAY_PISTOL, 200, 0, 0, MOD_AKIMBO }, // WP_AKIMBO // 27 + { MAX_AMMO_9MM, 1, 8, 1500, DELAY_PISTOL, 250, 0, 0, MOD_SILENCER }, // WP_SILENCER // 26 + { MAX_AMMO_45, 1, 8, 2700, DELAY_PISTOL, 125, 0, 0, MOD_AKIMBO }, // WP_AKIMBO // 27 { 999, 0, 999, 0, 50, 0, 0, 0, 0 }, // WP_CLASS_SPECIAL // 28 // class_special // { 100, 1, 100, 1000, DELAY_PISTOL, 900, 0, 0, MOD_CROSS }, // WP_CROSS // 29 diff --git a/Projects/Android/jni/rtcw/src/game/g_weapon.c b/Projects/Android/jni/rtcw/src/game/g_weapon.c index 58a6283..36ceae8 100644 --- a/Projects/Android/jni/rtcw/src/game/g_weapon.c +++ b/Projects/Android/jni/rtcw/src/game/g_weapon.c @@ -1744,7 +1744,7 @@ void CalcMuzzlePoint( gentity_t *ent, int weapon, vec3_t forward, vec3_t right, float worldscale = trap_Cvar_VariableIntegerValue("cg_worldScale"); float heightAdjust = 0; trap_Cvar_VariableValue("cg_heightAdjust", &heightAdjust); - convertFromVR(worldscale, ent, gVR->weaponoffset, ent->r.currentOrigin, muzzlePoint); + convertFromVR(worldscale, ent, gVR->calculated_weaponoffset, ent->r.currentOrigin, muzzlePoint); muzzlePoint[2] += (ent->client->ps.viewheight - 64); muzzlePoint[2] += (gVR->hmdposition[1] + heightAdjust) * worldscale; return; @@ -1805,7 +1805,7 @@ void CalcMuzzlePointForActivate( gentity_t *ent, vec3_t forward, vec3_t right, v float worldscale = trap_Cvar_VariableIntegerValue("cg_worldScale"); float heightAdjust = 0; trap_Cvar_VariableValue("cg_heightAdjust", &heightAdjust); - convertFromVR(worldscale, ent, gVR->weaponoffset, ent->r.currentOrigin, muzzlePoint); + convertFromVR(worldscale, ent, gVR->calculated_weaponoffset, ent->r.currentOrigin, muzzlePoint); muzzlePoint[2] += (ent->client->ps.viewheight - 64); muzzlePoint[2] += (gVR->hmdposition[1] + heightAdjust) * worldscale; return; @@ -1934,8 +1934,13 @@ void FireWeapon( gentity_t *ent ) { { //Stabilised weapon is even more accurate aimSpreadScale /= 3.0f; - } + if (gVR->pistol) + { + //Stabilised pistol is even more accurate + aimSpreadScale /= 2.0f; + } + } // fire the specific weapon switch ( ent->s.weapon ) {