HAPTICS!!!

Controller only so far - still needs some things implemented, but mostly there
This commit is contained in:
Simon 2022-11-17 00:05:01 +00:00
parent 85f642e9e7
commit 077cfe159e
14 changed files with 163 additions and 45 deletions

View file

@ -848,16 +848,23 @@ JKVR_Vibrate
float vibration_channel_duration[2] = {0.0f, 0.0f};
float vibration_channel_intensity[2] = {0.0f, 0.0f};
void JKVR_Vibrate( int duration, int channel, float intensity )
void JKVR_Vibrate( int duration, int chan, float intensity )
{
if (vibration_channel_duration[channel] > 0.0f)
return;
for (int i = 0; i < 2; ++i)
{
int channel = (i + 1) & chan;
if (channel)
{
if (vibration_channel_duration[channel-1] > 0.0f)
return;
if (vibration_channel_duration[channel] == -1.0f && duration != 0.0f)
return;
if (vibration_channel_duration[channel-1] == -1.0f && duration != 0.0f)
return;
vibration_channel_duration[channel] = duration;
vibration_channel_intensity[channel] = intensity;
vibration_channel_duration[channel-1] = duration;
vibration_channel_intensity[channel-1] = intensity * vr_haptic_intensity->value;
}
}
}
void JKVR_GetMove(float *forward, float *side, float *pos_forward, float *pos_side, float *up,
@ -1337,6 +1344,7 @@ void JKVR_Init()
vr_irl_crouch_enabled = Cvar_Get ("vr_irl_crouch_enabled", "0", CVAR_ARCHIVE);
vr_irl_crouch_to_stand_ratio = Cvar_Get ("vr_irl_crouch_to_stand_ratio", "0.65", CVAR_ARCHIVE);
vr_saber_block_debounce_time = Cvar_Get ("vr_saber_block_debounce_time", "200", CVAR_ARCHIVE);
vr_haptic_intensity = Cvar_Get ("vr_haptic_intensity", "1.0", CVAR_ARCHIVE);
cvar_t *expanded_menu_enabled = Cvar_Get ("expanded_menu_enabled", "0", CVAR_ARCHIVE);
if (FS_FileExists("expanded_menu.pk3")) {
@ -1636,7 +1644,7 @@ void JKVR_processHaptics() {
for (int i = 0; i < 2; ++i) {
if (vibration_channel_duration[i] > 0.0f ||
vibration_channel_duration[i] == -1.0f) {
vrapi_SetHapticVibrationSimple(gAppState.Ovr, controllerIDs[i],
vrapi_SetHapticVibrationSimple(gAppState.Ovr, controllerIDs[1 - i],
vibration_channel_intensity[i]);
if (vibration_channel_duration[i] != -1.0f) {
@ -1648,11 +1656,73 @@ void JKVR_processHaptics() {
}
}
} else {
vrapi_SetHapticVibrationSimple(gAppState.Ovr, controllerIDs[i], 0.0f);
vrapi_SetHapticVibrationSimple(gAppState.Ovr, controllerIDs[1 - i], 0.0f);
}
}
}
void JKVR_HapticEvent(const char* event, int position, int flags, int intensity, float angle, float yHeight )
{
if (vr_haptic_intensity->value == 0.0f)
{
return;
}
// engine_t* engine = VR_GetEngine();
// jstring StringArg1 = (*(engine->java.Env))->NewStringUTF(engine->java.Env, event);
// (*(engine->java.Env))->CallVoidMethod(engine->java.Env, engine->java.ActivityObject, android_haptic_event, StringArg1, position, flags, (int)(intensity * vr_hapticIntensity->value), angle, yHeight);
//Controller Haptic Support
int weaponFireChannel = vr.weapon_stabilised ? 3 : (vr_control_scheme->integer ? 2 : 1);
if (flags != 0)
{
weaponFireChannel = flags;
}
if (strcmp(event, "pickup_shield") == 0 ||
strcmp(event, "pickup_weapon") == 0 ||
strstr(event, "pickup_item") != NULL)
{
JKVR_Vibrate(100, 3, 1.0);
}
else if (strcmp(event, "weapon_switch") == 0)
{
JKVR_Vibrate(250, vr_control_scheme->integer ? 2 : 1, 0.8);
}
else if (strcmp(event, "shotgun") == 0 || strcmp(event, "fireball") == 0)
{
JKVR_Vibrate(400, 3, 1.0);
}
else if (strcmp(event, "bullet") == 0)
{
JKVR_Vibrate(150, 3, 1.0);
}
else if (strcmp(event, "chainsaw_fire") == 0 ||
strcmp(event, "RTCWQuest:fire_tesla") == 0)
{
JKVR_Vibrate(500, weaponFireChannel, 1.0);
}
else if (strcmp(event, "machinegun_fire") == 0 || strcmp(event, "plasmagun_fire") == 0)
{
JKVR_Vibrate(90, weaponFireChannel, 0.8);
}
else if (strcmp(event, "shotgun_fire") == 0)
{
JKVR_Vibrate(250, weaponFireChannel, 1.0);
}
else if (strcmp(event, "rocket_fire") == 0 ||
strcmp(event, "RTCWQuest:fire_sniper") == 0 ||
strcmp(event, "bfg_fire") == 0 ||
strcmp(event, "handgrenade_fire") == 0 )
{
JKVR_Vibrate(400, weaponFireChannel, 1.0);
}
else if (strcmp(event, "selector_icon") == 0)
{
//Quick blip
JKVR_Vibrate(50, flags, 1.0);
}
}
void showLoadingIcon()
{
int frameFlags = 0;

View file

@ -17,4 +17,5 @@ extern cvar_t *vr_crouch_toggle;
extern cvar_t *vr_irl_crouch_enabled;
extern cvar_t *vr_irl_crouch_to_stand_ratio;
extern cvar_t *vr_saber_block_debounce_time;
extern cvar_t *vr_haptic_intensity;

View file

@ -37,6 +37,7 @@ cvar_t *vr_crouch_toggle;
cvar_t *vr_irl_crouch_enabled;
cvar_t *vr_irl_crouch_to_stand_ratio;
cvar_t *vr_saber_block_debounce_time;
cvar_t *vr_haptic_intensity;
ovrInputStateTrackedRemote leftTrackedRemoteState_old;
ovrInputStateTrackedRemote leftTrackedRemoteState_new;

View file

@ -221,7 +221,8 @@ Ghoul2 Insert End
CG_OPENJK_MENU_PAINT,
CG_OPENJK_GETMENU_BYNAME,
CG_CVAR_GET
CG_CVAR_GET,
CG_HAPTICEVENT
} cgameImport_t;
#ifdef JK2_MODE
@ -348,6 +349,7 @@ Ghoul2 Insert End
CG_OPENJK_MENU_PAINT_JK2,
CG_OPENJK_GETMENU_BYNAME_JK2,
CG_CVAR_GET_JK2,
CG_HAPTICEVENT_JK2
} cgameJK2Import_t;
#endif

View file

@ -467,6 +467,9 @@ cgameImport_t CL_ConvertJK2SysCall( cgameJK2Import_t import )
case CG_CVAR_GET_JK2:
return CG_CVAR_GET;
break;
case CG_HAPTICEVENT_JK2:
return CG_HAPTICEVENT;
break;
case CG_ARGC_JK2:
return CG_ARGC;
break;
@ -1378,6 +1381,9 @@ Ghoul2 Insert End
return strlen(text);
#endif
case CG_HAPTICEVENT:
JKVR_HapticEvent( (const char*)VMA(1), args[2], args[3], args[4], VMF(5), VMF(6) );
return 0;
default:
Com_Error( ERR_DROP, "Bad cgame system trap: %ld", (long int) args[0] );
}

View file

@ -841,6 +841,8 @@ void CL_Frame ( int msec,float fractionMsec ) {
JKVR_processHaptics();
//trigger frame tick for haptics
JKVR_HapticEvent("frame_tick", 0, 0, 0, 0, 0);
// see if we need to update any userinfo
CL_CheckUserinfo();

View file

@ -41,6 +41,10 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
#include "qcommon/stringed_ingame.h"
#include <JKVR/VrClientInfo.h>
extern vr_client_info_t vr;
void UI_LoadMenus(const char *menuFile, qboolean reset);
extern vmCvar_t ui_char_color_red;
@ -9159,7 +9163,7 @@ void Item_MouseEnter(itemDef_t *item, float x, float y)
}
}
void JKVR_HapticEvent(const char* event, int position, int flags, int intensity, float angle, float yHeight );
/*
=================
@ -9244,6 +9248,7 @@ qboolean Item_SetFocus(itemDef_t *item, float x, float y)
if (playSound && sfx)
{
DC->startLocalSound( *sfx, CHAN_LOCAL_SOUND );
JKVR_HapticEvent("selector_icon", 0, vr.right_handed ? 1 : 2, 60, 0, 0);
}
for (i = 0; i < parent->itemCount; i++)

View file

@ -478,6 +478,7 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
// show icon and name on status bar
if ( es->number == cg.snap->ps.clientNum ) {
CG_ItemPickup( index, bHadItem );
cgi_HapticEvent("pickup_weapon", 0, 0, 80, 0, 0);
}
}
break;
@ -511,6 +512,8 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
}
}
cgi_HapticEvent("weapon_switch", 0, 0, 100, 0, 0);
// FIXME: if it happens that you don't want the saber to play the switch sounds, feel free to modify this bit.
if ( weaponData[cg.weaponSelect].selectSnd[0] )
{
@ -564,7 +567,11 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
cg.powerupActive = PW_BATTLESUIT;
cg.powerupTime = cg.time;
}
//cgi_S_StartSound (NULL, es->number, CHAN_ITEM, cgs.media.invulnoProtectSound );
if ( clientNum == cg.snap->ps.clientNum ) {
cgi_HapticEvent("decontaminate", 0, 0, 100, 0, 0);
}
//cgi_S_StartSound (NULL, es->number, CHAN_ITEM, cgs.media.invulnoProtectSound );
break;
//=================================================================
@ -766,6 +773,9 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
return;
}
*/
if ( clientNum == cg.snap->ps.clientNum ) {
cgi_HapticEvent("fireball", 0, 0, 100, 0, 0);
}
CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*death%i.wav", event - EV_DEATH1 + 1), CS_BASIC );
break;

View file

@ -972,6 +972,9 @@ void cgi_Cvar_Set( const char *var_name, const char *value );
char* cgi_Cvar_Get( const char *var_name );
//Haptics
int cgi_HapticEvent( char *description, int position, int channel, int intensity, float yaw, float height);
// ServerCommand and ConsoleCommand parameter access
int cgi_Argc( void );
void cgi_Argv( int n, char *buffer, int bufferLength );

View file

@ -204,6 +204,13 @@ void CG_DamageFeedback( int yawByte, int pitchByte, int damage ) {
cg.damageValue = kick;
cg.v_dmg_time = cg.time + DAMAGE_TIME;
cg.damageTime = cg.snap->serverTime;
if (damage > 30)
{
cgi_HapticEvent("shotgun", 0, 0, 100, yaw, 0);
} else {
cgi_HapticEvent("bullet", 0, 0, 100, yaw, 0);
}
}

View file

@ -198,7 +198,8 @@ Ghoul2 Insert End
CG_OPENJK_MENU_PAINT,
CG_OPENJK_GETMENU_BYNAME,
CG_CVAR_GET
CG_CVAR_GET,
CG_HAPTICEVENT
} cgameImport_t;
//----------------------------------------------

View file

@ -421,6 +421,10 @@ void cgi_R_WorldEffectCommand( const char *command )
Q_syscall( CG_R_WORLD_EFFECT_COMMAND, command );
}
int cgi_HapticEvent( char *description, int position, int channel, int intensity, float yaw, float height) {
return Q_syscall( CG_HAPTICEVENT, description, position, channel, intensity, PASSFLOAT(yaw), PASSFLOAT(height));
}
// this returns a handle. arg0 is the name in the format "idlogo.roq", set arg1 to NULL, alteredstates to qfalse (do not alter gamestate)
int trap_CIN_PlayCinematic( const char *arg0, int xpos, int ypos, int width, int height, int bits, const char *psAudioFile /* = NULL */) {
return Q_syscall(CG_CIN_PLAYCINEMATIC, arg0, xpos, ypos, width, height, bits, psAudioFile);

View file

@ -3040,7 +3040,9 @@ void CG_DrawItemSelector( void )
selectable) {
if (cg.itemSelectorSelection != itemId) {
cg.itemSelectorSelection = itemId;
//trap_HapticEvent("selector_icon", 0, 0, 100, 0, 0);
cgi_HapticEvent("selector_icon", 0, vr->right_handed ?
((cg.itemSelectorType == 3) ? 2 : 1) : ((cg.itemSelectorType == 3) ? 1 : 2), 100, 0, 0);
}
selected = qtrue;
@ -3231,51 +3233,46 @@ void CG_FireWeapon( centity_t *cent, qboolean alt_fire )
}
}
// Do overcharge sound that get's added to the top
/* if (( ent->powerups & ( 1<<PW_WEAPON_OVERCHARGE )))
//Are we the player?
if (cent->gent->client->ps.clientNum == 0)
{
if ( alt_fire )
{
switch( ent->weapon )
{
case WP_THERMAL:
case WP_DET_PACK:
case WP_TRIP_MINE:
case WP_ROCKET_LAUNCHER:
case WP_FLECHETTE:
// these weapon fires don't overcharge
break;
int position = vr->weapon_stabilised ? 4 : (vr->right_handed ? 1 : 2);
//Haptics
switch (ent->weapon) {
case WP_SABER:
cgi_HapticEvent("chainsaw_fire", position, 0, 50, 0, 0);
break;
case WP_BRYAR_PISTOL:
case WP_BOWCASTER:
case WP_BLASTER:
cgi_S_StartSound( NULL, ent->number, CHAN_AUTO, cgs.media.overchargeFastSound );
cgi_HapticEvent("machinegun_fire", position, 0, 100, 0, 0);
break;
default:
cgi_S_StartSound( NULL, ent->number, CHAN_AUTO, cgs.media.overchargeSlowSound );
case WP_BLASTER_PISTOL:
cgi_HapticEvent("shotgun_fire", position, 0, 100, 0, 0);
break;
}
}
else
{
switch( ent->weapon )
{
case WP_THERMAL:
case WP_DET_PACK:
case WP_TRIP_MINE:
cgi_HapticEvent("handgrenade_fire", position, 0, 80, 0, 0);
break;
case WP_ROCKET_LAUNCHER:
// these weapon fires don't overcharge
cgi_HapticEvent("rocket_fire", position, 0, 100, 0, 0);
break;
case WP_DISRUPTOR:
cgi_HapticEvent("RTCWQuest:fire_sniper", position, 0, 100, 0, 0);
break;
case WP_FLECHETTE:
case WP_REPEATER:
cgi_S_StartSound( NULL, ent->number, CHAN_AUTO, cgs.media.overchargeFastSound );
cgi_HapticEvent("plasmagun_fire", position, 0, 100, 0, 0);
break;
default:
cgi_S_StartSound( NULL, ent->number, CHAN_AUTO, cgs.media.overchargeSlowSound );
case WP_DEMP2:
case WP_EMPLACED_GUN:
cgi_HapticEvent("bfg_fire", position, 0, 100, 0, 0);
break;
}
}
}*/
}
}
/*

View file

@ -5716,6 +5716,11 @@ void ForceThrowEx( gentity_t *self, qboolean pull, qboolean aimByViewAngles )
parts = SETANIM_BOTH;
}
}
//Handle this here so it is refreshed on every frame, not just when the lightning gun is first fired
cgi_HapticEvent("RTCWQuest:fire_tesla", 0, (vr->right_handed ? 2 : 1), 100, 0, 0);
NPC_SetAnim( self, parts, anim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_RESTART );
self->client->ps.saberMove = self->client->ps.saberBounceMove = LS_READY;//don't finish whatever saber anim you may have been in
self->client->ps.saberBlocked = BLOCKED_NONE;
@ -7326,6 +7331,10 @@ void ForceShootLightning( gentity_t *self )
VectorNormalize( forward );
//Handle this here so it is refreshed on every frame, not just when the lightning gun is first fired
cgi_HapticEvent("RTCWQuest:fire_tesla", 0, (vr->right_handed ? 2 : 1), 100, 0, 0);
//FIXME: if lightning hits water, do water-only-flagged radius damage from that point
if ( self->client->ps.forcePowerLevel[FP_LIGHTNING] > FORCE_LEVEL_2 )
{//arc