From 0c9d6d3e861075411d20a186167384f251b757eb Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 12 Oct 2022 18:00:26 +0100 Subject: [PATCH] Item Selector and a number of other changes: - Scrolling text on main menu for patron credits - Off-hand force powers using trigger - vr_weapon_velocity_trigger - cvar controls speed for velocity triggered weapons - walk direction is hmd based --- .../Android/jni/JKVR/JKVR_SurfaceView.cpp | 3 +- Projects/Android/jni/JKVR/VrClientInfo.h | 4 + Projects/Android/jni/JKVR/VrCvars.h | 1 + Projects/Android/jni/JKVR/VrInputCommon.cpp | 1 + Projects/Android/jni/JKVR/VrInputDefault.cpp | 930 +++++++++--------- .../Android/jni/OpenJK/code/client/cl_cin.cpp | 70 ++ .../jni/OpenJK/code/client/cl_scrn.cpp | 8 +- .../Android/jni/OpenJK/code/game/bg_local.h | 1 + .../Android/jni/OpenJK/code/game/bg_misc.cpp | 2 +- .../Android/jni/OpenJK/code/game/weapons.h | 3 - .../OpenJK/codeJK2/cgame/cg_consolecmds.cpp | 7 + .../jni/OpenJK/codeJK2/cgame/cg_draw.cpp | 4 +- .../jni/OpenJK/codeJK2/cgame/cg_local.h | 9 + .../jni/OpenJK/codeJK2/cgame/cg_main.cpp | 6 +- .../jni/OpenJK/codeJK2/cgame/cg_players.cpp | 120 ++- .../jni/OpenJK/codeJK2/cgame/cg_view.cpp | 74 +- .../jni/OpenJK/codeJK2/cgame/cg_weapons.cpp | 293 +++++- .../jni/OpenJK/codeJK2/game/bg_local.h | 1 + .../jni/OpenJK/codeJK2/game/bg_misc.cpp | 2 +- .../Android/jni/OpenJK/codeJK2/game/weapons.h | 3 - .../jni/OpenJK/codeJK2/game/wp_saber.cpp | 44 +- 21 files changed, 1027 insertions(+), 559 deletions(-) diff --git a/Projects/Android/jni/JKVR/JKVR_SurfaceView.cpp b/Projects/Android/jni/JKVR/JKVR_SurfaceView.cpp index b6e6491..4b33ea0 100644 --- a/Projects/Android/jni/JKVR/JKVR_SurfaceView.cpp +++ b/Projects/Android/jni/JKVR/JKVR_SurfaceView.cpp @@ -1268,7 +1268,7 @@ void JKVR_Init() vr_turn_mode = Cvar_Get( "vr_turn_mode", "0", CVAR_ARCHIVE); // 0 = snap, 1 = smooth vr_turn_angle = Cvar_Get( "vr_turn_angle", "45", CVAR_ARCHIVE); vr_positional_factor = Cvar_Get( "vr_positional_factor", "12", CVAR_ARCHIVE); - vr_walkdirection = Cvar_Get( "vr_walkdirection", "0", CVAR_ARCHIVE); + vr_walkdirection = Cvar_Get( "vr_walkdirection", "1", CVAR_ARCHIVE); vr_movement_multiplier = Cvar_Get( "vr_movement_multiplier", "0.8", CVAR_ARCHIVE); vr_weapon_pitchadjust = Cvar_Get( "vr_weapon_pitchadjust", "-20.0", CVAR_ARCHIVE); vr_virtual_stock = Cvar_Get( "vr_virtual_stock", "0", CVAR_ARCHIVE); @@ -1279,6 +1279,7 @@ void JKVR_Init() vr_immersive_cinematics = Cvar_Get("vr_immersive_cinematics", "0", CVAR_ARCHIVE); vr_screen_dist = Cvar_Get( "vr_screen_dist", "2.5", CVAR_ARCHIVE); + vr_weapon_velocity_trigger = Cvar_Get( "vr_weapon_velocity_trigger", "1.6", CVAR_ARCHIVE); } diff --git a/Projects/Android/jni/JKVR/VrClientInfo.h b/Projects/Android/jni/JKVR/VrClientInfo.h index a2871dd..b76e76b 100644 --- a/Projects/Android/jni/JKVR/VrClientInfo.h +++ b/Projects/Android/jni/JKVR/VrClientInfo.h @@ -37,6 +37,8 @@ typedef struct { vec3_t weaponoffset_history[NUM_WEAPON_SAMPLES]; float weaponoffset_history_timestamp[NUM_WEAPON_SAMPLES]; + bool item_selector; + bool pistol; // True if the weapon is a pistol //Lots of scope weapon stuff @@ -49,7 +51,9 @@ typedef struct { bool velocitytriggered; float primaryswingvelocity; + bool primaryVelocityTriggeredAttack; float secondaryswingvelocity; + bool secondaryVelocityTriggeredAttack; vec3_t offhandangles; vec3_t offhandangles_last; // Don't use this, it is just for calculating delta! diff --git a/Projects/Android/jni/JKVR/VrCvars.h b/Projects/Android/jni/JKVR/VrCvars.h index 79f2ae1..a1a2eaa 100644 --- a/Projects/Android/jni/JKVR/VrCvars.h +++ b/Projects/Android/jni/JKVR/VrCvars.h @@ -9,4 +9,5 @@ extern cvar_t *vr_virtual_stock; extern cvar_t *vr_switch_sticks; extern cvar_t *vr_immersive_cinematics; extern cvar_t *vr_screen_dist; +extern cvar_t *vr_weapon_velocity_trigger; diff --git a/Projects/Android/jni/JKVR/VrInputCommon.cpp b/Projects/Android/jni/JKVR/VrInputCommon.cpp index 3eb8e35..57a38fe 100644 --- a/Projects/Android/jni/JKVR/VrInputCommon.cpp +++ b/Projects/Android/jni/JKVR/VrInputCommon.cpp @@ -29,6 +29,7 @@ cvar_t *vr_virtual_stock; cvar_t *vr_switch_sticks; cvar_t *vr_immersive_cinematics; cvar_t *vr_screen_dist; +cvar_t *vr_weapon_velocity_trigger; ovrInputStateTrackedRemote leftTrackedRemoteState_old; ovrInputStateTrackedRemote leftTrackedRemoteState_new; diff --git a/Projects/Android/jni/JKVR/VrInputDefault.cpp b/Projects/Android/jni/JKVR/VrInputDefault.cpp index 5824466..daa32e4 100644 --- a/Projects/Android/jni/JKVR/VrInputDefault.cpp +++ b/Projects/Android/jni/JKVR/VrInputDefault.cpp @@ -156,308 +156,48 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG bool offhandGripPushed = (pOffTrackedRemoteNew->Buttons & ovrButton_GripTrigger); if ( (offhandGripPushed != (pOffTrackedRemoteOld->Buttons & ovrButton_GripTrigger)) && offhandGripPushed && (distance < STABILISATION_DISTANCE)) -#ifndef DEBUG +//#ifndef DEBUG { stabilised = qtrue; } -#else +//#else +// { +// Cvar_Set("vr_control_scheme", "99"); +// } +//#endif + + dominantGripPushed = (pDominantTrackedRemoteNew->Buttons & + ovrButton_GripTrigger) != 0; + bool dominantButton1Pushed = (pDominantTrackedRemoteNew->Buttons & + domButton1) != 0; + bool dominantButton2Pushed = (pDominantTrackedRemoteNew->Buttons & + domButton2) != 0; + + //Do this early so we can suppress other button actions when item selector is up { - Cvar_Set("vr_control_scheme", "99"); - } -#endif - - vr.weapon_stabilised = stabilised; - - //Engage scope / virtual stock if conditions are right - bool scopeready = vr.weapon_stabilised && (distanceToHMD < SCOPE_ENGAGE_DISTANCE); - static bool lastScopeReady = qfalse; - if (scopeready != lastScopeReady) { - if (vr.scopedweapon && !vr.scopedetached) { - if (!vr.scopeengaged && scopeready) { - ALOGV("**WEAPON EVENT** trigger scope mode"); - sendButtonActionSimple("weapalt"); + if (dominantGripPushed) { + if (dominantGripPushTime == 0) { + dominantGripPushTime = GetTimeInMilliSeconds(); } - else if (vr.scopeengaged && !scopeready) { - ALOGV("**WEAPON EVENT** disable scope mode"); - sendButtonActionSimple("weapalt"); + vr.item_selector = true; + } + else + { + dominantGripPushTime = 0; + if (vr.item_selector) + { + sendButtonActionSimple("itemselectorselect"); + vr.item_selector = false; } - lastScopeReady = scopeready; } } - //ALOGV("**GB WEAPON ACTIVE** %i",vr.weaponid); - if(!scopeready && vr.weaponid >= 15 && vr.weaponid <= 17) - { - lastScopeReady = false; - ALOGV("**WEAPON EVENT** disable scope mode forced"); - sendButtonActionSimple("weapalt"); - } - //Engage scope / virtual stock (iron sight lock) if conditions are right - static bool scopeEngaged = qfalse; - if (scopeEngaged != vr.scopeengaged) - { - scopeEngaged = vr.scopeengaged; - } - - //dominant hand stuff first - { - //Record recent weapon position for trajectory based stuff - for (int i = (NUM_WEAPON_SAMPLES-1); i != 0; --i) - { - 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; - - vr.weaponposition[0] = pWeapon->HeadPose.Pose.Position.x; - vr.weaponposition[1] = pWeapon->HeadPose.Pose.Position.y; - vr.weaponposition[2] = pWeapon->HeadPose.Pose.Position.z; - - ///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.primaryswingvelocity = sqrtf(powf(pWeapon->HeadPose.LinearVelocity.x, 2) + - powf(pWeapon->HeadPose.LinearVelocity.y, 2) + - powf(pWeapon->HeadPose.LinearVelocity.z, 2)); - - vr.secondaryswingvelocity = sqrtf(powf(pOff->HeadPose.LinearVelocity.x, 2) + - powf(pOff->HeadPose.LinearVelocity.y, 2) + - powf(pOff->HeadPose.LinearVelocity.z, 2)); - - - //For melee right hand is alt attack and left hand is attack - static bool primaryVelocityTriggeredAttack = false; - static bool secondaryVelocityTriggeredAttack = false; - if (vr.weaponid == WP_MELEE) { - //Does weapon velocity trigger attack (melee) and is it fast enough - if (vr.velocitytriggered) { - static bool fired = qfalse; - primaryVelocityTriggeredAttack = (vr.primaryswingvelocity > WEAPON_VELOCITY_TRIGGER); - - if (fired != primaryVelocityTriggeredAttack) { - ALOGV("**WEAPON EVENT** veocity triggered %s", - primaryVelocityTriggeredAttack ? "+altattack" : "-altattack"); - //normal attack is a punch with the left hand - sendButtonAction("+altattack", primaryVelocityTriggeredAttack); - fired = primaryVelocityTriggeredAttack; - } - } else if (primaryVelocityTriggeredAttack) { - //send a stop attack as we have an unfinished velocity attack - primaryVelocityTriggeredAttack = qfalse; - ALOGV("**WEAPON EVENT** veocity triggered -altattack"); - sendButtonAction("+altattack", primaryVelocityTriggeredAttack); - } - - if (vr.velocitytriggered) { - static bool fired = qfalse; - secondaryVelocityTriggeredAttack = (vr.secondaryswingvelocity > - WEAPON_VELOCITY_TRIGGER); - - if (fired != secondaryVelocityTriggeredAttack) { - ALOGV("**WEAPON EVENT** veocity triggered %s", - secondaryVelocityTriggeredAttack ? "+attack" : "-attack"); - //normal attack is a punch with the left hand - sendButtonAction("+attack", secondaryVelocityTriggeredAttack); - fired = secondaryVelocityTriggeredAttack; - } - } else if (secondaryVelocityTriggeredAttack) { - //send a stop attack as we have an unfinished velocity attack - secondaryVelocityTriggeredAttack = qfalse; - ALOGV("**WEAPON EVENT** veocity triggered -attack"); - sendButtonAction("+attack", secondaryVelocityTriggeredAttack); - } - } - else if (vr.weaponid == WP_SABER) { - //Does weapon velocity trigger attack - if (vr.velocitytriggered) { - static bool fired = qfalse; - primaryVelocityTriggeredAttack = (vr.primaryswingvelocity > WEAPON_VELOCITY_TRIGGER); - - if (fired != primaryVelocityTriggeredAttack) { - ALOGV("**WEAPON EVENT** veocity triggered %s", - primaryVelocityTriggeredAttack ? "+attack" : "-attack"); - //normal attack is a punch with the left hand - sendButtonAction("+attack", primaryVelocityTriggeredAttack); - fired = primaryVelocityTriggeredAttack; - } - } else if (primaryVelocityTriggeredAttack) { - //send a stop attack as we have an unfinished velocity attack - primaryVelocityTriggeredAttack = qfalse; - ALOGV("**WEAPON EVENT** veocity triggered -attack"); - sendButtonAction("+attack", primaryVelocityTriggeredAttack); - } - } - - if (vr.weapon_stabilised) - { - if (vr.scopeengaged || vr_virtual_stock->integer == 1) - { - //offset to the appropriate eye a little bit - vec2_t xy; - rotateAboutOrigin(Cvar_VariableValue("cg_stereoSeparation") / 2.0f, 0.0f, -vr.hmdorientation[YAW], xy); - float x = pOff->HeadPose.Pose.Position.x - (vr.hmdposition[0] + xy[0]); - 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] + xy[1]); - float zxDist = length(x, z); - - if (zxDist != 0.0f && z != 0.0f) { - VectorSet(vr.weaponangles, -degrees(atanf(y / zxDist)), - -degrees(atan2f(x, -z)), 0); - } - } - else - { - float x = pOff->HeadPose.Pose.Position.x - pWeapon->HeadPose.Pose.Position.x; - float y = pOff->HeadPose.Pose.Position.y - pWeapon->HeadPose.Pose.Position.y; - float z = pOff->HeadPose.Pose.Position.z - pWeapon->HeadPose.Pose.Position.z; - float zxDist = length(x, z); - - if (zxDist != 0.0f && z != 0.0f) { - VectorSet(vr.weaponangles, -degrees(atanf(y / zxDist)), - -degrees(atan2f(x, -z)), vr.weaponangles[ROLL] / 2.0f); //Dampen roll on stabilised weapon - } - } - } - - // Calculate if player tries to reach backpack - bool handInBackpack = false; - bool bpDistToHMDOk = false, bpWeaponHeightOk = false, bpWeaponAngleOk = false, bpHmdToWeaponAngleOk = false; - vec3_t hmdForwardXY = {}, weaponForwardXY = {}; - float weaponToDownAngle = 0, hmdToWeaponDotProduct = 0; - static vec3_t downVector = {0.0, 0.0, -1.0}; - - bool bpTrackOk = pOffTracking->Status & VRAPI_TRACKING_STATUS_POSITION_TRACKED; // 1) Position must be tracked - if (bpTrackOk && (bpDistToHMDOk = distanceToHMD >= 0.2 && distanceToHMD <= 0.35) // 2) Weapon-to-HMD distance must be within <0.2-0.35> range - && (bpWeaponHeightOk = vr.weaponoffset[1] >= -0.10 && vr.weaponoffset[1] <= 0.10)) // 3) Weapon height in relation to HMD must be within <-0.10, 0.10> range - { - AngleVectors(vr.hmdorientation, hmdForwardXY, NULL, NULL); - AngleVectors(vr.weaponangles, weaponForwardXY, NULL, NULL); - - float weaponToDownAngle = AngleBetweenVectors(downVector, weaponForwardXY); - // 4) Angle between weapon forward vector and a down vector must be within 80-140 degrees - if(bpWeaponAngleOk = weaponToDownAngle >= 80.0 && weaponToDownAngle <= 140.0) - { - hmdForwardXY[2] = 0; - VectorNormalize(hmdForwardXY); - - weaponForwardXY[2] = 0; - VectorNormalize(weaponForwardXY); - - hmdToWeaponDotProduct = DotProduct(hmdForwardXY, weaponForwardXY); - // 5) HMD and weapon forward on XY plane must go in opposite directions (i.e. dot product < 0) - handInBackpack = bpHmdToWeaponAngleOk = hmdToWeaponDotProduct < 0; - } - } - - //off-hand stuff (done here as I reference it in the save state thing - { - vr.offhandposition[0] = pOff->HeadPose.Pose.Position.x; - vr.offhandposition[1] = pOff->HeadPose.Pose.Position.y; - vr.offhandposition[2] = pOff->HeadPose.Pose.Position.z; - - vr.offhandoffset[0] = pOff->HeadPose.Pose.Position.x - vr.hmdposition[0]; - vr.offhandoffset[1] = pOff->HeadPose.Pose.Position.y - vr.hmdposition[1]; - vr.offhandoffset[2] = pOff->HeadPose.Pose.Position.z - vr.hmdposition[2]; - - vec3_t rotation = {0}; - QuatToYawPitchRoll(pOff->HeadPose.Pose.Orientation, rotation, vr.offhandangles); - - if (vr_walkdirection->value == 0) { - controllerYawHeading = vr.offhandangles[YAW] - vr.hmdorientation[YAW]; - } - else - { - controllerYawHeading = 0.0f; - } - } - - // Use off hand as well to trigger save condition - canUseQuickSave = false; - bool bpOffhandDistToHMDOk = false, bpOffhandHeightOk = false, bpOffhandAngleOk = false, bpHmdToOffhandAngleOk = false; - vec3_t offhandForwardXY = {}; - float hmdToOffhandDotProduct = 0; - float offhandToDownAngle = 0; - if (bpTrackOk && (bpOffhandDistToHMDOk = distanceToHMDOff >= 0.2 && distanceToHMDOff <= 0.35) // 2) Off-to-HMD distance must be within <0.2-0.35> range - && (bpOffhandHeightOk = vr.offhandoffset[1] >= -0.10 && vr.offhandoffset[1] <= 0.10)) // 3) Offhand height in relation to HMD must be within <-0.10, 0.10> range - { - //Need to do this again as might not have done it above and cant be bothered to refactor - AngleVectors(vr.hmdorientation, hmdForwardXY, NULL, NULL); - AngleVectors(vr.offhandangles, offhandForwardXY, NULL, NULL); - - offhandToDownAngle = AngleBetweenVectors(downVector, offhandForwardXY); - - // 4) Angle between weapon forward vector and a down vector must be within 80-140 degrees - if(bpOffhandAngleOk = offhandToDownAngle >= 80.0 && offhandToDownAngle <= 140.0) - { - hmdForwardXY[2] = 0; - VectorNormalize(hmdForwardXY); - - offhandForwardXY[2] = 0; - VectorNormalize(offhandForwardXY); - - hmdToOffhandDotProduct = DotProduct(hmdForwardXY, offhandForwardXY); - // 5) HMD and weapon forward on XY plane must go in opposite directions (i.e. dot product < 0) - canUseQuickSave = bpHmdToOffhandAngleOk = hmdToOffhandDotProduct < 0; - } - } - - // Uncomment to debug offhand reaching - - ALOGV("Quick Save> Dist: %f | OffHandToDownAngle: %f | HandOffs: %f %f %f\nHmdHandDot: %f | HmdFwdXY: %f %f | WpnFwdXY: %f %f\nTrackOk: %i, DistOk: %i, HeightOk: %i, HnadAngleOk: %i, HmdHandDotOk: %i", - distanceToHMDOff, offhandToDownAngle, vr.offhandoffset[0], vr.offhandoffset[1], vr.offhandoffset[2], - hmdToOffhandDotProduct, hmdForwardXY[0], hmdForwardXY[1], offhandForwardXY[0], offhandForwardXY[1], - bpTrackOk, bpOffhandDistToHMDOk, bpOffhandHeightOk, bpOffhandAngleOk, bpHmdToOffhandAngleOk); - - - // Check quicksave - if (canUseQuickSave) { - int channel = (vr_control_scheme->integer >= 10) ? 1 : 0; - JKVR_Vibrate(40, channel, 0.5); // vibrate to let user know they can switch - - if (((pOffTrackedRemoteNew->Buttons & offButton1) != - (pOffTrackedRemoteOld->Buttons & offButton1)) && - (pOffTrackedRemoteNew->Buttons & offButton1)) { - sendButtonActionSimple("savegame quicksave"); - } - - if (((pOffTrackedRemoteNew->Buttons & offButton2) != - (pOffTrackedRemoteOld->Buttons & offButton2)) && - (pOffTrackedRemoteNew->Buttons & offButton2)) { - sendButtonActionSimple("loadgame quicksave"); - } - } - - dominantGripPushed = (pDominantTrackedRemoteNew->Buttons & - ovrButton_GripTrigger) != 0; - bool dominantButton1Pushed = (pDominantTrackedRemoteNew->Buttons & - domButton1) != 0; - bool dominantButton2Pushed = (pDominantTrackedRemoteNew->Buttons & - domButton2) != 0; - - { - if (dominantGripPushed) { - if (dominantGripPushTime == 0) { - dominantGripPushTime = GetTimeInMilliSeconds(); - } - Cvar_Set("timescale", "0.22"); - } - else - { - dominantGripPushTime = 0; - Cvar_Set("timescale", "1.0"); - } - } - } #define JOYX_SAMPLE_COUNT 4 static float joyx[JOYX_SAMPLE_COUNT] = {0}; - for (int j = JOYX_SAMPLE_COUNT-1; j > 0; --j) - joyx[j] = joyx[j-1]; + for (int j = JOYX_SAMPLE_COUNT - 1; j > 0; --j) + joyx[j] = joyx[j - 1]; joyx[0] = pPrimaryJoystick->x; float sum = 0.0f; for (int j = 0; j < JOYX_SAMPLE_COUNT; ++j) @@ -465,201 +205,471 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG float primaryJoystickX = sum / 4.0f; - //Right-hand specific stuff - { - //This section corrects for the fact that the controller actually controls direction of movement, but we want to move relative to the direction the - //player is facing for positional tracking - - //Positional movement speed correction for when we are not hitting target framerate - static double lastframetime = 0; - int refresh = GetRefresh(); - double newframetime = GetTimeInMilliSeconds(); - float multiplier = (float)((1000.0 / refresh) / (newframetime - lastframetime)); - lastframetime = newframetime; - - vec2_t v; - float factor = (refresh / 72.0F) * vr_positional_factor->value; // adjust positional factor based on refresh rate - rotateAboutOrigin(-vr.hmdposition_delta[0] * factor * multiplier, - vr.hmdposition_delta[2] * factor * multiplier, - vr.hmdorientation[YAW], v); - positional_movementSideways = v[0]; - positional_movementForward = v[1]; - - ALOGV(" positional_movementSideways: %f, positional_movementForward: %f", - positional_movementSideways, - positional_movementForward); - - - //Jump (A Button) - if ((primaryButtonsNew & primaryButton1) != (primaryButtonsOld & primaryButton1)) - { - sendButtonAction("+moveup", (primaryButtonsNew & primaryButton1)); - } - - //Alt Fire (B Button) - if ((primaryButtonsNew & primaryButton2) != (primaryButtonsOld & primaryButton2)) - { - sendButtonAction("+altattack", (primaryButtonsNew & primaryButton2)); - } - - - static bool firing = false; - - { - //Fire Primary - Doesn't trigger the saber - if (!vr.velocitytriggered && // Don't fire velocity triggered weapons - (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger) != - (pDominantTrackedRemoteOld->Buttons & ovrButton_Trigger)) { - - ALOGV("**WEAPON EVENT** Not Grip Pushed %sattack", (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger) ? "+" : "-"); - firing = (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger); - sendButtonAction("+attack", firing); + //Left/right to switch between which selector we are using + if (vr.item_selector) { + static bool itemSwitched = false; + if (between(-0.2f, pPrimaryJoystick->y, 0.2f) && + (between(0.8f, primaryJoystickX, 1.0f) || + between(-1.0f, primaryJoystickX, -0.8f))) { + if (!itemSwitched) { + if (between(0.8f, primaryJoystickX, 1.0f)) { + sendButtonActionSimple("itemselectornext"); + } else { + sendButtonActionSimple("itemselectorprev"); + } + itemSwitched = true; } + } else { + itemSwitched = false; } - - - //Duck - off hand joystick - if ((secondaryButtonsNew & secondaryThumb) != - (secondaryButtonsOld & secondaryThumb)) { - - sendButtonAction("+movedown", (secondaryButtonsNew & secondaryThumb)); - } - - //Use - if ((pDominantTrackedRemoteNew->Buttons & primaryThumb) != - (pDominantTrackedRemoteOld->Buttons & primaryThumb)) { - - sendButtonAction("+use", (pDominantTrackedRemoteNew->Buttons & primaryThumb)); - } - - //Weapon Chooser - static bool itemSwitched = false; - if (between(-0.2f, primaryJoystickX, 0.2f) && - (between(0.8f, pPrimaryJoystick->y, 1.0f) || - between(-1.0f, pPrimaryJoystick->y, -0.8f))) - { - if (!itemSwitched) { - if (between(0.8f, pPrimaryJoystick->y, 1.0f)) - { - sendButtonActionSimple("weapprev"); - } - else - { - sendButtonActionSimple("weapnext"); - } - itemSwitched = true; - } - } else { - itemSwitched = false; - } } + vr.weapon_stabilised = stabilised; + + //if (!vr.item_selector) { - //Apply a filter and quadratic scaler so small movements are easier to make - float dist = length(pSecondaryJoystick->x, pSecondaryJoystick->y); - float nlf = nonLinearFilter(dist); - float x = (nlf * pSecondaryJoystick->x) + pFootTrackingNew->LeftJoystick.x; - float y = (nlf * pSecondaryJoystick->y) - pFootTrackingNew->LeftJoystick.y; - - vr.player_moving = (fabs(x) + fabs(y)) > 0.05f; - - //Adjust to be off-hand controller oriented - vec2_t v; - rotateAboutOrigin(x, y, controllerYawHeading, v); - - //Move a lot slower if scope is engaged - remote_movementSideways = v[0] * (vr.scopeengaged ? 0.3f : 1.0f) * vr_movement_multiplier->value; - remote_movementForward = v[1] * (vr.scopeengaged ? 0.3f : 1.0f) * vr_movement_multiplier->value; - ALOGV(" remote_movementSideways: %f, remote_movementForward: %f", - remote_movementSideways, - remote_movementForward); - - - //Use Force (X button) - if (!canUseQuickSave) { - if ((secondaryButtonsNew & secondaryButton1) != - (secondaryButtonsOld & secondaryButton1)) { - sendButtonAction("+useforce", (secondaryButtonsNew & secondaryButton1)); + //Engage scope / virtual stock if conditions are right + bool scopeready = vr.weapon_stabilised && (distanceToHMD < SCOPE_ENGAGE_DISTANCE); + static bool lastScopeReady = qfalse; + if (scopeready != lastScopeReady) { + if (vr.scopedweapon && !vr.scopedetached) { + if (!vr.scopeengaged && scopeready) { + ALOGV("**WEAPON EVENT** trigger scope mode"); + sendButtonActionSimple("weapalt"); + } else if (vr.scopeengaged && !scopeready) { + ALOGV("**WEAPON EVENT** disable scope mode"); + sendButtonActionSimple("weapalt"); + } + lastScopeReady = scopeready; } } - //Open the datapad - if (!canUseQuickSave) { - if (((secondaryButtonsNew & secondaryButton2) != - (secondaryButtonsOld & secondaryButton2)) && - (secondaryButtonsNew & secondaryButton2)) { - Sys_QueEvent( 0, SE_KEY, A_TAB, true, 0, NULL ); + //ALOGV("**GB WEAPON ACTIVE** %i",vr.weaponid); + if (!scopeready && vr.weaponid >= 15 && vr.weaponid <= 17) { + lastScopeReady = false; + ALOGV("**WEAPON EVENT** disable scope mode forced"); + sendButtonActionSimple("weapalt"); + } + + //Engage scope / virtual stock (iron sight lock) if conditions are right + static bool scopeEngaged = qfalse; + if (scopeEngaged != vr.scopeengaged) { + scopeEngaged = vr.scopeengaged; + } + + //dominant hand stuff first + { + //Record recent weapon position for trajectory based stuff + for (int i = (NUM_WEAPON_SAMPLES - 1); i != 0; --i) { + 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; - //We need to record if we have started firing primary so that releasing trigger will stop definitely firing, if user has pushed grip - //in meantime, then it wouldn't stop the gun firing and it would get stuck - { - //Run - handleTrackedControllerButton(pOffTrackedRemoteNew, - pOffTrackedRemoteOld, - ovrButton_Trigger, A_SHIFT); - } + VectorSet(vr.weaponposition, pWeapon->HeadPose.Pose.Position.x, + pWeapon->HeadPose.Pose.Position.y, pWeapon->HeadPose.Pose.Position.z); - //Resync Yaw on mounted gun transition - static int usingMountedGun = false; - if (vr.mountedgun != usingMountedGun) - { - usingMountedGun = vr.mountedgun; - } + ///Weapon location relative to view + VectorSet(vr.weaponoffset, pWeapon->HeadPose.Pose.Position.x, + pWeapon->HeadPose.Pose.Position.y, pWeapon->HeadPose.Pose.Position.z); + VectorSubtract(vr.weaponoffset, vr.hmdposition, vr.weaponoffset); + vr.weaponoffset_timestamp = Sys_Milliseconds(); - //No snap turn when using mounted gun - static int syncCount = 0; - static int increaseSnap = true; - if (!vr.mountedgun && !vr.scopeengaged) { - if (primaryJoystickX > 0.7f) { - if (increaseSnap) { - float turnAngle = vr_turn_mode->integer ? (vr_turn_angle->value / 9.0f) : vr_turn_angle->value; - vr.snapTurn -= turnAngle; + vec3_t velocity; + VectorSet(velocity, pWeapon->HeadPose.LinearVelocity.x, + pWeapon->HeadPose.LinearVelocity.y, pWeapon->HeadPose.LinearVelocity.z); + vr.primaryswingvelocity = VectorLength(velocity); - if (vr_turn_mode->integer == 0) { - increaseSnap = false; + VectorSet(velocity, pOff->HeadPose.LinearVelocity.x, + pOff->HeadPose.LinearVelocity.y, pOff->HeadPose.LinearVelocity.z); + vr.secondaryswingvelocity = VectorLength(velocity); + + + //For melee right hand is alt attack and left hand is attack + if (vr.weaponid == WP_MELEE) { + //Does weapon velocity trigger attack (melee) and is it fast enough + if (vr.velocitytriggered) { + static bool fired = false; + vr.primaryVelocityTriggeredAttack = (vr.primaryswingvelocity > + vr_weapon_velocity_trigger->value); + + if (fired != vr.primaryVelocityTriggeredAttack) { + ALOGV("**WEAPON EVENT** veocity triggered %s", + vr.primaryVelocityTriggeredAttack ? "+altattack" : "-altattack"); + //normal attack is a punch with the left hand + sendButtonAction("+altattack", vr.primaryVelocityTriggeredAttack); + fired = vr.primaryVelocityTriggeredAttack; } + } else if (vr.primaryVelocityTriggeredAttack) { + //send a stop attack as we have an unfinished velocity attack + vr.primaryVelocityTriggeredAttack = false; + ALOGV("**WEAPON EVENT** veocity triggered -altattack"); + sendButtonAction("+altattack", vr.primaryVelocityTriggeredAttack); + } - if (vr.snapTurn < -180.0f) { - vr.snapTurn += 360.f; + if (vr.velocitytriggered) { + static bool fired = false; + vr.secondaryVelocityTriggeredAttack = (vr.secondaryswingvelocity > + vr_weapon_velocity_trigger->value); + + if (fired != vr.secondaryVelocityTriggeredAttack) { + ALOGV("**WEAPON EVENT** veocity triggered %s", + vr.secondaryVelocityTriggeredAttack ? "+attack" : "-attack"); + //normal attack is a punch with the left hand + sendButtonAction("+attack", vr.secondaryVelocityTriggeredAttack); + fired = vr.secondaryVelocityTriggeredAttack; + } + } else if (vr.secondaryVelocityTriggeredAttack) { + //send a stop attack as we have an unfinished velocity attack + vr.secondaryVelocityTriggeredAttack = qfalse; + ALOGV("**WEAPON EVENT** veocity triggered -attack"); + sendButtonAction("+attack", vr.secondaryVelocityTriggeredAttack); + } + } else if (vr.weaponid == WP_SABER) { + //Does weapon velocity trigger attack + if (vr.velocitytriggered) { + static bool fired = false; + vr.primaryVelocityTriggeredAttack = (vr.primaryswingvelocity > + vr_weapon_velocity_trigger->value); + + if (fired != vr.primaryVelocityTriggeredAttack) { + ALOGV("**WEAPON EVENT** veocity triggered %s", + vr.primaryVelocityTriggeredAttack ? "+attack" : "-attack"); + //normal attack is a punch with the left hand + sendButtonAction("+attack", vr.primaryVelocityTriggeredAttack); + fired = vr.primaryVelocityTriggeredAttack; + } + } else if (vr.primaryVelocityTriggeredAttack) { + //send a stop attack as we have an unfinished velocity attack + vr.primaryVelocityTriggeredAttack = false; + ALOGV("**WEAPON EVENT** veocity triggered -attack"); + sendButtonAction("+attack", vr.primaryVelocityTriggeredAttack); + } + } + + if (vr.weapon_stabilised) { + if (vr.scopeengaged || vr_virtual_stock->integer == 1) { + //offset to the appropriate eye a little bit + vec2_t xy; + rotateAboutOrigin(Cvar_VariableValue("cg_stereoSeparation") / 2.0f, 0.0f, + -vr.hmdorientation[YAW], xy); + float x = pOff->HeadPose.Pose.Position.x - (vr.hmdposition[0] + xy[0]); + 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] + xy[1]); + float zxDist = length(x, z); + + if (zxDist != 0.0f && z != 0.0f) { + VectorSet(vr.weaponangles, -degrees(atanf(y / zxDist)), + -degrees(atan2f(x, -z)), 0); + } + } else { + float x = + pOff->HeadPose.Pose.Position.x - pWeapon->HeadPose.Pose.Position.x; + float y = + pOff->HeadPose.Pose.Position.y - pWeapon->HeadPose.Pose.Position.y; + float z = + pOff->HeadPose.Pose.Position.z - pWeapon->HeadPose.Pose.Position.z; + float zxDist = length(x, z); + + if (zxDist != 0.0f && z != 0.0f) { + VectorSet(vr.weaponangles, -degrees(atanf(y / zxDist)), + -degrees(atan2f(x, -z)), vr.weaponangles[ROLL] / + 2.0f); //Dampen roll on stabilised weapon } } - } else if (primaryJoystickX < 0.3f) { - increaseSnap = true; } - static int decreaseSnap = true; - if (primaryJoystickX < -0.7f) { - if (decreaseSnap) { + // Calculate if player tries to reach backpack + bool handInBackpack = false; + bool bpDistToHMDOk = false, bpWeaponHeightOk = false, bpWeaponAngleOk = false, bpHmdToWeaponAngleOk = false; + vec3_t hmdForwardXY = {}, weaponForwardXY = {}; + float weaponToDownAngle = 0, hmdToWeaponDotProduct = 0; + static vec3_t downVector = {0.0, 0.0, -1.0}; - float turnAngle = vr_turn_mode->integer ? (vr_turn_angle->value / 9.0f) : vr_turn_angle->value; - vr.snapTurn += turnAngle; - - //If snap turn configured for less than 10 degrees - if (vr_turn_mode->integer == 0) { - decreaseSnap = false; - } - - if (vr.snapTurn > 180.0f) { - vr.snapTurn -= 360.f; - } - } - } else if (primaryJoystickX > -0.3f) { - decreaseSnap = true; - } - } - else { - if (fabs(primaryJoystickX) > 0.5f) { - increaseSnap = false; - } - else + bool bpTrackOk = pOffTracking->Status & + VRAPI_TRACKING_STATUS_POSITION_TRACKED; // 1) Position must be tracked + if (bpTrackOk && (bpDistToHMDOk = distanceToHMD >= 0.2 && distanceToHMD <= + 0.35) // 2) Weapon-to-HMD distance must be within <0.2-0.35> range + && (bpWeaponHeightOk = vr.weaponoffset[1] >= -0.10 && vr.weaponoffset[1] <= + 0.10)) // 3) Weapon height in relation to HMD must be within <-0.10, 0.10> range { - increaseSnap = true; + AngleVectors(vr.hmdorientation, hmdForwardXY, NULL, NULL); + AngleVectors(vr.weaponangles, weaponForwardXY, NULL, NULL); + + float weaponToDownAngle = AngleBetweenVectors(downVector, weaponForwardXY); + // 4) Angle between weapon forward vector and a down vector must be within 80-140 degrees + if (bpWeaponAngleOk = weaponToDownAngle >= 80.0 && weaponToDownAngle <= 140.0) { + hmdForwardXY[2] = 0; + VectorNormalize(hmdForwardXY); + + weaponForwardXY[2] = 0; + VectorNormalize(weaponForwardXY); + + hmdToWeaponDotProduct = DotProduct(hmdForwardXY, weaponForwardXY); + // 5) HMD and weapon forward on XY plane must go in opposite directions (i.e. dot product < 0) + handInBackpack = bpHmdToWeaponAngleOk = hmdToWeaponDotProduct < 0; + } + } + + //off-hand stuff (done here as I reference it in the save state thing + { + vr.offhandposition[0] = pOff->HeadPose.Pose.Position.x; + vr.offhandposition[1] = pOff->HeadPose.Pose.Position.y; + vr.offhandposition[2] = pOff->HeadPose.Pose.Position.z; + + vr.offhandoffset[0] = pOff->HeadPose.Pose.Position.x - vr.hmdposition[0]; + vr.offhandoffset[1] = pOff->HeadPose.Pose.Position.y - vr.hmdposition[1]; + vr.offhandoffset[2] = pOff->HeadPose.Pose.Position.z - vr.hmdposition[2]; + + vec3_t rotation = {0}; + QuatToYawPitchRoll(pOff->HeadPose.Pose.Orientation, rotation, vr.offhandangles); + + if (vr_walkdirection->value == 0) { + controllerYawHeading = vr.offhandangles[YAW] - vr.hmdorientation[YAW]; + } else { + controllerYawHeading = 0.0f; + } + } + + // Use off hand as well to trigger save condition + canUseQuickSave = false; + bool bpOffhandDistToHMDOk = false, bpOffhandHeightOk = false, bpOffhandAngleOk = false, bpHmdToOffhandAngleOk = false; + vec3_t offhandForwardXY = {}; + float hmdToOffhandDotProduct = 0; + float offhandToDownAngle = 0; + if (bpTrackOk && (bpOffhandDistToHMDOk = distanceToHMDOff >= 0.2 && + distanceToHMDOff <= + 0.35) // 2) Off-to-HMD distance must be within <0.2-0.35> range + && (bpOffhandHeightOk = vr.offhandoffset[1] >= -0.10 && vr.offhandoffset[1] <= + 0.10)) // 3) Offhand height in relation to HMD must be within <-0.10, 0.10> range + { + //Need to do this again as might not have done it above and cant be bothered to refactor + AngleVectors(vr.hmdorientation, hmdForwardXY, NULL, NULL); + AngleVectors(vr.offhandangles, offhandForwardXY, NULL, NULL); + + offhandToDownAngle = AngleBetweenVectors(downVector, offhandForwardXY); + + // 4) Angle between weapon forward vector and a down vector must be within 80-140 degrees + if (bpOffhandAngleOk = + offhandToDownAngle >= 80.0 && offhandToDownAngle <= 140.0) { + hmdForwardXY[2] = 0; + VectorNormalize(hmdForwardXY); + + offhandForwardXY[2] = 0; + VectorNormalize(offhandForwardXY); + + hmdToOffhandDotProduct = DotProduct(hmdForwardXY, offhandForwardXY); + // 5) HMD and weapon forward on XY plane must go in opposite directions (i.e. dot product < 0) + canUseQuickSave = bpHmdToOffhandAngleOk = hmdToOffhandDotProduct < 0; + } + } + + // Uncomment to debug offhand reaching + + ALOGV("Quick Save> Dist: %f | OffHandToDownAngle: %f | HandOffs: %f %f %f\nHmdHandDot: %f | HmdFwdXY: %f %f | WpnFwdXY: %f %f\nTrackOk: %i, DistOk: %i, HeightOk: %i, HnadAngleOk: %i, HmdHandDotOk: %i", + distanceToHMDOff, offhandToDownAngle, vr.offhandoffset[0], + vr.offhandoffset[1], vr.offhandoffset[2], + hmdToOffhandDotProduct, hmdForwardXY[0], hmdForwardXY[1], offhandForwardXY[0], + offhandForwardXY[1], + bpTrackOk, bpOffhandDistToHMDOk, bpOffhandHeightOk, bpOffhandAngleOk, + bpHmdToOffhandAngleOk); + + + // Check quicksave + if (canUseQuickSave) { + int channel = (vr_control_scheme->integer >= 10) ? 1 : 0; + JKVR_Vibrate(40, channel, 0.5); // vibrate to let user know they can switch + + if (((pOffTrackedRemoteNew->Buttons & offButton1) != + (pOffTrackedRemoteOld->Buttons & offButton1)) && + (pOffTrackedRemoteNew->Buttons & offButton1)) { + sendButtonActionSimple("savegame quicksave"); + } + + if (((pOffTrackedRemoteNew->Buttons & offButton2) != + (pOffTrackedRemoteOld->Buttons & offButton2)) && + (pOffTrackedRemoteNew->Buttons & offButton2)) { + sendButtonActionSimple("loadgame quicksave"); + } } } - } - updateScopeAngles(); + //Right-hand specific stuff + { + //This section corrects for the fact that the controller actually controls direction of movement, but we want to move relative to the direction the + //player is facing for positional tracking + + //Positional movement speed correction for when we are not hitting target framerate + static double lastframetime = 0; + int refresh = GetRefresh(); + double newframetime = GetTimeInMilliSeconds(); + float multiplier = (float) ((1000.0 / refresh) / (newframetime - lastframetime)); + lastframetime = newframetime; + + vec2_t v; + float factor = (refresh / 72.0F) * + vr_positional_factor->value; // adjust positional factor based on refresh rate + rotateAboutOrigin(-vr.hmdposition_delta[0] * factor * multiplier, + vr.hmdposition_delta[2] * factor * multiplier, + -vr.hmdorientation[YAW], v); + positional_movementSideways = v[0]; + positional_movementForward = v[1]; + + ALOGV(" positional_movementSideways: %f, positional_movementForward: %f", + positional_movementSideways, + positional_movementForward); + + + //Jump (A Button) + if ((primaryButtonsNew & primaryButton1) != (primaryButtonsOld & primaryButton1)) { + sendButtonAction("+moveup", (primaryButtonsNew & primaryButton1)); + } + + //Alt Fire (B Button) + if ((primaryButtonsNew & primaryButton2) != (primaryButtonsOld & primaryButton2)) { + sendButtonAction("+altattack", (primaryButtonsNew & primaryButton2)); + } + + + static bool firing = false; + + { + //Fire Primary - Doesn't trigger the saber + if (!vr.velocitytriggered && // Don't fire velocity triggered weapons + (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger) != + (pDominantTrackedRemoteOld->Buttons & ovrButton_Trigger)) { + + ALOGV("**WEAPON EVENT** Not Grip Pushed %sattack", + (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger) ? "+" : "-"); + firing = (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger); + sendButtonAction("+attack", firing); + } + } + + + //Duck - off hand joystick + if ((secondaryButtonsNew & secondaryThumb) != + (secondaryButtonsOld & secondaryThumb)) { + + sendButtonAction("+movedown", (secondaryButtonsNew & secondaryThumb)); + } + + //Use + if ((pDominantTrackedRemoteNew->Buttons & primaryThumb) != + (pDominantTrackedRemoteOld->Buttons & primaryThumb)) { + + sendButtonAction("+use", (pDominantTrackedRemoteNew->Buttons & primaryThumb)); + } + } + + { + //Apply a filter and quadratic scaler so small movements are easier to make + float dist = length(pSecondaryJoystick->x, pSecondaryJoystick->y); + float nlf = nonLinearFilter(dist); + float x = (nlf * pSecondaryJoystick->x) + pFootTrackingNew->LeftJoystick.x; + float y = (nlf * pSecondaryJoystick->y) - pFootTrackingNew->LeftJoystick.y; + + vr.player_moving = (fabs(x) + fabs(y)) > 0.05f; + + //Adjust to be off-hand controller oriented + vec2_t v; + rotateAboutOrigin(x, y, controllerYawHeading, v); + + //Move a lot slower if scope is engaged + remote_movementSideways = + v[0] * (vr.scopeengaged ? 0.3f : 1.0f) * vr_movement_multiplier->value; + remote_movementForward = + v[1] * (vr.scopeengaged ? 0.3f : 1.0f) * vr_movement_multiplier->value; + ALOGV(" remote_movementSideways: %f, remote_movementForward: %f", + remote_movementSideways, + remote_movementForward); + + + if (!canUseQuickSave) { + if ((secondaryButtonsNew & secondaryButton1) != + (secondaryButtonsOld & secondaryButton1)) { + //Toggle walk/run somehow?! + } + } + + //Open the datapad + if (!canUseQuickSave) { + if (((secondaryButtonsNew & secondaryButton2) != + (secondaryButtonsOld & secondaryButton2)) && + (secondaryButtonsNew & secondaryButton2)) { + Sys_QueEvent(0, SE_KEY, A_TAB, true, 0, NULL); + } + } + + //Use Force - off hand trigger + { + if ((pOffTrackedRemoteNew->Buttons & ovrButton_Trigger) != + (pOffTrackedRemoteOld->Buttons & ovrButton_Trigger)) { + sendButtonAction("+useforce", (pOffTrackedRemoteNew->Buttons & ovrButton_Trigger)); + } + } + + //Resync Yaw on mounted gun transition + static int usingMountedGun = false; + if (vr.mountedgun != usingMountedGun) { + usingMountedGun = vr.mountedgun; + } + + //No snap turn when using mounted gun + static int syncCount = 0; + static int increaseSnap = true; + if (!vr.item_selector && !vr.mountedgun && !vr.scopeengaged) { + if (primaryJoystickX > 0.7f) { + if (increaseSnap) { + float turnAngle = vr_turn_mode->integer ? (vr_turn_angle->value / 9.0f) + : vr_turn_angle->value; + vr.snapTurn -= turnAngle; + + if (vr_turn_mode->integer == 0) { + increaseSnap = false; + } + + if (vr.snapTurn < -180.0f) { + vr.snapTurn += 360.f; + } + } + } else if (primaryJoystickX < 0.3f) { + increaseSnap = true; + } + + static int decreaseSnap = true; + if (primaryJoystickX < -0.7f) { + if (decreaseSnap) { + + float turnAngle = vr_turn_mode->integer ? (vr_turn_angle->value / 9.0f) + : vr_turn_angle->value; + vr.snapTurn += turnAngle; + + //If snap turn configured for less than 10 degrees + if (vr_turn_mode->integer == 0) { + decreaseSnap = false; + } + + if (vr.snapTurn > 180.0f) { + vr.snapTurn -= 360.f; + } + } + } else if (primaryJoystickX > -0.3f) { + decreaseSnap = true; + } + } else { + if (fabs(primaryJoystickX) > 0.5f) { + increaseSnap = false; + } else { + increaseSnap = true; + } + } + } + + updateScopeAngles(); + } } //Save state diff --git a/Projects/Android/jni/OpenJK/code/client/cl_cin.cpp b/Projects/Android/jni/OpenJK/code/client/cl_cin.cpp index 48ece6d..3d4b1b7 100644 --- a/Projects/Android/jni/OpenJK/code/client/cl_cin.cpp +++ b/Projects/Android/jni/OpenJK/code/client/cl_cin.cpp @@ -2018,6 +2018,76 @@ void CL_PlayInGameCinematic_f(void) } +// Text crawl defines +#define TC_PLANE_WIDTH 250 +#define TC_PLANE_NEAR 90 +#define TC_PLANE_FAR 715 +#define TC_PLANE_TOP 0 +#define TC_PLANE_BOTTOM 1100 + +#define TC_DELAY 9000 +#define TC_STOPTIME 81000 +void SCR_AddCreditTextCrawl() +{ + static int startTime = cls.realtime; + refdef_t refdef; + polyVert_t verts[4]; + + // Set up refdef + memset( &refdef, 0, sizeof( refdef )); + + refdef.rdflags = RDF_NOWORLDMODEL; + AxisClear( refdef.viewaxis ); + + refdef.fov_x = 150; + refdef.fov_y = 150; + + refdef.x = 0; + refdef.y = -50; + refdef.width = cls.glconfig.vidWidth; + refdef.height = cls.glconfig.vidHeight * 2; // deliberately extend off the bottom of the screen + + // use to set shaderTime for scrolling shaders + refdef.time = 0; + + // Set up the poly verts + float fadeDown = 1.0; + for ( int i = 0; i < 4; i++ ) + { + verts[i].modulate[0] = 255*fadeDown; // gold color? + verts[i].modulate[1] = 235*fadeDown; + verts[i].modulate[2] = 127*fadeDown; + verts[i].modulate[3] = 255*fadeDown; + } + + VectorScaleM( verts[2].modulate, 0.1f, verts[2].modulate ); // darken at the top?? + VectorScaleM( verts[3].modulate, 0.1f, verts[3].modulate ); + + float timeoffset = (cls.realtime-startTime)*0.000015f -1; + VectorSet( verts[0].xyz, TC_PLANE_NEAR, -TC_PLANE_WIDTH, TC_PLANE_TOP ); + verts[0].st[0] = 1; + verts[0].st[1] = 1 +timeoffset; + + VectorSet( verts[1].xyz, TC_PLANE_NEAR, TC_PLANE_WIDTH, TC_PLANE_TOP ); + verts[1].st[0] = 0; + verts[1].st[1] = 1 +timeoffset; + + VectorSet( verts[2].xyz, TC_PLANE_FAR, TC_PLANE_WIDTH, TC_PLANE_BOTTOM ); + verts[2].st[0] = 0; + verts[2].st[1] = 0 +timeoffset; + + VectorSet( verts[3].xyz, TC_PLANE_FAR, -TC_PLANE_WIDTH, TC_PLANE_BOTTOM ); + verts[3].st[0] = 1; + verts[3].st[1] = 0 +timeoffset; + + // render it out + re.ClearScene(); + re.AddPolyToScene( re.RegisterShaderNoMip( "menu/video/tc_demo" ), 4, verts ); + re.RenderScene( &refdef ); +} + + + // Externally-called only, and only if cls.state == CA_CINEMATIC (or CL_IsRunningInGameCinematic() == true now) // void SCR_DrawCinematic (void) diff --git a/Projects/Android/jni/OpenJK/code/client/cl_scrn.cpp b/Projects/Android/jni/OpenJK/code/client/cl_scrn.cpp index dc0857d..df19f83 100644 --- a/Projects/Android/jni/OpenJK/code/client/cl_scrn.cpp +++ b/Projects/Android/jni/OpenJK/code/client/cl_scrn.cpp @@ -404,6 +404,7 @@ void SCR_Init( void ) { void UI_SetActiveMenu( const char* menuname,const char *menuID ); void _UI_Refresh( int realtime ); void UI_DrawConnect( const char *servername, const char * updateInfoString ); +void SCR_AddCreditTextCrawl( void ); /* ================== @@ -412,6 +413,7 @@ SCR_DrawScreenField This will be called twice if rendering in stereo mode ================== */ + void SCR_DrawScreenField( stereoFrame_t stereoFrame ) { re.BeginFrame( stereoFrame ); @@ -455,7 +457,6 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) { break; } } - re.ProcessDissolve(); // draw downloading progress bar @@ -470,6 +471,11 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) { if ( cl_debuggraph->integer || cl_timegraph->integer ) { SCR_DrawDebugGraph (); } + + if ( uiFullscreen ) + { + SCR_AddCreditTextCrawl(); + } } /* diff --git a/Projects/Android/jni/OpenJK/code/game/bg_local.h b/Projects/Android/jni/OpenJK/code/game/bg_local.h index 38d84b8..7e5ad28 100644 --- a/Projects/Android/jni/OpenJK/code/game/bg_local.h +++ b/Projects/Android/jni/OpenJK/code/game/bg_local.h @@ -83,6 +83,7 @@ void BG_CalculateVRWeaponPosition( vec3_t origin, vec3_t angles ); void BG_CalculateVRSaberPosition( vec3_t origin, vec3_t angles ); void BG_CalculateVROffHandPosition( vec3_t origin, vec3_t angles ); void BG_ConvertFromVR(vec3_t in, vec3_t offset, vec3_t out); +void BG_CalculateVRPositionInWorld( vec3_t in_position, vec3_t in_offset, vec3_t in_orientation, vec3_t origin, vec3_t angles ); #endif diff --git a/Projects/Android/jni/OpenJK/code/game/bg_misc.cpp b/Projects/Android/jni/OpenJK/code/game/bg_misc.cpp index 6c0e53c..81b736e 100644 --- a/Projects/Android/jni/OpenJK/code/game/bg_misc.cpp +++ b/Projects/Android/jni/OpenJK/code/game/bg_misc.cpp @@ -733,7 +733,7 @@ void BG_ConvertFromVR(vec3_t in, vec3_t offset, vec3_t out) } } -static void BG_CalculateVRPositionInWorld( vec3_t in_position, vec3_t in_offset, vec3_t in_orientation, vec3_t origin, vec3_t angles ) +void BG_CalculateVRPositionInWorld( vec3_t in_position, vec3_t in_offset, vec3_t in_orientation, vec3_t origin, vec3_t angles ) { vec3_t offset; VectorCopy(in_offset, offset); diff --git a/Projects/Android/jni/OpenJK/code/game/weapons.h b/Projects/Android/jni/OpenJK/code/game/weapons.h index 4bb063c..7845cd5 100644 --- a/Projects/Android/jni/OpenJK/code/game/weapons.h +++ b/Projects/Android/jni/OpenJK/code/game/weapons.h @@ -31,9 +31,6 @@ along with this program; if not, see . #include "../qcommon/q_shared.h" -//How fast the saber/melee needs to be physically swung in order to trigger sounds and trails etc -#define WEAPON_VELOCITY_TRIGGER 1.6f - typedef enum //# weapon_e { WP_NONE, diff --git a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_consolecmds.cpp b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_consolecmds.cpp index 6a67a67..e1daca6 100644 --- a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_consolecmds.cpp +++ b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_consolecmds.cpp @@ -202,6 +202,10 @@ int cmdcmp( const void *a, const void *b ) { return Q_stricmp( (const char *)a, ((consoleCommand_t*)b)->cmd ); } +void CG_ItemSelectorSelect_f( void ); +void CG_ItemSelectorNext_f( void ); +void CG_ItemSelectorPrev_f( void ); + /* This array MUST be sorted correctly by alphabetical name field */ static consoleCommand_t commands[] = { { "cam_disable", CMD_CGCam_Disable }, //gets out of camera mode for debuggin @@ -239,6 +243,9 @@ static consoleCommand_t commands[] = { { "weapprev", CG_PrevWeapon_f }, { "writecam", CG_WriteCam_f }, { "zoom", CG_ToggleBinoculars }, + { "itemselectorselect", CG_ItemSelectorSelect_f }, + { "itemselectornext", CG_ItemSelectorNext_f }, + { "itemselectorprev", CG_ItemSelectorPrev_f }, }; static const size_t numCommands = ARRAY_LEN( commands ); diff --git a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_draw.cpp b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_draw.cpp index f657405..2bac5be 100644 --- a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_draw.cpp +++ b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_draw.cpp @@ -2582,7 +2582,9 @@ void CG_DrawActive( stereoFrame_t stereoView ) { return; } - CG_DrawCrosshair3D(); + if (!vr->item_selector) { + CG_DrawCrosshair3D(); + } //FIXME: these globals done once at start of frame for various funcs AngleVectors (cg.refdefViewAngles, vfwd, vright, vup); diff --git a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_local.h b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_local.h index 5c6573e..5580a83 100644 --- a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_local.h +++ b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_local.h @@ -444,6 +444,13 @@ typedef struct { int weaponAnimation; int weaponAnimationTime; + int itemSelectorType; // 0 - weapons, 1 - force powers, 2 - gadgets + int itemSelectorSelection; + int itemSelectorTime; + vec3_t itemSelectorAngles; + vec3_t itemSelectorOrigin; + vec3_t itemSelectorOffset; + int inventorySelect; // Current inventory item chosen int inventorySelectTime; @@ -845,6 +852,8 @@ void CG_FireWeapon( centity_t *cent, qboolean alt_fire ); void CG_AddViewWeapon (playerState_t *ps); void CG_DrawWeaponSelect( void ); +void CG_DrawItemSelector( void ); + void CG_OutOfAmmoChange( void ); // should this be in pmove? void CG_Chunks( int owner, vec3_t origin, const vec3_t normal, const vec3_t min, const vec3_t maxs, float speed, int numChunks, material_t chunkType, int customChunk, float baseScale ); diff --git a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_main.cpp b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_main.cpp index c8c54fe..2b9fdab 100644 --- a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_main.cpp +++ b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_main.cpp @@ -2535,7 +2535,7 @@ INVENTORY SELECTION CG_InventorySelectable =============== */ -static qboolean CG_InventorySelectable( int index) +qboolean CG_InventorySelectable( int index) { if (cg.snap->ps.inventory[index]) // Is there any in the inventory? { @@ -3524,7 +3524,9 @@ void CG_DrawForceSelect( void ) { int w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 1.0f); int x = ( SCREEN_WIDTH - w ) / 2; - cgi_R_Font_DrawString(x, (SCREEN_HEIGHT / 2 + 50), text, colorTable[CT_ICON_BLUE], cgs.media.qhFontSmall, -1, 1.0f); + int y = (SCREEN_HEIGHT / 2 + 50); + CG_AdjustFrom640Int(&x, &y, NULL, NULL); + cgi_R_Font_DrawString(x, y, text, colorTable[CT_ICON_BLUE], cgs.media.qhFontSmall, -1, 1.0f); } } diff --git a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_players.cpp b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_players.cpp index b27a3bf..1e16780 100644 --- a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_players.cpp +++ b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_players.cpp @@ -3443,7 +3443,7 @@ void CG_AddRefEntityWithPowerups( refEntity_t *ent, int powerups, centity_t *cen cgi_R_AddRefEntityToScene(ent); } - if (player1stPersonSaber && !cent->currentState.saberInFlight) + if (player1stPersonSaber && !cent->currentState.saberInFlight && !vr->item_selector) { memset( &hiltEnt, 0, sizeof(refEntity_t) ); hiltEnt.renderfx = RF_DEPTHHACK; @@ -3459,14 +3459,11 @@ void CG_AddRefEntityWithPowerups( refEntity_t *ent, int powerups, centity_t *cen cgi_R_AddRefEntityToScene(&hiltEnt); static int playingSaberSwingSound = 0; - if (vr->primaryswingvelocity > WEAPON_VELOCITY_TRIGGER && ((cg.time - playingSaberSwingSound) > 800)) + if (vr->primaryVelocityTriggeredAttack && ((cg.time - playingSaberSwingSound) > 800)) { cgi_S_StartSound ( hiltEnt.origin, cent->gent->s.number, CHAN_AUTO, cgi_S_RegisterSound( va( "sound/weapons/saber/saberhup%d.wav", Q_irand( 1, 9 ) ) ) ); playingSaberSwingSound = cg.time; } - - //Try setting ent to be the hilt entity, then any subsequent effects below are applied to that instead - ent = &hiltEnt; } // Disruptor Gun Alt-fire @@ -4457,6 +4454,11 @@ void CG_AddSaberBlade( centity_t *cent, centity_t *scent, refEntity_t *saber, in return; } + if (vr->item_selector) + { + return; + } + /* Ghoul2 Insert Start */ @@ -5549,60 +5551,70 @@ extern vmCvar_t cg_thirdPersonAlpha; } } } + } - //play special force effects - if ( cent->gent->NPC && ( cent->gent->NPC->confusionTime > cg.time || cent->gent->NPC->charmedTime > cg.time || cent->gent->NPC->controlledTime > cg.time) ) - {// we are currently confused, so play an effect at the headBolt position - theFxScheduler.PlayEffect( cgs.effects.forceConfusion, cent->gent->client->renderInfo.eyePoint ); + //play special force effects + if ( cent->gent->NPC && ( cent->gent->NPC->confusionTime > cg.time || cent->gent->NPC->charmedTime > cg.time || cent->gent->NPC->controlledTime > cg.time) ) + {// we are currently confused, so play an effect at the headBolt position + theFxScheduler.PlayEffect( cgs.effects.forceConfusion, cent->gent->client->renderInfo.eyePoint ); + } + + if ( cent->gent->client && cent->gent->forcePushTime > cg.time ) + {//being pushed + CG_ForcePushBodyBlur( cent, ent.origin, tempAngles ); + } + + if ( cent->gent->client->ps.powerups[PW_FORCE_PUSH] > cg.time || (cent->gent->client->ps.forcePowersActive & (1<gent->client->renderInfo.handLPoint ); + } + + if ( cent->gent->client->ps.eFlags & EF_FORCE_GRIPPED ) + {//being gripped + CG_ForcePushBlur( cent->gent->client->renderInfo.headPoint ); + } + + if ( cent->gent->client && cent->gent->client->ps.powerups[PW_SHOCKED] > cg.time ) + {//being electrocuted + CG_ForceElectrocution( cent, ent.origin, tempAngles ); + } + + if ( cent->gent->client->ps.forcePowersActive&(1<gent->client->ps.clientNum == 0) + { + vec3_t origin, angles; + BG_CalculateVROffHandPosition(origin, tAng); } - - if ( cent->gent->client && cent->gent->forcePushTime > cg.time ) - {//being pushed - CG_ForcePushBodyBlur( cent, ent.origin, tempAngles ); - } - - if ( cent->gent->client->ps.powerups[PW_FORCE_PUSH] > cg.time || (cent->gent->client->ps.forcePowersActive & (1<gent->client->renderInfo.handLPoint ); - } - - if ( cent->gent->client->ps.eFlags & EF_FORCE_GRIPPED ) - {//being gripped - CG_ForcePushBlur( cent->gent->client->renderInfo.headPoint ); - } - - if ( cent->gent->client && cent->gent->client->ps.powerups[PW_SHOCKED] > cg.time ) - {//being electrocuted - CG_ForceElectrocution( cent, ent.origin, tempAngles ); - } - - if ( cent->gent->client->ps.forcePowersActive&(1<lerpAngles, tAng ); - /* - if ( cent->currentState.number ) - { - VectorSet( tAng, cent->pe.torso.pitchAngle, cent->pe.torso.yawAngle, 0 ); - } - else - {//FIXME: this dir looks right on players, but not on NPCs, NPCs pe angles are absolute, not relative? - VectorSet( tAng, tempAngles[0]+cent->pe.torso.pitchAngle, tempAngles[1]+cent->pe.torso.yawAngle, 0 ); - } - */ - if ( cent->gent->client->ps.forcePowerLevel[FP_LIGHTNING] > FORCE_LEVEL_2 ) - {//arc - vec3_t fxAxis[3]; - AnglesToAxis( tAng, fxAxis ); - theFxScheduler.PlayEffect( cgs.effects.forceLightningWide, cent->gent->client->renderInfo.handLPoint, fxAxis ); - } - else - {//line - AngleVectors( tAng, fxDir, NULL, NULL ); - theFxScheduler.PlayEffect( cgs.effects.forceLightning, cent->gent->client->renderInfo.handLPoint, fxDir ); - } + } + + /* + if ( cent->currentState.number ) + { + VectorSet( tAng, cent->pe.torso.pitchAngle, cent->pe.torso.yawAngle, 0 ); + } + else + {//FIXME: this dir looks right on players, but not on NPCs, NPCs pe angles are absolute, not relative? + VectorSet( tAng, tempAngles[0]+cent->pe.torso.pitchAngle, tempAngles[1]+cent->pe.torso.yawAngle, 0 ); + } + */ + if ( cent->gent->client->ps.forcePowerLevel[FP_LIGHTNING] > FORCE_LEVEL_2 ) + {//arc + vec3_t fxAxis[3]; + AnglesToAxis( tAng, fxAxis ); + theFxScheduler.PlayEffect( cgs.effects.forceLightningWide, cent->gent->client->renderInfo.handLPoint, fxAxis ); + } + else + {//line + AngleVectors( tAng, fxDir, NULL, NULL ); + theFxScheduler.PlayEffect( cgs.effects.forceLightning, cent->gent->client->renderInfo.handLPoint, fxDir ); } } + //As good a place as any, I suppose, to do this keyframed sound thing CGG2_AnimSounds( cent ); //setup old system for gun to look at diff --git a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_view.cpp b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_view.cpp index f3b443f..560fce5 100644 --- a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_view.cpp +++ b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_view.cpp @@ -30,6 +30,7 @@ along with this program; if not, see . #include "../game/wp_saber.h" #include "../game/anims.h" #include "../game/g_functions.h" +#include "bg_local.h" #include #define MASK_CAMERACLIP (MASK_SOLID) @@ -1309,7 +1310,7 @@ qboolean CG_CalcFOVFromX( float fov_x ) return (inwater); } -float CG_ForceSpeedFOV( void ) +float CG_ForceSpeedFOV( float infov ) { gentity_t *player = &g_entities[0]; float fov; @@ -1318,15 +1319,15 @@ float CG_ForceSpeedFOV( void ) float amt = forceSpeedFOVMod[player->client->ps.forcePowerLevel[FP_SPEED]]; if ( timeLeft < 500 ) {//start going back - fov = cg_fov.value + (timeLeft)/500*amt; + fov = infov + (timeLeft)/500*amt; } else if ( length - timeLeft < 1000 ) {//start zooming in - fov = cg_fov.value + (length - timeLeft)/1000*amt; + fov = infov + (length - timeLeft)/1000*amt; } else {//stay at this FOV - fov = cg_fov.value+amt; + fov = infov+amt; } return fov; } @@ -1357,7 +1358,7 @@ static qboolean CG_CalcFov( void ) { g_entities[cg.snap->ps.viewEntity].NPC ) {//FIXME: looks bad when take over a jedi... but never really do that, do we? //fov_x = g_entities[cg.snap->ps.viewEntity].NPC->stats.hfov; - fov_x = vr ? vr->fov : 90.0f; + fov_x = vr ? vr->fov : cg_fov.value; //sanity-cap? if ( fov_x > 120 ) { @@ -1377,13 +1378,13 @@ static qboolean CG_CalcFov( void ) { else { //fov_x = 120;//FIXME: read from the NPC's fov stats? - fov_x = vr ? vr->fov : 90.0f; + fov_x = vr ? vr->fov : cg_fov.value; } } } else if ( (!cg.zoomMode || cg.zoomMode > 2) && (cg.snap->ps.forcePowersActive&(1<client->ps.forcePowerDuration[FP_SPEED] )//cg.renderingThirdPerson && { - fov_x = CG_ForceSpeedFOV(); + fov_x = CG_ForceSpeedFOV(vr ? vr->fov : cg_fov.value); } else { /* // user selectable @@ -1401,7 +1402,7 @@ static qboolean CG_CalcFov( void ) { fov_x = 160; }*/ - fov_x = vr ? vr->fov : 90.0f; + fov_x = vr ? vr->fov : cg_fov.value; // Disable zooming when in third person if ( cg.zoomMode && cg.zoomMode < 3 )//&& !cg.renderingThirdPerson ) // light amp goggles do none of the zoom silliness @@ -1987,18 +1988,55 @@ wasForceSpeed=isForceSpeed; cgi_CM_SnapPVS( cg.refdef.vieworg, cg.snap->areamask ); } - // Don't draw the in-view weapon when in camera mode - if ( !in_camera - && !cg_pano.integer - && cg.snap->ps.weapon != WP_SABER - && ( cg.snap->ps.viewEntity == 0 || cg.snap->ps.viewEntity >= ENTITYNUM_WORLD ) ) + + + if (vr->item_selector) { - CG_AddViewWeapon( &cg.predicted_player_state ); + CG_DrawItemSelector(); } - else if( cg.snap->ps.viewEntity != 0 && cg.snap->ps.viewEntity < ENTITYNUM_WORLD && - g_entities[cg.snap->ps.viewEntity].client) - { - CG_AddViewWeapon( &g_entities[cg.snap->ps.viewEntity ].client->ps ); // HAX - because I wanted to --eez + else { + // Don't draw the in-view weapon when in camera mode + if (!in_camera + && !cg_pano.integer + && cg.snap->ps.weapon != WP_SABER + && (cg.snap->ps.viewEntity == 0 || cg.snap->ps.viewEntity >= ENTITYNUM_WORLD)) { + CG_AddViewWeapon(&cg.predicted_player_state); + } else if (cg.snap->ps.viewEntity != 0 && cg.snap->ps.viewEntity < ENTITYNUM_WORLD && + g_entities[cg.snap->ps.viewEntity].client) { + CG_AddViewWeapon( + &g_entities[cg.snap->ps.viewEntity].client->ps); // HAX - because I wanted to --eez + } + + if (!in_camera + && !cg.renderingThirdPerson + && cg.predicted_player_state.stats[STAT_HEALTH] > 0 + && !vr->weapon_stabilised + && !cg_pano.integer + && (cg.snap->ps.viewEntity == 0 || cg.snap->ps.viewEntity >= ENTITYNUM_WORLD)) + { + vec3_t end, forward; + refEntity_t handEnt; + memset( &handEnt, 0, sizeof(refEntity_t) ); + BG_CalculateVROffHandPosition(handEnt.origin, handEnt.angles); + AngleVectors(handEnt.angles, forward, NULL, NULL); + VectorMA( handEnt.origin, 8.0f, forward, end ); + + //If the current force power is directional, show the nav arrow from off-hand for now + if (showPowers[cg.forcepowerSelect] >= FP_PUSH) { + vec3_t color = {0.0f, 1.0f, 0.0f}; + FX_AddLine(handEnt.origin, end, 0.1f, 1.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + color, color, 0.0f, + 60, cgi_R_RegisterShader("gfx/misc/nav_line"), + FX_SIZE_LINEAR | FX_ALPHA_LINEAR); + } + + handEnt.renderfx = RF_DEPTHHACK; + handEnt.hModel = cgi_R_RegisterModel( "models/weapons2/thermal/thermal_hand.md3" ); + VectorCopy(handEnt.origin, handEnt.oldorigin); + AnglesToAxis(handEnt.angles, handEnt.axis); + cgi_R_AddRefEntityToScene(&handEnt); + } } if ( !cg.hyperspace ) diff --git a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_weapons.cpp b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_weapons.cpp index 871131e..5d7852a 100644 --- a/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_weapons.cpp +++ b/Projects/Android/jni/OpenJK/codeJK2/cgame/cg_weapons.cpp @@ -975,7 +975,7 @@ Add the weapon, and flash for the player's view ============== */ extern int PM_TorsoAnimForFrame( gentity_t *ent, int torsoFrame ); -extern float CG_ForceSpeedFOV( void ); +extern float CG_ForceSpeedFOV( float infov ); void CG_AddViewWeapon( playerState_t *ps ) { @@ -1066,7 +1066,7 @@ void CG_AddViewWeapon( playerState_t *ps ) gentity_t *player = &g_entities[0]; if ( (cg.snap->ps.forcePowersActive&(1<client->ps.forcePowerDuration[FP_SPEED] )//cg.renderingThirdPerson && { - actualFOV = CG_ForceSpeedFOV(); + actualFOV = CG_ForceSpeedFOV(cg_fov.value); actualFOV = (cg_fovViewmodel.integer) ? actualFOV + (cg_fovViewmodel.integer - cg_fov.integer) : actualFOV; } else @@ -1124,25 +1124,26 @@ void CG_AddViewWeapon( playerState_t *ps ) trace_t trace; VectorMA(origin, 256, forward, endForward); - static vec3_t WHITE ={1.0f,1.0f,1.0f}; + static vec3_t RED = {1.0f,0.0f,0.0f}; FX_AddLine( origin, endForward, 0.1f, 4.0f, 0.0f, 1.0f, 0.0f, 0.0f, - WHITE, WHITE, 0.0f, - 120, cgi_R_RegisterShader( "gfx/effects/redLine" ), + RED, RED, 0.0f, + 120, cgi_R_RegisterShader( "gfx/effects/whiteline2" ), FX_SIZE_LINEAR | FX_ALPHA_LINEAR ); VectorMA(origin, 20, right, endRight); - vec3_t color = { 0, 0, 255 }; + vec3_t BLUE = {0.0f,0.0f,1.0f}; FX_AddLine( origin, endRight, 0.1f, 4.0f, 0.0f, 1.0f, 0.0f, 0.0f, - color, color, 0.0f, - 120, cgi_R_RegisterShader( "gfx/misc/nav_line" ), + BLUE, BLUE, 0.0f, + 120, cgi_R_RegisterShader( "gfx/misc/whiteline2" ), FX_SIZE_LINEAR | FX_ALPHA_LINEAR ); VectorMA(origin, 20, up, endUp); + vec3_t GREEN = {0.0f,1.0f,0.0f}; FX_AddLine( origin, endUp, 0.1f, 4.0f, 0.0f, 1.0f, 0.0f, 0.0f, - WHITE, WHITE, 0.0f, + GREEN, GREEN, 0.0f, 120, cgi_R_RegisterShader( "gfx/misc/whiteline2" ), FX_SIZE_LINEAR | FX_ALPHA_LINEAR ); @@ -2141,7 +2142,9 @@ void CG_DrawWeaponSelect( void ) { int w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 1.0f); int x = ( SCREEN_WIDTH - w ) / 2; - cgi_R_Font_DrawString(x, (SCREEN_HEIGHT - 24), text, textColor, cgs.media.qhFontSmall, -1, 1.0f); + int y = (SCREEN_HEIGHT - 24); + CG_AdjustFrom640Int(&x, &y, NULL, NULL); + cgi_R_Font_DrawString(x, y, text, textColor, cgs.media.qhFontSmall, -1, 1.0f); } } @@ -2644,6 +2647,276 @@ void CG_Weapon_f( void ) cg.weaponSelect = num; } + +void Cmd_UseInventory_f(gentity_t *ent); + +//Selects the currently selected thing (if one _is_ selected) +void CG_ItemSelectorSelect_f( void ) +{ + cg.itemSelectorTime = 0; + cgi_Cvar_Set("timescale", "1.0"); + + if (cg.itemSelectorSelection == -1) + { + cg.itemSelectorType = 0; + return; + } + + if (cg.itemSelectorType == 0) + { + if (cg.weaponSelect == cg.itemSelectorSelection) + { + return; + } + + cg.weaponSelectTime = cg.time; + cg.weaponSelect = cg.itemSelectorSelection; + } + else if (cg.itemSelectorType == 1) + { + if (cg.forcepowerSelect == cg.itemSelectorSelection) + { + return; + } + + cg.forcepowerSelectTime = cg.time; + cg.forcepowerSelect = cg.itemSelectorSelection; + } + else if (cg.itemSelectorType == 2) + { + cg.inventorySelectTime = cg.time; + cg.inventorySelect = cg.itemSelectorSelection; + + //Immediately use the selected inventory item + if (player) + { + Cmd_UseInventory_f(player); + } + } + + //reset ready for next time + cg.itemSelectorType = 0; + cg.itemSelectorSelection = -1; +} + +void CG_ItemSelectorNext_f( void ) +{ + cg.itemSelectorType = (cg.itemSelectorType+1) % 3; + cg.itemSelectorTime = cg.time; +} + +void CG_ItemSelectorPrev_f( void ) +{ + if (--cg.itemSelectorType < 0) + cg.itemSelectorType = 2; + cg.itemSelectorTime = cg.time; +} + +extern int force_icons[NUM_FORCE_POWERS]; +extern int inv_icons[INV_MAX]; +qboolean CG_InventorySelectable( int index); +qboolean ForcePower_Valid(int index); + +void CG_DrawItemSelector( void ) +{ + if (cg.itemSelectorTime == 0) + { + cg.itemSelectorTime = cg.time; + VectorCopy(vr->weaponangles, cg.itemSelectorAngles); + VectorCopy(vr->weaponposition, cg.itemSelectorOrigin); + VectorCopy(vr->weaponoffset, cg.itemSelectorOffset); + } + + float dist = 10.0f; + float radius = 4.4f; + float scale = 0.05f; + + float frac = (cg.time - cg.itemSelectorTime) / 20.0f; + if (frac > 1.0f) + { + frac = 1.0f; + } + cgi_Cvar_Set("timescale", "0.22"); + + vec3_t controllerOrigin, controllerAngles, controllerOffset, selectorOrigin; + BG_CalculateVRWeaponPosition(controllerOrigin, controllerAngles); + VectorSubtract(vr->weaponposition, cg.itemSelectorOrigin, controllerOffset); + + vec3_t wheelAngles, wheelOrigin, beamOrigin, wheelForward, wheelRight, wheelUp; + BG_CalculateVRPositionInWorld(cg.itemSelectorOrigin, cg.itemSelectorOffset, cg.itemSelectorAngles, wheelOrigin, wheelAngles); + + AngleVectors(wheelAngles, wheelForward, wheelRight, wheelUp); + VectorCopy(controllerOrigin, wheelOrigin); + + VectorCopy(wheelOrigin, beamOrigin); + VectorMA(wheelOrigin, (dist * frac), wheelForward, wheelOrigin); + VectorCopy(wheelOrigin, selectorOrigin); + + vec3_t pos; + memset(&pos, 0, sizeof pos); + { + pos[0] = (sinf(DEG2RAD(wheelAngles[YAW] - controllerAngles[YAW])) / sinf(DEG2RAD(22.5f))); + pos[1] = ((wheelAngles[PITCH] - controllerAngles[PITCH]) / 22.5f); + + float len = VectorLength(pos); + if (len > 1.0f) + { + pos[0] *= (1.0f / len); + pos[1] *= (1.0f / len); + } + } + + VectorMA(selectorOrigin, radius * pos[0], wheelRight, selectorOrigin); + VectorMA(selectorOrigin, radius * pos[1], wheelUp, selectorOrigin); + + { + vec3_t color = { 0, 0, 255 }; + FX_AddLine( beamOrigin, selectorOrigin, 0.1f, 1.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + color, color, 0.0f, + 60, cgi_R_RegisterShader( "gfx/misc/nav_line" ), + FX_SIZE_LINEAR | FX_ALPHA_LINEAR ); + + } + + int count; + switch (cg.itemSelectorType) + { + case 0: //weapons + count = WP_EMPLACED_GUN; + break; + case 1: // force powers + count = MAX_SHOWPOWERS; + break; + case 2: //gadgets + count = INV_GOODIE_KEY; + break; + } + + qboolean selected = qfalse; + for (int index = 0; index < count; ++index) + { + int itemId = index; + if (cg.itemSelectorType == 0) { + itemId = index+1; // We need to ignore WP_NONE for weapons + if (itemId == count) + { + break; + } + + if (itemId == WP_SABER || + itemId == WP_BRYAR_PISTOL || + itemId == WP_BLASTER || + itemId == WP_FLECHETTE || + itemId == WP_REPEATER || + itemId == WP_THERMAL) { + CG_RegisterWeapon(itemId); + } else { + continue; + } + } + + { + bool selectable; + switch (cg.itemSelectorType) + { + case 0: //weapons + selectable = CG_WeaponSelectable(itemId, cg.weaponSelect, qfalse) && cg.snap->ps.ammo[weaponData[itemId].ammoIndex]; + break; + case 1: // force powers + selectable = ForcePower_Valid(itemId); + break; + case 2: //gadgets + selectable = CG_InventorySelectable(itemId) && inv_icons[itemId]; + break; + } + + if (selectable) { + //first calculate wheel slot position + vec3_t angles, iconOrigin, iconBackground, iconForeground; + VectorClear(angles); + angles[YAW] = wheelAngles[YAW]; + angles[PITCH] = wheelAngles[PITCH]; + angles[ROLL] = + (360 / count) * (itemId - 1); + vec3_t forward, up; + AngleVectors(angles, forward, NULL, up); + + VectorMA(wheelOrigin, (radius * frac), up, iconOrigin); + VectorMA(iconOrigin, 0.2f, forward, iconBackground); + VectorMA(iconOrigin, -0.2f, forward, iconForeground); + + { + vec3_t diff; + VectorSubtract(selectorOrigin, iconOrigin, diff); + float length = VectorLength(diff); + if (length <= 1.0f && + frac == 1.0f && + selectable) { + if (cg.itemSelectorSelection != itemId) { + cg.itemSelectorSelection = itemId; + //trap_HapticEvent("selector_icon", 0, 0, 100, 0, 0); + } + + selected = qtrue; + } + } + + if (cg.itemSelectorSelection == itemId) { + refEntity_t sprite; + memset(&sprite, 0, sizeof(sprite)); + VectorCopy(iconOrigin, sprite.origin); + sprite.origin[2] += 2.5f + (0.5f * sinf(DEG2RAD( + AngleNormalize360(cg.time - cg.itemSelectorTime)))); + sprite.reType = RT_SPRITE; + sprite.customShader = cgs.media.binocularArrow; + sprite.radius = 0.6f; + sprite.shaderRGBA[0] = 255; + sprite.shaderRGBA[1] = 255; + sprite.shaderRGBA[2] = 255; + sprite.shaderRGBA[3] = 255; + cgi_R_AddRefEntityToScene(&sprite); + } + + { + refEntity_t sprite; + memset(&sprite, 0, sizeof(sprite)); + + float sRadius = 1.3f; + + VectorCopy(iconOrigin, sprite.origin); + sprite.reType = RT_SPRITE; + switch (cg.itemSelectorType) + { + case 0: //weapons + sprite.customShader = cg_weapons[itemId].weaponIcon; + break; + case 1: // force powers + sprite.customShader = force_icons[showPowers[itemId]]; + break; + case 2: //gadgets + sprite.customShader = inv_icons[itemId]; + break; + } + + sprite.radius = + sRadius * (cg.itemSelectorSelection == itemId ? 1.3f : 0.6f); + sprite.shaderRGBA[0] = 255; + sprite.shaderRGBA[1] = 255; + sprite.shaderRGBA[2] = 255; + sprite.shaderRGBA[3] = 255; + cgi_R_AddRefEntityToScene(&sprite); + } + } + } + } + + if (!selected) + { + cg.itemSelectorSelection = -1; + } +} + /* =================== CG_OutOfAmmoChange diff --git a/Projects/Android/jni/OpenJK/codeJK2/game/bg_local.h b/Projects/Android/jni/OpenJK/codeJK2/game/bg_local.h index 38d84b8..7e5ad28 100644 --- a/Projects/Android/jni/OpenJK/codeJK2/game/bg_local.h +++ b/Projects/Android/jni/OpenJK/codeJK2/game/bg_local.h @@ -83,6 +83,7 @@ void BG_CalculateVRWeaponPosition( vec3_t origin, vec3_t angles ); void BG_CalculateVRSaberPosition( vec3_t origin, vec3_t angles ); void BG_CalculateVROffHandPosition( vec3_t origin, vec3_t angles ); void BG_ConvertFromVR(vec3_t in, vec3_t offset, vec3_t out); +void BG_CalculateVRPositionInWorld( vec3_t in_position, vec3_t in_offset, vec3_t in_orientation, vec3_t origin, vec3_t angles ); #endif diff --git a/Projects/Android/jni/OpenJK/codeJK2/game/bg_misc.cpp b/Projects/Android/jni/OpenJK/codeJK2/game/bg_misc.cpp index 6716fb0..1f5ec73 100644 --- a/Projects/Android/jni/OpenJK/codeJK2/game/bg_misc.cpp +++ b/Projects/Android/jni/OpenJK/codeJK2/game/bg_misc.cpp @@ -674,7 +674,7 @@ void BG_ConvertFromVR(vec3_t in, vec3_t offset, vec3_t out) } } -static void BG_CalculateVRPositionInWorld( vec3_t in_position, vec3_t in_offset, vec3_t in_orientation, vec3_t origin, vec3_t angles ) +void BG_CalculateVRPositionInWorld( vec3_t in_position, vec3_t in_offset, vec3_t in_orientation, vec3_t origin, vec3_t angles ) { vec3_t offset; VectorCopy(in_offset, offset); diff --git a/Projects/Android/jni/OpenJK/codeJK2/game/weapons.h b/Projects/Android/jni/OpenJK/codeJK2/game/weapons.h index c3f601a..f796fc6 100644 --- a/Projects/Android/jni/OpenJK/codeJK2/game/weapons.h +++ b/Projects/Android/jni/OpenJK/codeJK2/game/weapons.h @@ -31,9 +31,6 @@ along with this program; if not, see . #include "../../code/qcommon/q_shared.h" -//How fast the saber/melee needs to be physically swung in order to trigger sounds and trails -#define WEAPON_VELOCITY_TRIGGER 1.6f - typedef enum //# weapon_e { WP_NONE, diff --git a/Projects/Android/jni/OpenJK/codeJK2/game/wp_saber.cpp b/Projects/Android/jni/OpenJK/codeJK2/game/wp_saber.cpp index bc9b6d1..74046de 100644 --- a/Projects/Android/jni/OpenJK/codeJK2/game/wp_saber.cpp +++ b/Projects/Android/jni/OpenJK/codeJK2/game/wp_saber.cpp @@ -5706,7 +5706,15 @@ void ForceThrow( gentity_t *self, qboolean pull ) G_Sound( self, soundIndex ); - VectorCopy( self->client->ps.viewangles, fwdangles ); + if (self->client->ps.clientNum == 0) + { + vec3_t origin, angles; + BG_CalculateVROffHandPosition(origin, fwdangles); + } + else + { + VectorCopy( self->client->ps.viewangles, fwdangles ); + } //fwdangles[1] = self->client->ps.viewangles[1]; AngleVectors( fwdangles, forward, right, NULL ); VectorCopy( self->currentOrigin, center ); @@ -6226,7 +6234,16 @@ void ForceThrow( gentity_t *self, qboolean pull ) vec3_t pushDir; float damage = 800; - AngleVectors( self->client->ps.viewangles, forward, NULL, NULL ); + if (self->client->ps.clientNum == 0) + { + vec3_t origin, angles; + BG_CalculateVROffHandPosition(origin, angles); + AngleVectors(angles, forward, right, NULL); + } + else + { + AngleVectors(self->client->ps.viewangles, forward, right, NULL); + } VectorNormalize( forward ); VectorMA( self->client->renderInfo.eyePoint, radius, forward, end ); gi.trace( &tr, self->client->renderInfo.eyePoint, vec3_origin, vec3_origin, end, self->s.number, MASK_SHOT, G2_NOCOLLIDE, 0 ); @@ -6937,7 +6954,16 @@ void ForceGrip( gentity_t *self ) self->client->ps.weaponTime = floor( self->client->ps.weaponTime * g_timescale->value ); } - AngleVectors( self->client->ps.viewangles, forward, NULL, NULL ); + if (self->client->ps.clientNum == 0) + { + vec3_t origin, angles; + BG_CalculateVROffHandPosition(origin, angles); + AngleVectors(angles, forward, NULL, NULL); + } + else + { + AngleVectors(self->client->ps.viewangles, forward, NULL, NULL); + } VectorNormalize( forward ); VectorMA( self->client->renderInfo.handLPoint, FORCE_GRIP_DIST, forward, end ); @@ -7259,7 +7285,17 @@ void ForceShootLightning( gentity_t *self ) return; } - AngleVectors( self->client->ps.viewangles, forward, NULL, NULL ); + if (self->client->ps.clientNum == 0) + { + vec3_t origin, angles; + BG_CalculateVROffHandPosition(origin, angles); + AngleVectors(angles, forward, NULL, NULL); + } + else + { + AngleVectors(self->client->ps.viewangles, forward, NULL, NULL); + } + VectorNormalize( forward ); //FIXME: if lightning hits water, do water-only-flagged radius damage from that point