Weapon haptics working rather nicely!
World shake also triggers haptics
Velocity triggered attack for the  flashlight and chainsaw
vr_chibi (thanks to RBDOOM-BFG) just for a bit of a laugh
This commit is contained in:
Simon 2020-09-17 22:46:48 +01:00
parent a8f3d92ee0
commit 6defa52225
14 changed files with 122 additions and 69 deletions

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.drbeef.doom3quest"
android:versionCode="1"
android:versionName="0.0.1" android:installLocation="auto" >
android:versionCode="3"
android:versionName="0.0.9" android:installLocation="auto" >
<!-- Tell the system this app requires OpenGL ES 3.1. -->
<uses-feature android:glEsVersion="0x00030001" android:required="true"/>

View file

@ -20,7 +20,7 @@ typedef struct {
bool dualwield;
int weaponid;
int lastweaponid;
int backpackitemactive; //0 - nothing, 1 - grenades, 2 - knife, 3 - Binoculars
int holsteritemactive; //0 - nothing, 1 - flashlight
bool mountedgun;
vec3_t hmdposition;

View file

@ -11,7 +11,7 @@ enum control_scheme;
#define SCOPE_ENGAGE_DISTANCE 0.25
#define VSTOCK_ENGAGE_DISTANCE 0.25
#define BINOCULAR_ENGAGE_DISTANCE 0.25
#define VELOCITY_TRIGGER 1.6
#define VELOCITY_TRIGGER 1.4
ovrInputStateTrackedRemote leftTrackedRemoteState_old;
ovrInputStateTrackedRemote leftTrackedRemoteState_new;

View file

@ -60,6 +60,7 @@ int Sys_Milliseconds( void ) {
void Android_SetImpuse(int impulse);
void Android_SetCommand(const char * cmd);
void Android_ButtonChange(int key, int state);
extern bool inMenu;
extern bool inGameGuiActive;
@ -248,7 +249,7 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
if (fired != velocityTriggeredAttack) {
ALOGV("**WEAPON EVENT** veocity triggered %s", velocityTriggeredAttack ? "+attack" : "-attack");
sendButtonAction("+attack", velocityTriggeredAttack);
Android_ButtonChange(UB_ATTACK, velocityTriggeredAttack ? 1 : 0);
fired = velocityTriggeredAttack;
}
}
@ -257,7 +258,7 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
//send a stop attack as we have an unfinished velocity attack
velocityTriggeredAttack = false;
ALOGV("**WEAPON EVENT** veocity triggered -attack");
sendButtonAction("+attack", velocityTriggeredAttack);
Android_ButtonChange(UB_ATTACK, velocityTriggeredAttack ? 1 : 0);
}
if (pVRClientInfo->weapon_stabilised)
@ -280,7 +281,7 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
if (pDominantTracking->Status & (VRAPI_TRACKING_STATUS_POSITION_TRACKED | VRAPI_TRACKING_STATUS_POSITION_VALID)) {
canUseBackpack = false;
}
else if (!canUseBackpack && pVRClientInfo->backpackitemactive == 0) {
else if (!canUseBackpack && pVRClientInfo->holsteritemactive == 0) {
int channel = (vr_control_scheme >= 10) ? 0 : 1;
Doom3Quest_Vibrate(40, channel, 0.5); // vibrate to let user know they can switch
@ -289,10 +290,6 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
dominantGripPushed = (pDominantTrackedRemoteNew->Buttons &
ovrButton_GripTrigger) != 0;
bool dominantButton1Pushed = (pDominantTrackedRemoteNew->Buttons &
domButton1) != 0;
bool dominantButton2Pushed = (pDominantTrackedRemoteNew->Buttons &
domButton2) != 0;
if (!canUseBackpack)
{
@ -303,60 +300,33 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
}
else
{
if (pVRClientInfo->backpackitemactive == 1) {
if (pVRClientInfo->holsteritemactive == 1) {
//Restores last used weapon if possible
if (pVRClientInfo->weaponid != -1) {
Android_SetImpuse(UB_IMPULSE0 + pVRClientInfo->weaponid);
}
pVRClientInfo->backpackitemactive = 0;
pVRClientInfo->holsteritemactive = 0;
}
else if ((GetTimeInMilliSeconds() - dominantGripPushTime) < vr_reloadtimeoutms) {
//Reload
Android_SetImpuse(UB_IMPULSE13);
}
dominantGripPushTime = 0;
}
if (!dominantButton1Pushed && pVRClientInfo->backpackitemactive == 2)
{
//Restores last used weapon if possible
if (pVRClientInfo->weaponid != -1) {
Android_SetImpuse(UB_IMPULSE0 + pVRClientInfo->weaponid);
}
pVRClientInfo->backpackitemactive = 0;
}
if (!dominantButton2Pushed && pVRClientInfo->backpackitemactive == 3)
{
pVRClientInfo->backpackitemactive = 0;
}
} else {
if (pVRClientInfo->backpackitemactive == 0) {
if (pVRClientInfo->holsteritemactive == 0) {
if (dominantGripPushed) {
pVRClientInfo->lastweaponid = pVRClientInfo->weaponid;
//Initiate flashlight from backpack mode
Android_SetImpuse(UB_IMPULSE11);
int channel = (vr_control_scheme >= 10) ? 0 : 1;
Doom3Quest_Vibrate(80, channel, 0.8); // vibrate to let user know they switched
pVRClientInfo->backpackitemactive = 1;
}
/*else if (dominantButton1Pushed)
{
pVRClientInfo->lastweaponid = pVRClientInfo->weaponid;
//Initiate knife from backpack mode
sendButtonActionSimple("weapon 1");
int channel = (vr_control_scheme >= 10) ? 0 : 1;
Doom3Quest_Vibrate(80, channel, 0.8); // vibrate to let user know they switched
pVRClientInfo->backpackitemactive = 2;
pVRClientInfo->holsteritemactive = 1;
}
else if (dominantButton2Pushed && pVRClientInfo->hasbinoculars)
{
int channel = (vr_control_scheme >= 10) ? 0 : 1;
Doom3Quest_Vibrate(80, channel, 0.8); // vibrate to let user know they switched
pVRClientInfo->backpackitemactive = 3;
}*/
}
}
}
@ -399,7 +369,7 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
positional_movementForward = v[1];
//Jump (B Button)
if (pVRClientInfo->backpackitemactive != 2 && !canUseBackpack) {
if (pVRClientInfo->holsteritemactive != 2 && !canUseBackpack) {
if ((primaryButtonsNew & primaryButton2) != (primaryButtonsOld & primaryButton2))
{
@ -409,7 +379,7 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
//Fire Primary
if (pVRClientInfo->backpackitemactive != 3 && // Can't fire while holding binoculars
if (pVRClientInfo->holsteritemactive != 3 && // Can't fire while holding binoculars
!pVRClientInfo->velocitytriggered && // Don't fire velocity triggered weapons
(pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger) !=
(pDominantTrackedRemoteOld->Buttons & ovrButton_Trigger)) {
@ -420,7 +390,7 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
}
//Duck
if (pVRClientInfo->backpackitemactive != 2 &&
if (pVRClientInfo->holsteritemactive != 2 &&
!canUseBackpack &&
(primaryButtonsNew & primaryButton1) !=
(primaryButtonsOld & primaryButton1)) {

View file

@ -162,7 +162,9 @@ public:
virtual int ButtonState( int key );
virtual int KeyState( int key );
// DG: hack to allow adding callbacks and exporting additional functions without breaking the game ABI
virtual void Vibrate(int duration, int channel, float intensity );
// DG: hack to allow adding callbacks and exporting additional functions without breaking the game ABI
// see Common.h for longer explanation...
// returns true if setting the callback was successful, else false
@ -2382,6 +2384,13 @@ void idCommonLocal::InitSIMD( void ) {
extern "C" void Doom3Quest_setUseScreenLayer(int use);
extern "C" void Doom3Quest_FrameSetup();
extern "C" void Doom3Quest_Vibrate(int duration, int channel, float intensity );
void idCommonLocal::Vibrate(int duration, int channel, float intensity )
{
Doom3Quest_Vibrate(duration, channel, intensity );
}
/*
=================

View file

@ -212,6 +212,9 @@ public:
// Directly sample a keystate.
virtual int KeyState( int key ) = 0;
//Haptic Feedback
virtual void Vibrate(int duration, int channel, float intensity ) = 0;
/* Some Mods (like Ruiner and DarkMod when it still was a mod) used "SourceHook"
* to override Doom3 Methods to call their own code before the original method
* was executed.. this is super ugly and probably not super portable either.

View file

@ -459,6 +459,26 @@ void idAFAttachment::Think( void ) {
}
}
/*
================
idAfAttachment::GetPhysicsToVisualTransform
================
*/
idCVar vr_chibi("vr_chibi", "1.0", CVAR_FLOAT | CVAR_ARCHIVE, "changes the size of human heads.");
bool idAFAttachment::GetPhysicsToVisualTransform( idVec3& origin, idMat3& axis )
{
const float scale = vr_chibi.GetFloat();
if( scale > 0.f && scale != 1.0f )
{
static const idVec3 offset( -1.8f, 0, -8.f);
axis = mat3_identity * scale;
origin = (scale - 1.f) / scale * offset;
return true;
}
return false;
}
/*
================
idAFAttachment::SetCombatModel

View file

@ -131,6 +131,8 @@ public:
virtual void LinkCombat( void );
virtual void UnlinkCombat( void );
virtual bool GetPhysicsToVisualTransform( idVec3& origin, idMat3& axis );
protected:
idEntity * body;
idClipModel * combatModel; // render model for hit detection of head

View file

@ -6236,7 +6236,15 @@ void idPlayer::Think( void ) {
return;
}
// clear the ik before we do anything else so the skeleton doesn't get updated twice
if (pVRClientInfo != nullptr)
{
pVRClientInfo->weaponid = currentWeapon;
cvarSystem->SetCVarBool("vr_weapon_stabilised", pVRClientInfo->weapon_stabilised);
pVRClientInfo->velocitytriggered = (currentWeapon == 11 || // 11 is flashlight
currentWeapon == 10); // 10 is chainsaw
}
// clear the ik before we do anything else so the skeleton doesn't get updated twice
walkIK.ClearJointMods();
// if this is the very first frame of the map, set the delta view angles
@ -6418,11 +6426,6 @@ void idPlayer::Think( void ) {
playerView.CalculateShake();
}
if (pVRClientInfo != nullptr)
{
pVRClientInfo->weaponid = currentWeapon;
}
if ( !( thinkFlags & TH_THINK ) ) {
gameLocal.Printf( "player %d not thinking?\n", entityNumber );
}
@ -6620,6 +6623,12 @@ void idPlayer::DamageFeedback( idEntity *victim, idEntity *inflictor, int &damag
if ( damage && ( victim != this ) && victim->IsType( idActor::Type ) ) {
SetLastHitTime( gameLocal.time );
}
if (victim == this)
{
common->Vibrate(250, 0, damage / 50);
common->Vibrate(250, 1, damage / 50);
}
}
/*
@ -7306,7 +7315,7 @@ idVec3 idPlayer::GetEyePosition( void ) const {
if (pVRClientInfo)
{
float eyeHeight = 0;
float vrEyeHeight = (-pVRClientInfo->hmdposition[1] * cvarSystem->GetCVarFloat( "vr_worldscale" ));
float vrEyeHeight = (-(pVRClientInfo->hmdposition[1] + cvarSystem->GetCVarFloat( "vr_heightoffset" )) * cvarSystem->GetCVarFloat( "vr_worldscale" ));
//Add special handling for physical crouching at some point
/* if (physicsObj.IsCrouching() && PHYSICAL_CROUCH) {
@ -8215,6 +8224,11 @@ void idPlayer::ReadFromSnapshot( const idBitMsgDelta &msg ) {
if ( weapon.GetEntity() ) {
weapon.GetEntity()->OwnerDied();
}
{
common->Vibrate(250, 0, 1.0);
common->Vibrate(250, 1, 1.0);
}
} else if ( oldHealth <= 0 && health > 0 ) {
// respawn
Init();
@ -8235,6 +8249,11 @@ void idPlayer::ReadFromSnapshot( const idBitMsgDelta &msg ) {
} else {
common->Warning( "NET: no damage def for damage feedback '%d'\n", lastDamageDef );
}
{
common->Vibrate(250, 0, 0.6);
common->Vibrate(250, 1, 0.6);
}
}
} else if ( health > oldHealth && PowerUpActive( MEGAHEALTH ) && !stateHitch ) {
// just pulse, for any health raise

View file

@ -369,6 +369,20 @@ void idPlayerView::WeaponFireFeedback( const idDict *weaponDef ) {
kickFinishTime = finish;
}
//Defined for the VR weapons - defaults in case they are missing
float controllerShakeHighMag = weaponDef->GetFloat( "controllerShakeHighMag", "1.0" );
int controllerShakeHighTime = weaponDef->GetInt( "controllerShakeHighTime", "0" );
bool rightHanded = cvarSystem->GetCVarInteger("vr_control_scheme") == 0;
if (controllerShakeHighTime == 0)
{
controllerShakeHighTime = recoilTime / 2;
}
common->Vibrate(controllerShakeHighTime, rightHanded ? 1 : 0, controllerShakeHighMag);
if (cvarSystem->GetCVarBool("vr_weapon_stabilised"))
{
common->Vibrate(controllerShakeHighTime, rightHanded ? 0 : 1, controllerShakeHighMag);
}
}
/*
@ -389,6 +403,12 @@ void idPlayerView::CalculateShake() {
shakeAng[0] = gameLocal.random.CRandomFloat() * shakeVolume;
shakeAng[1] = gameLocal.random.CRandomFloat() * shakeVolume;
shakeAng[2] = gameLocal.random.CRandomFloat() * shakeVolume;
if (shakeVolume > 0.05) {
//Shake controllers!
common->Vibrate(50, 0, idMath::ClampFloat(0.3, 1.0, (shakeVolume*2.0f + 0.1f)));
common->Vibrate(50, 1, idMath::ClampFloat(0.3, 1.0, (shakeVolume*2.0f + 0.1f)));
}
}
/*

View file

@ -1102,12 +1102,15 @@ void idWeapon::UpdateFlashPosition( void ) {
GetGlobalJointTransform( true, flashJointView, muzzleFlash.origin, muzzleFlash.axis );
// if the desired point is inside or very close to a wall, back it up until it is clear
idVec3 start = muzzleFlash.origin - playerViewAxis[0] * 16;
idVec3 end = muzzleFlash.origin + playerViewAxis[0] * 8;
//idVec3 start = muzzleFlash.origin - playerViewAxis[0] * 16;
idVec3 start = muzzleFlash.origin - viewWeaponAxis[0] * 16;
//idVec3 end = muzzleFlash.origin + playerViewAxis[0] * 8;
idVec3 end = muzzleFlash.origin + viewWeaponAxis[0] * 8;
trace_t tr;
gameLocal.clip.TracePoint( tr, start, end, MASK_SHOT_RENDERMODEL, owner );
// be at least 8 units away from a solid
muzzleFlash.origin = tr.endpos - playerViewAxis[0] * 8;
//muzzleFlash.origin = tr.endpos - playerViewAxis[0] * 8;
muzzleFlash.origin = tr.endpos - viewWeaponAxis[0] * 8;
// put the world muzzle flash on the end of the joint, no matter what
GetGlobalJointTransform( false, flashJointWorld, worldMuzzleFlash.origin, worldMuzzleFlash.axis );
@ -2876,9 +2879,8 @@ void idWeapon::Event_LaunchProjectiles( int num_projectiles, float spread, float
// there is an explicit joint for the muzzle
GetGlobalJointTransform( true, barrelJointView, muzzleOrigin, muzzleAxis );
} else {
// go straight out of the view
muzzleOrigin = playerViewOrigin;
muzzleAxis = playerViewAxis;
muzzleOrigin = viewWeaponOrigin;
muzzleAxis = viewWeaponAxis;
}
// add some to the kick time, incrementally moving repeat firing weapons back
@ -2895,11 +2897,13 @@ void idWeapon::Event_LaunchProjectiles( int num_projectiles, float spread, float
// predict instant hit projectiles
if ( projectileDict.GetBool( "net_instanthit" ) ) {
float spreadRad = DEG2RAD( spread );
muzzle_pos = muzzleOrigin + playerViewAxis[ 0 ] * 2.0f;
//muzzle_pos = muzzleOrigin + playerViewAxis[ 0 ] * 2.0f;
muzzle_pos = muzzleOrigin + viewWeaponAxis[ 0 ] * 2.0f;
for( i = 0; i < num_projectiles; i++ ) {
ang = idMath::Sin( spreadRad * gameLocal.random.RandomFloat() );
spin = (float)DEG2RAD( 360.0f ) * gameLocal.random.RandomFloat();
dir = playerViewAxis[ 0 ] + playerViewAxis[ 2 ] * ( ang * idMath::Sin( spin ) ) - playerViewAxis[ 1 ] * ( ang * idMath::Cos( spin ) );
//dir = playerViewAxis[ 0 ] + playerViewAxis[ 2 ] * ( ang * idMath::Sin( spin ) ) - playerViewAxis[ 1 ] * ( ang * idMath::Cos( spin ) );
dir = viewWeaponAxis[ 0 ] + viewWeaponAxis[ 2 ] * ( ang * idMath::Sin( spin ) ) - viewWeaponAxis[ 1 ] * ( ang * idMath::Cos( spin ) );
dir.Normalize();
gameLocal.clip.Translation( tr, muzzle_pos, muzzle_pos + dir * 4096.0f, NULL, mat3_identity, MASK_SHOT_RENDERMODEL, owner );
if ( tr.fraction < 1.0f ) {
@ -3000,8 +3004,9 @@ void idWeapon::Event_Melee( void ) {
}
if ( !gameLocal.isClient ) {
idVec3 start = playerViewOrigin;
idVec3 end = start + playerViewAxis[0] * ( meleeDistance * owner->PowerUpModifier( MELEE_DISTANCE ) );
idVec3 start = viewWeaponOrigin;
//idVec3 end = start + playerViewAxis[0] * ( meleeDistance * owner->PowerUpModifier( MELEE_DISTANCE ) );
idVec3 end = start + viewWeaponAxis[0] * ( meleeDistance * owner->PowerUpModifier( MELEE_DISTANCE ) );
gameLocal.clip.TracePoint( tr, start, end, MASK_SHOT_RENDERMODEL, owner );
if ( tr.fraction < 1.0f ) {
ent = gameLocal.GetTraceEntity( tr );
@ -3163,7 +3168,8 @@ void idWeapon::Event_EjectBrass( void ) {
debris->Create( owner, origin, axis );
debris->Launch();
linear_velocity = 40 * ( playerViewAxis[0] + playerViewAxis[1] + playerViewAxis[2] );
//linear_velocity = 40 * ( playerViewAxis[0] + playerViewAxis[1] + playerViewAxis[2] );
linear_velocity = 40 * ( viewWeaponAxis[0] + viewWeaponAxis[1] + viewWeaponAxis[2] );
angular_velocity.Set( 10 * gameLocal.random.CRandomFloat(), 10 * gameLocal.random.CRandomFloat(), 10 * gameLocal.random.CRandomFloat() );
debris->GetPhysics()->SetLinearVelocity( linear_velocity );

View file

@ -339,7 +339,9 @@ idCVar net_serverDlTable( "net_serverDlTable", "", CVAR_GAME | CVAR_ARCHIV
idCVar vr_ipd( "vr_ipd", "0.065", CVAR_GAME | CVAR_FLOAT | CVAR_ARCHIVE, "VR IPD" );
idCVar vr_worldscale( "vr_worldscale", "40.0", CVAR_GAME | CVAR_FLOAT | CVAR_ARCHIVE, "VR World Scale" );
idCVar vr_worldscale( "vr_worldscale", "45.0", CVAR_GAME | CVAR_FLOAT | CVAR_ARCHIVE, "VR World Scale" );
idCVar vr_heightoffset( "vr_heightoffset", "0.0", CVAR_GAME | CVAR_FLOAT | CVAR_ARCHIVE, "VR Height Offset" );
idCVar vr_eye( "vr_eye", "0", CVAR_GAME | CVAR_INTEGER, "VR Eye currently being drawn" );
idCVar vr_control_scheme( "vr_control_scheme", "0", CVAR_GAME | CVAR_INTEGER, "VR Control Scheme: 0 = right handed, 10 = left handed" );

View file

@ -255,6 +255,8 @@ extern idCVar net_clientLagOMeter;
extern idCVar vr_ipd;
extern idCVar vr_worldscale;
extern idCVar vr_eye;
extern idCVar vr_heightoffset;
extern idCVar vr_control_scheme;
extern const char *si_gameTypeArgs[];

View file

@ -300,7 +300,7 @@ void idDeviceContext::SetMenuScaleForVR( bool enable ) {
float offsetX = (1.0f - scaleX) * (VIRTUAL_WIDTH * 0.5f);
float offsetY = (1.0f - scaleY) * (VIRTUAL_HEIGHT * 0.5f);
fixScaleForMenu.Set(scaleX, scaleY);
fixOffsetForMenu.Set(offsetX + (eye==0 ? 14 : -14), offsetY);
fixOffsetForMenu.Set(offsetX + (eye==0 ? 20 : -20), offsetY);
} else {
fixScaleForMenu.Set(1, 1);
fixOffsetForMenu.Set(0, 0);