Improved Spectator/Follow mode

- Spectator / Follow mode will now be 3rd person, with the person you are following marked with an icon
- Optional Laser Sight for aiming (in VR Menu)
- Toggle to send Roll angles to the server
- Removed very janky first person body option
This commit is contained in:
Simon 2022-03-04 18:19:18 +00:00
parent 2abe93692b
commit 1c823b6943
13 changed files with 184 additions and 126 deletions

View File

@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.drbeef.ioq3quest"
android:installLocation="preferExternal"
android:versionCode="24"
android:versionName="0.17.0">
android:versionCode="25"
android:versionName="0.18.0">
<uses-feature android:name="android.hardware.vr.headtracking" android:version="1" android:required="true" />
<uses-feature android:glEsVersion="0x00030001" />
<!-- <uses-feature android:name="oculus.software.overlay_keyboard" android:required="false"/>-->

View File

@ -2726,8 +2726,7 @@ void CG_DrawActive( stereoFrame_t stereoView ) {
VectorCopy( cg.refdef.vieworg, baseOrg );
float worldscale = trap_Cvar_VariableValue("vr_worldscale");
if (cg.snap->ps.pm_type == PM_SPECTATOR ||
(cg.snap->ps.pm_flags & PMF_FOLLOW))
if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW))
{
worldscale *= SPECTATOR_WORLDSCALE_MULTIPLIER;
}
@ -2749,7 +2748,10 @@ void CG_DrawActive( stereoFrame_t stereoView ) {
//If connected to external server, allow some amount of faked positional tracking
cg.refdef.vieworg[2] -= PLAYER_HEIGHT;
cg.refdef.vieworg[2] += vr->hmdposition[1] * worldscale;
if (cg.snap->ps.stats[STAT_HEALTH] > 0)
if (cg.snap->ps.stats[STAT_HEALTH] > 0 &&
//Don't use fake positional if following another player - this is handled in the
//VR third person code
!( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW)))
{
vec3_t pos, hmdposition, vieworg;
VectorClear(pos);

View File

@ -527,6 +527,9 @@ typedef struct {
refdef_t refdef;
vec3_t refdefViewAngles; // will be converted to refdef.viewaxis
// view origin in VR thirdperson
vec3_t vr_vieworigin;
// zoom key
qboolean zoomed;
int zoomTime;
@ -1396,6 +1399,7 @@ void CG_GrappleTrail( centity_t *ent, const weaponInfo_t *wi );
void CG_AddViewWeapon (playerState_t *ps);
void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent, int team );
void CG_DrawWeaponSelect( void );
void CG_LaserSight( vec3_t start, vec3_t end );
void CG_OutOfAmmoChange( void ); // should this be in pmove?

View File

@ -150,7 +150,6 @@ vmCvar_t cg_ignore;
vmCvar_t cg_simpleItems;
vmCvar_t cg_fov;
vmCvar_t cg_zoomFov;
vmCvar_t cg_firstPersonBodyScale;
vmCvar_t cg_thirdPerson;
vmCvar_t cg_thirdPersonRange;
vmCvar_t cg_thirdPersonAngle;
@ -277,7 +276,6 @@ static cvarTable_t cvarTable[] = {
{ &cg_tracerLength, "cg_tracerlength", "100", CVAR_CHEAT },
{ &cg_thirdPersonRange, "cg_thirdPersonRange", "40", CVAR_CHEAT },
{ &cg_thirdPersonAngle, "cg_thirdPersonAngle", "0", CVAR_CHEAT },
{ &cg_firstPersonBodyScale, "cg_firstPersonBodyScale", "0", 0 },
{ &cg_thirdPerson, "cg_thirdPerson", "0", 0 },
{ &cg_teamChatTime, "cg_teamChatTime", "3000", CVAR_ARCHIVE },
{ &cg_teamChatHeight, "cg_teamChatHeight", "0", CVAR_ARCHIVE },
@ -960,8 +958,8 @@ static void CG_RegisterGraphics( void ) {
cgs.media.dustPuffShader = trap_R_RegisterShader("hasteSmokePuff" );
#endif
cgs.media.friendShader = trap_R_RegisterShader( "sprites/foe" );
if ( cgs.gametype >= GT_TEAM || cg_buildScript.integer ) {
cgs.media.friendShader = trap_R_RegisterShader( "sprites/foe" );
cgs.media.redQuadShader = trap_R_RegisterShader("powerups/blueflag" );
cgs.media.teamStatusBar = trap_R_RegisterShader( "gfx/2d/colorbar.tga" );
#ifdef MISSIONPACK

View File

@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../vr/vr_clientinfo.h"
extern vr_clientinfo_t* vr;
extern vmCvar_t cg_firstPersonBodyScale;
char *cg_customSoundNames[MAX_CUSTOM_SOUNDS] = {
"*death1.wav",
@ -2028,6 +2027,14 @@ Float sprites over the player's head
static void CG_PlayerSprites( centity_t *cent ) {
int team;
//Put a sprite over the followed player's head
if ( cent->currentState.number == cg.snap->ps.clientNum &&
cg.renderingThirdPerson &&
cg.snap->ps.pm_flags & PMF_FOLLOW) {
CG_PlayerFloatSprite( cent, cgs.media.friendShader );
return;
}
if ( cent->currentState.eFlags & EF_CONNECTION ) {
CG_PlayerFloatSprite( cent, cgs.media.connectionShader );
return;
@ -2358,20 +2365,11 @@ void CG_Player( centity_t *cent ) {
return;
}
//Are we drawing the first person body
qboolean firstPersonBody = ( cent->currentState.number == cg.snap->ps.clientNum) &&
(!cg.renderingThirdPerson) &&
(cg_firstPersonBodyScale.value > 0.0f) &&
( cgs.gametype != GT_SINGLE_PLAYER );
// get the player model information
renderfx = 0;
if ( cent->currentState.number == cg.snap->ps.clientNum) {
if (!cg.renderingThirdPerson) {
if (cg_firstPersonBodyScale.value == 0 ||
cgs.gametype == GT_SINGLE_PLAYER) {
renderfx = RF_THIRD_PERSON; // only draw in mirrors
}
renderfx = RF_THIRD_PERSON; // only draw in mirrors
} else {
if (cg_cameraMode.integer) {
return;
@ -2385,25 +2383,8 @@ void CG_Player( centity_t *cent ) {
memset( &head, 0, sizeof(head) );
// get the rotation information
if (firstPersonBody)
{
vec3_t angles;
VectorClear(angles);
angles[YAW] = cg.refdefViewAngles[YAW] + vr->hmdorientation[YAW] - vr->weaponangles[YAW];
AnglesToAxis(angles, legs.axis);
VectorScale( legs.axis[0], cg_firstPersonBodyScale.value, legs.axis[0] );
VectorScale( legs.axis[1], cg_firstPersonBodyScale.value, legs.axis[1] );
VectorScale( legs.axis[2], cg_firstPersonBodyScale.value, legs.axis[2] );
AnglesToAxis(vec3_origin, torso.axis);
VectorScale( torso.axis[0], cg_firstPersonBodyScale.value, torso.axis[0] );
VectorScale( torso.axis[1], cg_firstPersonBodyScale.value, torso.axis[1] );
VectorScale( torso.axis[2], cg_firstPersonBodyScale.value, torso.axis[2] );
//Don't care about head
}
else {
CG_PlayerAngles(cent, legs.axis, torso.axis, head.axis);
}
CG_PlayerAngles(cent, legs.axis, torso.axis, head.axis);
// get the animation state (after rotation, to allow feet shuffle)
CG_PlayerAnimation( cent, &legs.oldframe, &legs.frame, &legs.backlerp,
&torso.oldframe, &torso.frame, &torso.backlerp );
@ -2689,10 +2670,7 @@ void CG_Player( centity_t *cent ) {
head.shadowPlane = shadowPlane;
head.renderfx = renderfx;
if (!firstPersonBody)
{
CG_AddRefEntityWithPowerups(&head, &cent->currentState, ci->team);
}
CG_AddRefEntityWithPowerups(&head, &cent->currentState, ci->team);
#ifdef MISSIONPACK
CG_BreathPuffs(cent, &head);
@ -2703,9 +2681,7 @@ void CG_Player( centity_t *cent ) {
//
// add the gun / barrel / flash
//
if (!firstPersonBody) {
CG_AddPlayerWeapon(&torso, NULL, cent, ci->team);
}
CG_AddPlayerWeapon(&torso, NULL, cent, ci->team);
// add powerups floating behind the player
CG_PlayerPowerups( cent, &torso );

View File

@ -226,17 +226,35 @@ CG_OffsetVRThirdPersonView
*/
static void CG_OffsetVRThirdPersonView( void ) {
float scale = 1.0f;
if (cg.predictedPlayerState.pm_type == PM_SPECTATOR ||
(cg.predictedPlayerState.pm_flags & PMF_FOLLOW))
if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW))
{
scale *= SPECTATOR_WORLDSCALE_MULTIPLIER;
//Check to see if the followed player has moved far enough away to mean we should update our location
vec3_t currentOrigin;
VectorCopy(cg.refdef.vieworg, currentOrigin);
VectorSubtract(currentOrigin, cg.vr_vieworigin, currentOrigin);
currentOrigin[2] = 0;
if (VectorLength(currentOrigin) > 400)
{
VectorCopy(cg.refdef.vieworg, cg.vr_vieworigin);
//Move behind the player
vec3_t angles;
vec3_t forward, right, up;
VectorCopy(vr->clientviewangles, angles);
angles[PITCH] = 0;
AngleVectors( angles, forward, right, up );
VectorMA( cg.vr_vieworigin, -60, forward, cg.vr_vieworigin );
}
}
else if (( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) &&
( cg.predictedPlayerState.pm_type != PM_INTERMISSION ))
{
scale *= DEATH_WORLDSCALE_MULTIPLIER;
}
VectorCopy(cg.refdef.vieworg, cg.vr_vieworigin);
}
{
vec3_t position;
@ -244,7 +262,7 @@ static void CG_OffsetVRThirdPersonView( void ) {
CG_ConvertFromVR(position, NULL, position);
position[2] = 0;
VectorScale(position, scale, position);
VectorAdd(cg.refdef.vieworg, position, cg.refdef.vieworg);
VectorAdd(cg.vr_vieworigin, position, cg.refdef.vieworg);
}
}
@ -628,7 +646,6 @@ CG_CalcViewValues
Sets cg.refdef view values
===============
*/
void CG_RailTrail2( clientInfo_t *ci, vec3_t start, vec3_t end );
static int CG_CalcViewValues( stereoFrame_t stereoView ) {
playerState_t *ps;
@ -646,8 +663,9 @@ static int CG_CalcViewValues( stereoFrame_t stereoView ) {
//HACK!! - should change this to a renderer function call
//Indicate to renderer whether we are in deathcam mode, We don't want sky in death cam mode
trap_Cvar_Set( "vr_noSkybox", (((ps->stats[STAT_HEALTH] <= 0) &&
( ps->pm_type != PM_INTERMISSION )) || ps->pm_type == PM_SPECTATOR ||
(ps->pm_flags & PMF_FOLLOW)) ? "1" : "0" );
( ps->pm_type != PM_INTERMISSION )) ||
cg.demoPlayback ||
(cg.snap->ps.pm_flags & PMF_FOLLOW) ? "1" : "0" ));
// intermission view
static float hmdYaw = 0;
@ -702,23 +720,26 @@ static int CG_CalcViewValues( stereoFrame_t stereoView ) {
}
}
if (cg.snap->ps.stats[STAT_HEALTH] <= 0 ||
ps->pm_type == PM_SPECTATOR ||
ps->pm_flags & PMF_FOLLOW) {
if (( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) &&
( cg.predictedPlayerState.pm_type != PM_INTERMISSION ) ||
( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW)))
{
//If dead, or spectating, view the map from above
CG_OffsetVRThirdPersonView();
} else if ( cg.renderingThirdPerson ) {
}
else if ( cg.renderingThirdPerson )
{
// back away from character
CG_OffsetThirdPersonView();
} else {
}
else
{
// offset for local bobbing and kicks
CG_OffsetFirstPersonView();
}
if (!cgs.localServer && stereoView == STEREO_LEFT)
{
VectorCopy(vr->calculated_weaponangles, vr->last_calculated_weaponangles);
vec3_t weaponorigin, weaponangles;
CG_CalculateVRWeaponPosition(weaponorigin, weaponangles);
@ -731,9 +752,7 @@ static int CG_CalcViewValues( stereoFrame_t stereoView ) {
if (cg_debugWeaponAiming.integer)
{
clientInfo_t ci;
VectorSet(ci.color1, 1, 0, 0); // Forward is red
CG_RailTrail2(&ci, weaponorigin, trace.endpos);
CG_LaserSight(weaponorigin, trace.endpos);
}
{
@ -758,9 +777,7 @@ static int CG_CalcViewValues( stereoFrame_t stereoView ) {
if (cg_debugWeaponAiming.integer)
{
clientInfo_t ci;
VectorSet(ci.color1, 0, 1, 0);
CG_RailTrail2(&ci, cg.refdef.vieworg, trace2.endpos);
CG_LaserSight(cg.refdef.vieworg, trace2.endpos);
}
//convert to real-world angles - should be very close to real weapon angles
@ -780,7 +797,7 @@ static int CG_CalcViewValues( stereoFrame_t stereoView ) {
angles[ROLL] = vr->hmdorientation[ROLL];
AnglesToAxis( angles, cg.refdef.viewaxis );
}
else if (ps->pm_flags & PMF_FOLLOW)
else if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW))
{
//If we're following someone,
vec3_t angles;
@ -794,8 +811,8 @@ static int CG_CalcViewValues( stereoFrame_t stereoView ) {
//angles as we send orientation to the server that includes the weapon angles
vec3_t angles;
VectorCopy(vr->hmdorientation, angles);
angles[YAW] =
(cg.refdefViewAngles[YAW] + vr->hmdorientation[YAW]) - vr->last_calculated_weaponangles[YAW];
float deltaYaw = SHORT2ANGLE(cg.predictedPlayerState.delta_angles[YAW]);
angles[YAW] = deltaYaw + vr->clientviewangles[YAW];
AnglesToAxis(angles, cg.refdef.viewaxis);
}
} else {
@ -805,7 +822,17 @@ static int CG_CalcViewValues( stereoFrame_t stereoView ) {
angles[PITCH] = vr->weaponangles[PITCH];
angles[YAW] = (cg.refdefViewAngles[YAW] - vr->hmdorientation[YAW]) + vr->weaponangles[YAW];
AnglesToAxis(angles, cg.refdef.viewaxis);
} else {
}
else if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW))
{
//If we're following someone,
vec3_t angles;
VectorCopy(vr->hmdorientation, angles);
angles[YAW] = vr->clientviewangles[YAW];
AnglesToAxis(angles, cg.refdef.viewaxis);
}
else
{
AnglesToAxis(cg.refdefViewAngles, cg.refdef.viewaxis);
}
}
@ -927,7 +954,7 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo
// decide on third person view
cg.renderingThirdPerson = cg.predictedPlayerState.pm_type == PM_SPECTATOR ||
cg.predictedPlayerState.pm_flags & PMF_FOLLOW ||
cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW) ||
cg_thirdPerson.integer;
// build cg.refdef

View File

@ -235,6 +235,11 @@ void CG_ConvertFromVR(vec3_t in, vec3_t offset, vec3_t out)
//We are connected to a multiplayer server, so make the appropriate adjustment to the view
//angles as we send orientation to the server that includes the weapon angles
float deltaYaw = SHORT2ANGLE(cg.predictedPlayerState.delta_angles[YAW]);
if (cg.snap->ps.pm_flags & PMF_FOLLOW)
{
//Don't include delta if following another player
deltaYaw = 0.0f;
}
float angleYaw = deltaYaw + (vr->clientviewangles[YAW] - vr->hmdorientation[YAW]);
rotateAboutOrigin(vrSpace[0], vrSpace[1], angleYaw, r);
} else {
@ -259,8 +264,7 @@ static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles );
void CG_CalculateVRWeaponPosition( vec3_t origin, vec3_t angles )
{
if (cg.predictedPlayerState.pm_type == PM_SPECTATOR ||
cg.predictedPlayerState.pm_flags & PMF_FOLLOW)
if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW))
{
CG_CalculateWeaponPosition(origin, angles);
return;
@ -482,45 +486,30 @@ static void CG_NailgunEjectBrass( centity_t *cent ) {
/*
==========================
CG_RailTrail2
CG_LaserSight
==========================
*/
void CG_RailTrail2( clientInfo_t *ci, vec3_t start, vec3_t end ) {
localEntity_t *le;
refEntity_t *re;
void CG_LaserSight( vec3_t start, vec3_t end ) {
refEntity_t re;
memset( &re, 0, sizeof( re ) );
le = CG_AllocLocalEntity();
re = &le->refEntity;
//Ensure shader is loaded
cgs.media.railCoreShader = trap_R_RegisterShader( "railCore" );
le->leType = LE_FADE_RGB;
le->startTime = cg.time;
le->endTime = cg.time + 15;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
re.reType = RT_LASERSIGHT;
re.customShader = cgs.media.railCoreShader;
re->shaderTime = cg.time / 1000.0f;
re->reType = RT_RAIL_CORE;
re->customShader = cgs.media.railCoreShader;
VectorCopy( start, re.origin );
VectorCopy( end, re.oldorigin );
VectorCopy( start, re->origin );
VectorCopy( end, re->oldorigin );
AxisClear( re.axis );
// // still allow different colors so we can tell AI shots from player shots, etc.
le->color[3] = 1.0f;
if ( ci ) {
if (ci->health == 1)
{
le->color[3] = (ci->handicap / 255.0f);
}
le->color[0] = ci->color1[0] * 0.75;
le->color[1] = ci->color1[1] * 0.75;
le->color[2] = ci->color1[2] * 0.75;
} else {
le->color[0] = 1;
le->color[1] = 0;
le->color[2] = 0;
}
re.shaderRGBA[0] = 0xff;
re.shaderRGBA[1] = 0x00;
re.shaderRGBA[2] = 0x00;
re.shaderRGBA[3] = 0x40;
AxisClear( re->axis );
trap_R_AddRefEntityToScene(&re);
}
/*
@ -1712,7 +1701,18 @@ void CG_AddViewWeapon( playerState_t *ps ) {
// set up gun position
CG_CalculateVRWeaponPosition( hand.origin, angles );
//Scale / Move gun etc
if (trap_Cvar_VariableValue("vr_lasersight") != 0.0f)
{
vec3_t forward, end, dir;
AngleVectors(angles, forward, NULL, NULL);
VectorMA(hand.origin, 4096, forward, end);
trace_t trace;
CG_Trace(&trace, hand.origin, NULL, NULL, end, cg.predictedPlayerState.clientNum,
MASK_SOLID);
CG_LaserSight(hand.origin, trace.endpos);
}
//Scale / Move gun etc
float scale = 1.0f;
{
char cvar_name[64];

View File

@ -52,10 +52,11 @@ VR OPTIONS MENU
#define ID_DRAWHUD 138
#define ID_ROLLHIT 139
#define ID_HUDYOFFSET 140
#define ID_BODYSCALE 141
#define ID_GORE 142
#define ID_SENDROLL 141
#define ID_LASERSIGHT 142
#define ID_GORE 143
#define ID_BACK 143
#define ID_BACK 144
#define NUM_HUDDEPTH 6
#define NUM_DIRECTIONMODE 2
@ -83,7 +84,8 @@ typedef struct {
menuradiobutton_s scope;
menuradiobutton_s rollhit;
menuslider_s hudyoffset;
menuslider_s bodyscale;
menuradiobutton_s sendroll;
menuradiobutton_s lasersight;
menulist_s gore;
menubitmap_s back;
@ -121,7 +123,8 @@ static void VR_SetMenuItems( void ) {
s_VR.scope.curvalue = trap_Cvar_VariableValue( "vr_weaponScope" ) != 0;
s_VR.rollhit.curvalue = trap_Cvar_VariableValue( "vr_rollWhenHit" ) != 0;
s_VR.hudyoffset.curvalue = trap_Cvar_VariableValue( "vr_hudYOffset" ) + 200;
s_VR.bodyscale.curvalue = trap_Cvar_VariableValue( "cg_firstPersonBodyScale" );
s_VR.sendroll.curvalue = trap_Cvar_VariableValue( "vr_sendRollToServer" ) != 0;
s_VR.lasersight.curvalue = trap_Cvar_VariableValue( "vr_lasersight" ) != 0;
//GORE
{
@ -208,8 +211,12 @@ static void VR_Event( void* ptr, int notification ) {
trap_Cvar_SetValue( "vr_hudYOffset", s_VR.hudyoffset.curvalue - 200);
break;
case ID_BODYSCALE:
trap_Cvar_SetValue( "cg_firstPersonBodyScale", s_VR.bodyscale.curvalue);
case ID_SENDROLL:
trap_Cvar_SetValue( "vr_sendRollToServer", s_VR.sendroll.curvalue);
break;
case ID_LASERSIGHT:
trap_Cvar_SetValue( "vr_lasersight", s_VR.lasersight.curvalue);
break;
case ID_GORE: {
@ -322,7 +329,7 @@ static void VR_MenuInit( void ) {
s_VR.framer.width = 256;
s_VR.framer.height = 334;
y = 120;
y = 100;
s_VR.drawhud.generic.type = MTYPE_RADIOBUTTON;
s_VR.drawhud.generic.name = "Draw HUD:";
s_VR.drawhud.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
@ -453,16 +460,23 @@ static void VR_MenuInit( void ) {
s_VR.hudyoffset.minvalue = 0;
s_VR.hudyoffset.maxvalue = 400;
y += BIGCHAR_HEIGHT;
s_VR.bodyscale.generic.type = MTYPE_SLIDER;
s_VR.bodyscale.generic.name = "1st-Person Body Scale:";
s_VR.bodyscale.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
s_VR.bodyscale.generic.callback = VR_Event;
s_VR.bodyscale.generic.id = ID_BODYSCALE;
s_VR.bodyscale.generic.x = VR_X_POS;
s_VR.bodyscale.generic.y = y;
s_VR.bodyscale.minvalue = 0.0f;
s_VR.bodyscale.maxvalue = 1.0f;
y += BIGCHAR_HEIGHT;
s_VR.sendroll.generic.type = MTYPE_RADIOBUTTON;
s_VR.sendroll.generic.name = "Send Roll Angle to Server:";
s_VR.sendroll.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
s_VR.sendroll.generic.callback = VR_Event;
s_VR.sendroll.generic.id = ID_SENDROLL;
s_VR.sendroll.generic.x = VR_X_POS;
s_VR.sendroll.generic.y = y;
y += BIGCHAR_HEIGHT;
s_VR.lasersight.generic.type = MTYPE_RADIOBUTTON;
s_VR.lasersight.generic.name = "Laser Sight:";
s_VR.lasersight.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
s_VR.lasersight.generic.callback = VR_Event;
s_VR.lasersight.generic.id = ID_LASERSIGHT;
s_VR.lasersight.generic.x = VR_X_POS;
s_VR.lasersight.generic.y = y;
y += BIGCHAR_HEIGHT + 10;
s_VR.gore.generic.type = MTYPE_SPINCONTROL;
@ -502,7 +516,8 @@ static void VR_MenuInit( void ) {
Menu_AddItem( &s_VR.menu, &s_VR.scope );
Menu_AddItem( &s_VR.menu, &s_VR.rollhit );
Menu_AddItem( &s_VR.menu, &s_VR.hudyoffset );
Menu_AddItem( &s_VR.menu, &s_VR.bodyscale );
Menu_AddItem( &s_VR.menu, &s_VR.sendroll );
Menu_AddItem( &s_VR.menu, &s_VR.lasersight );
Menu_AddItem( &s_VR.menu, &s_VR.gore );
Menu_AddItem( &s_VR.menu, &s_VR.back );

View File

@ -80,6 +80,7 @@ typedef enum {
RT_RAIL_RINGS,
RT_LIGHTNING,
RT_PORTALSURFACE, // doesn't draw anything, just info for portals
RT_LASERSIGHT,
RT_MAX_REF_ENTITY_TYPE
} refEntityType_t;

View File

@ -1591,6 +1591,7 @@ static void R_AddEntitySurface (int entityNum)
case RT_LIGHTNING:
case RT_RAIL_CORE:
case RT_RAIL_RINGS:
case RT_LASERSIGHT:
// self blood sprites, talk balloons, etc should not be drawn in the primary
// view. We can't just do this check for all entities, because md3
// entities may still want to cast shadows from them

View File

@ -733,6 +733,36 @@ static void RB_SurfaceRailCore( void ) {
DoRailCore( start, end, right, len, r_railCoreWidth->integer );
}
/*
** RB_LaserSight
*/
static void RB_LaserSight( void ) {
refEntity_t *e;
int len;
vec3_t right;
vec3_t vec;
vec3_t start, end;
vec3_t v1, v2;
e = &backEnd.currentEntity->e;
VectorCopy( e->oldorigin, start );
VectorCopy( e->origin, end );
VectorSubtract( end, start, vec );
len = VectorNormalize( vec );
// compute side vector
VectorSubtract( start, backEnd.viewParms.or.origin, v1 );
VectorNormalize( v1 );
VectorSubtract( end, backEnd.viewParms.or.origin, v2 );
VectorNormalize( v2 );
CrossProduct( v1, v2, right );
VectorNormalize( right );
DoRailCore( start, end, right, len, 1 );
}
/*
** RB_SurfaceLightningBolt
*/
@ -1190,6 +1220,9 @@ static void RB_SurfaceEntity( surfaceType_t *surfType ) {
case RT_LIGHTNING:
RB_SurfaceLightningBolt();
break;
case RT_LASERSIGHT:
RB_LaserSight();
break;
default:
RB_SurfaceAxis();
break;

View File

@ -32,6 +32,7 @@ cvar_t *vr_weaponScope = NULL;
cvar_t *vr_rollWhenHit = NULL;
cvar_t *vr_hudYOffset = NULL;
cvar_t *vr_sendRollToServer = NULL;
cvar_t *vr_lasersight = NULL;
engine_t* VR_Init( ovrJava java )
{
@ -64,7 +65,8 @@ void VR_InitCvars( void )
vr_weaponScope = Cvar_Get ("vr_weaponScope", "1", CVAR_ARCHIVE);
vr_rollWhenHit = Cvar_Get ("vr_rollWhenHit", "0", CVAR_ARCHIVE);
vr_hudYOffset = Cvar_Get ("vr_hudYOffset", "0", CVAR_ARCHIVE);
vr_sendRollToServer = Cvar_Get ("vr_sendRollToServer", "0", CVAR_ARCHIVE);
vr_sendRollToServer = Cvar_Get ("vr_sendRollToServer", "1", CVAR_ARCHIVE);
vr_lasersight = Cvar_Get ("vr_lasersight", "0", CVAR_ARCHIVE);
// Values are: scale,right,up,forward,pitch,yaw,roll
// VALUES PROVIDED BY SkillFur - Thank-you!

View File

@ -29,7 +29,6 @@ typedef struct {
vec3_t hmdorientation_delta;
vec3_t weaponangles;
vec3_t last_calculated_weaponangles;
vec3_t calculated_weaponangles; //Calculated as the angle required to hit the point that the controller is pointing at, but coming from the view origin
vec3_t weaponangles_last; // Don't use this, it is just for calculating delta!
vec3_t weaponangles_delta;