From 26125033dd27af82e09e34b16c89d6be289ac732 Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 22 Mar 2021 22:12:24 +0000 Subject: [PATCH] Various haptic improvements --- .../neo/game/Player.cpp | 106 +++++++++++++++--- .../drbeef/doom3quest/bhaptics/bHaptics.java | 83 ++++++++------ 2 files changed, 136 insertions(+), 53 deletions(-) diff --git a/Projects/Android/jni/d3es-multithread-master/neo/game/Player.cpp b/Projects/Android/jni/d3es-multithread-master/neo/game/Player.cpp index 2f1f7b9..9a5f86a 100644 --- a/Projects/Android/jni/d3es-multithread-master/neo/game/Player.cpp +++ b/Projects/Android/jni/d3es-multithread-master/neo/game/Player.cpp @@ -988,6 +988,9 @@ bool idInventory::Give( idPlayer *owner, const idDict &spawnArgs, const char *st if ( armor > maxarmor ) { armor = maxarmor; } + + common->HapticEvent("pickup_shield", 0, 0, amount * 5, 0, 0); + nextArmorDepleteTime = 0; armorPulse = true; } @@ -996,6 +999,8 @@ bool idInventory::Give( idPlayer *owner, const idDict &spawnArgs, const char *st if ( i != -1 ) { // set, don't add. not going over the clip size limit. clip[ i ] = atoi( value ); + + common->HapticEvent("pickup_ammo", 0, 0, 100, 0, 0); } } else if ( !idStr::Icmp( statname, "berserk" ) ) { GivePowerUp( owner, BERSERK, SEC2MS( atof( value ) ) ); @@ -1042,6 +1047,8 @@ bool idInventory::Give( idPlayer *owner, const idDict &spawnArgs, const char *st if ( ( weapons & ( 1 << i ) ) == 0 || ( duplicateWeapons & ( 1 << i ) ) == 0 || gameLocal.isMultiplayer ) { tookWeapon = true; + common->HapticEvent("pickup_weapon", 0, 0, 100, 0, 0); + if ( owner->GetUserInfo()->GetBool( "ui_autoSwitch" ) && idealWeapon ) { assert( !gameLocal.isClient ); *idealWeapon = i; @@ -3871,7 +3878,7 @@ void idPlayer::UpdateVrHud() idAngles a(0, viewAngles.yaw - pVRClientInfo->hmdorientation[YAW], 0); offpos *= a.ToMat3(); - offpos *= ((100.0f / 2.54f) * vr_scale.GetFloat()); + offpos *= vr_worldscale.GetFloat(); { hudOrigin = viewOrigin + offpos; @@ -4636,6 +4643,11 @@ bool idPlayer::GiveItem( idItem *item ) { // frame no matter what UpdateHudWeapon( false ); hud->HandleNamedEvent( "weaponPulse" ); + + if (gave) + { + common->HapticEvent("pickup_weapon", 0, 0, 100, 0, 0); + } } // display the pickup feedback on the hud @@ -5076,6 +5088,8 @@ void idPlayer::GiveSecurity( const char *security ) { hud->SetStateString( "pda_security", "1" ); hud->HandleNamedEvent( "securityPickup" ); } + + common->HapticEvent("pda_alarm", 0, 0, 100, 0, 0); } /* @@ -5095,8 +5109,11 @@ void idPlayer::GiveEmail( const char *emailName ) { if ( hud ) { hud->HandleNamedEvent( "emailPickup" ); } + + common->HapticEvent("pda_alarm", 0, 0, 100, 0, 0); } + /* =============== idPlayer::GivePDA @@ -5553,6 +5570,8 @@ void idPlayerHand::NextBestWeapon() common->Printf( "After NextBestWeapon():\n" ); debugPrint(); } + + common->HapticEvent("weapon_switch", 0, 0, 100, 0, 0); } /* @@ -5728,6 +5747,7 @@ void idPlayerHand::NextWeapon( int dir ) if( vr_debugHands.GetBool() ) common->Printf( "Changing weapon\n" ); + common->HapticEvent("weapon_switch", 0, 0, 100, 0, 0); } if( vr_debugHands.GetBool() ) { @@ -5986,6 +6006,8 @@ void idPlayerHand::SelectWeapon( int num, bool force, bool specific ) // If we made it all this way, we want weapon "num" and we can switch to it idealWeapon = num; owner->UpdateHudWeapon( whichHand ); + + common->HapticEvent("weapon_switch", 0, 0, 100, 0, 0); } common->Printf( "After SelectWeapon(%d):\n", idealWeapon); @@ -7476,6 +7498,12 @@ bool idPlayer::HandleSingleGuiCommand( idEntity *entityGui, idLexer *src ) { if ( entityGui->GetRenderEntity() && entityGui->GetRenderEntity()->gui[ 0 ] ) { entityGui->GetRenderEntity()->gui[ 0 ]->SetStateInt( "gui_parm1", _health ); } + if (health < 100) + { + //Ass health increases, play the effect higher up the body + float yHeight = -0.5f + ((float)(health+amt) / 100.0f); + common->HapticEvent("healstation", 0, 0, 100, 0, yHeight); + } health += amt; if ( health > 100 ) { health = 100; @@ -8188,6 +8216,8 @@ void idPlayer::UpdateFocus( void ) { //Rumble the controller to let player know they scored a touch. hands[fingerHand].SetControllerShake( 0.1f, 12, 0.8f, 12 ); + common->HapticEvent("pda_touch", 0, 0, 100, 0, 0); + focusTime = gameLocal.time + FOCUS_GUI_TIME; break; @@ -8399,6 +8429,8 @@ bool idPlayer::UpdateFocusPDA() // Carl: Should the PDA vibrate/haptic feedback too? hands[fingerHand].SetControllerShake( 0.1f, 12, 0.8f, 12 ); hands[pdahand].SetControllerShake( 0.1f, 12, 0.8f, 12 ); + + common->HapticEvent("pda_touch", 0, 0, 100, 0, 0); } commonVr->scanningPDA = false; return true; @@ -9843,12 +9875,16 @@ void idPlayer::TogglePDA( int hand ) { objectiveSystem->Activate( true, gameLocal.time ); hud->HandleNamedEvent( "pdaPickupHide" ); hud->HandleNamedEvent( "videoPickupHide" ); + + common->HapticEvent("pda_open", 0, 0, 100, 0, 0); } else { inventory.selPDA = objectiveSystem->State().GetInt( "listPDA_sel_0" ); inventory.selVideo = objectiveSystem->State().GetInt( "listPDAVideo_sel_0" ); inventory.selAudio = objectiveSystem->State().GetInt( "listPDAAudio_sel_0" ); inventory.selEMail = objectiveSystem->State().GetInt( "listPDAEmail_sel_0" ); objectiveSystem->Activate( false, gameLocal.time ); + + common->HapticEvent("pda_close", 0, 0, 100, 0, 0); } //objectiveSystemOpen ^= 1; objectiveSystemOpen = !objectiveSystemOpen; @@ -11535,7 +11571,7 @@ void idPlayer::UpdateFlashlightHolster() idAngles a(0, viewAngles.yaw - pVRClientInfo->hmdorientation[YAW], 0); holsterOffset *= a.ToMat3(); - holsterOffset *= ((100.0f / 2.54f) * vr_scale.GetFloat()); + holsterOffset *= vr_worldscale.GetFloat(); flashlightRenderEntity.origin = firstPersonViewOrigin + holsterOffset; flashlightRenderEntity.entityNum = ENTITYNUM_NONE; @@ -11600,16 +11636,14 @@ void idPlayer::Think( void ) { else { pVRClientInfo->weaponid = -1; } - + cvarSystem->SetCVarBool("vr_weapon_stabilised", pVRClientInfo->weapon_stabilised); int _currentWeapon = GetCurrentWeaponId(); if(_currentWeapon == WEAPON_FLASHLIGHT || _currentWeapon == WEAPON_FISTS) pVRClientInfo->velocitytriggered = true; else pVRClientInfo->velocitytriggered = false; pVRClientInfo->velocitytriggeredoffhand = true; - - pVRClientInfo->oneHandOnly = (_currentWeapon == WEAPON_FISTS) || - (_currentWeapon == weapon_handgrenade); + pVRClientInfo->pistol = GetCurrentWeaponId() == WEAPON_PISTOL; } // clear the ik before we do anything else so the skeleton doesn't get updated twice @@ -11760,6 +11794,12 @@ void idPlayer::Think( void ) { UpdatePowerUps(); + if (health > 0 && health < 40) + { + //heartbeat is a special case that uses intensity for a different purpose + common->HapticEvent("heartbeat", 0, 0, health, 0, 0); + } + //UpdateFlashlightHolster(); //Dr Beef version - maybe minimise @@ -12468,6 +12508,13 @@ void idPlayer::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &di if ( armorSave ) { inventory.armor -= armorSave; + if (inventory.armor == 0) + { + if ( IsType( idPlayer::Type ) ) { + common->HapticEvent("shield_break", 0, 0, 100, 0, 0); + } + } + if ( gameLocal.time > lastArmorPulse + 200 ) { StartSound( "snd_hitArmor", SND_CHANNEL_ITEM, 0, false, NULL ); } @@ -12476,6 +12523,11 @@ void idPlayer::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &di if ( damageDef->dict.GetBool( "burn" ) ) { StartSound( "snd_burn", SND_CHANNEL_BODY3, 0, false, NULL ); + + if ( IsType( idPlayer::Type ) ) { + common->HapticEvent("fire", 0, 0, 50, 0, 0); + } + } else if ( damageDef->dict.GetBool( "no_air" ) ) { if ( !armorSave && health > 0 ) { StartSound( "snd_airGasp", SND_CHANNEL_ITEM, 0, false, NULL ); @@ -12560,6 +12612,33 @@ void idPlayer::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &di } } + if ( IsType( idPlayer::Type ) && + //Save the effort of going through this code if bhaptics isn't enabled + vr_bhaptics.GetBool()) { + idVec3 bodyOrigin = vec3_zero; + idMat3 bodyAxis; + GetViewPos( bodyOrigin, bodyAxis ); + idAngles bodyAng = bodyAxis.ToAngles(); + + float yHeight = idMath::ClampFloat(-0.5f, 0.5f, damage_from.ToPitch() / 45.0f); + float damageYaw = 180 + (damage_from.ToYaw() - bodyAng.yaw); + if (damageYaw < 0.0f) + damageYaw += 360.0f; + if (damageYaw >= 360.0f) + damageYaw -= 360.0f; + + //Ensure a decent level of haptic feedback for any damage + float hapticLevel = 80 + Min(damage * 4, 120.0); + + //Indicate head damage if appropriate + if ( location >= 0 && location < damageGroups.Size() && + strstr( damageGroups[location].c_str(), "head" ) ) { + common->HapticEvent(damageDefName, 4, 0, hapticLevel, damageYaw, yHeight); + } else { + common->HapticEvent(damageDefName, 0, 0, hapticLevel, damageYaw, yHeight); + } + } + lastDamageDef = damageDef->Index(); lastDamageDir = damage_from; lastDamageLocation = location; @@ -13168,7 +13247,7 @@ void idPlayer::CalculateViewWeaponPos( int hand, idVec3& origin, idMat3& axis ) idAngles a(0, viewAngles.yaw - pVRClientInfo->hmdorientation[YAW], 0); gunpos *= a.ToMat3(); - gunpos *= ((100.0f / 2.54f) * vr_scale.GetFloat()); + gunpos *= cvarSystem->GetCVarFloat( "vr_worldscale" ); if (GetCurrentWeaponId( == WEAPON_FLASHLIGHT) // Flashlight adjustment { @@ -13389,11 +13468,8 @@ void idPlayer::CalculateViewWeaponPosVR( int hand, idVec3 &origin, idMat3 &axis commonVr->MotionControlGetHand( hand, hands[ hand ].motionPosition, hands[ hand ].motionRotation ); - if (!commonVr->GetWeaponStabilised()) - { - weaponPitch = idAngles( vr_motionWeaponPitchAdj.GetFloat(), 0.0f, 0.0f ).ToQuat(); - hands[hand].motionRotation = weaponPitch * hands[hand].motionRotation; - } + weaponPitch = idAngles( vr_motionWeaponPitchAdj.GetFloat(), 0.0f, 0.0f ).ToQuat(); + hands[ hand ].motionRotation = weaponPitch * hands[ hand ].motionRotation; GetViewPos( weapOrigin, weapAxis ); @@ -13665,10 +13741,6 @@ void idPlayer::CalculateViewFlashlightPos( idVec3 &origin, idMat3 &axis, idVec3 axis = idAngles( 0.0, viewAngles.yaw - commonVr->bodyYawOffset, 0.0f ).ToMat3(); int flashlightMode = commonVr->GetCurrentFlashlightMode(); - if (commonVr->GetWeaponStabilised() && flashlightMode == FLASHLIGHT_HAND ) - { - flashlightMode = FLASHLIGHT_GUN; - } setLeftHand = false; //move the flashlight to alternate location for items with no mount @@ -13952,7 +14024,7 @@ idVec3 idPlayer::GetEyePosition( void ) const { if (pVRClientInfo) { float eyeHeight = 0; - float vrEyeHeight = (-(pVRClientInfo->hmdposition[1] + vr_heightoffset.GetFloat()) * ((100.0f / 2.54f) * vr_scale.GetFloat())); + float vrEyeHeight = (-(pVRClientInfo->hmdposition[1] + vr_heightoffset.GetFloat()) * vr_worldscale.GetFloat()); //Add special handling for physical crouching at some point if (physicsObj.IsCrouching() && PHYSICAL_CROUCH) { diff --git a/java/com/drbeef/doom3quest/bhaptics/bHaptics.java b/java/com/drbeef/doom3quest/bhaptics/bHaptics.java index cf7ef53..5d7d126 100644 --- a/java/com/drbeef/doom3quest/bhaptics/bHaptics.java +++ b/java/com/drbeef/doom3quest/bhaptics/bHaptics.java @@ -132,6 +132,7 @@ public class bHaptics { registerFromAsset(context, "bHaptics/Interaction/Vest/Body_Door_Open.tact", "dooropen", "door"); registerFromAsset(context, "bHaptics/Interaction/Vest/Body_Door_Close.tact", "doorclose", "door"); registerFromAsset(context, "bHaptics/Interaction/Vest/Body_Scan.tact", PositionType.Vest, "scan", "environment", 1.0f, 1.15f); + registerFromAsset(context, "bHaptics/Interaction/Vest/Body_Scan.tact", PositionType.Vest, "decontaminate", "environment", 0.5f, 0.65f); registerFromAsset(context, "bHaptics/Interaction/Vest/Body_Chamber_Up.tact", "liftup", "environment"); registerFromAsset(context, "bHaptics/Interaction/Vest/Body_Chamber_Down.tact", "liftdown", "environment"); registerFromAsset(context, "bHaptics/Interaction/Vest/Body_Machine.tact", "machine", "environment"); @@ -308,10 +309,11 @@ public class bHaptics { /* position values: - 0 - Will play on both arms if tactosy tact files present for both - 1 - Will play on left arm only if tactosy tact files present for left - 2 - Will play on right arm only if tactosy tact files present for right + 0 - Will play on vest and both arms if tactosy tact files present for both + 1 - Will play on vest and on left arm only if tactosy tact files present for left + 2 - Will play on vest and on right arm only if tactosy tact files present for right 3 - Will play on head only (if present) + 4 - Will play on all devices (that have a pattern defined for them) flag values: 0 - No flags set @@ -366,46 +368,52 @@ public class bHaptics { intensity = 100; } - if (position > 0) { - BhapticsManager manager = BhapticsModule.getBhapticsManager(); - - //If playing left position and haptic type is right, don;t play that one - if (position == 1 && haptic.type == PositionType.ForearmR) - { - continue; - } - - //If playing right position and haptic type is left, don;t play that one - if (position == 2 && haptic.type == PositionType.ForearmL) - { - continue; - } - - - if (position == 3 && - (haptic.type != PositionType.Head || !manager.isDeviceConnected(BhapticsManager.DeviceType.Head))) - { - continue; - } - - if (position != 3 && haptic.type == PositionType.Head) - { - continue; - } - } - - if (haptic != null) { float flIntensity = ((intensity / 100.0F) * haptic.intensity); - float duration = haptic.duration; + float flAngle = angle; + float flDuration = haptic.duration; - //Special hack for heartbeat + if (position > 0) + { + BhapticsManager manager = BhapticsModule.getBhapticsManager(); + + //If playing left position and haptic type is right, don;t play that one + if (position == 1 && haptic.type == PositionType.ForearmR) + { + continue; + } + + //If playing right position and haptic type is left, don;t play that one + if (position == 2 && haptic.type == PositionType.ForearmL) + { + continue; + } + + + if (position == 3 && + (haptic.type != PositionType.Head || !manager.isDeviceConnected(BhapticsManager.DeviceType.Head))) + { + continue; + } + + if (haptic.type == PositionType.Head) { + if (position < 3) { + continue; + } + + //Zero angle for head + flAngle = 0; + } + } + + //Special values for heartbeat if (haptic.group.compareTo("health") == 0) { //The worse condition we are in, the faster the heart beats! float health = intensity; - duration = 1.0f - (0.4f * ((40 - health) / 40)); + flDuration = 1.0f - (0.4f * ((40 - health) / 40)); flIntensity = 1.0f; + flAngle = 0; } //If this is a repeating event, then add to the set to play in begin frame @@ -414,7 +422,7 @@ public class bHaptics { repeatingHaptics.put(key, haptic); } else { - player.submitRegistered(haptic.key, haptic.altKey, flIntensity, duration, angle, yHeight); + player.submitRegistered(haptic.key, haptic.altKey, flIntensity, flDuration, flAngle, yHeight); } } } @@ -479,6 +487,9 @@ public class bHaptics { } else if (key.contains("entrance_scanner") || key.contains("scanner_rot1s")) { key = "scan"; + } else if (key.contains("decon_started")) + { + key = "decontaminate"; } return key; }