Real dual-wield for akimbo

This commit is contained in:
Petr Bartos 2023-10-08 17:09:41 +02:00
parent 86a6a87903
commit 0f6d6386e8
14 changed files with 317 additions and 144 deletions

View file

@ -1514,8 +1514,7 @@ void RTCWVR_Init()
//Set up vr client info
vr.backpackitemactive = 0;
vr.visible_hud = qtrue;
vr.dualwield = qfalse;
vr.weapon_recoil = 0.0f;
vr.weapon_recoil = 0.0f;
//Clear teleport stuff
vr.teleportexecute = qfalse;

View file

@ -4,8 +4,8 @@
#define NUM_WEAPON_SAMPLES 10
#define WEAPON_RECOIL 15.0f;
#define USE_GESTURE_OFF_HAND 1
#define USE_GESTURE_WEAPON_HAND 2
#define ACTIVE_OFF_HAND 1
#define ACTIVE_WEAPON_HAND 2
typedef struct {
qboolean screen;
@ -15,7 +15,6 @@ typedef struct {
qboolean menu_right_handed;
qboolean player_moving;
qboolean visible_hud;
qboolean dualwield;
int weaponid;
int lastweaponid;
int backpackitemactive; //0 - nothing, 1 - grenades, 2 - knife, 3 - Binoculars
@ -55,6 +54,7 @@ typedef struct {
qboolean velocitytriggered; // Weapon attack triggered by velocity (knife)
vec3_t offhandweaponangles;
vec3_t offhandangles;
vec3_t offhandangles_last; // Don't use this, it is just for calculating delta!
vec3_t offhandangles_delta;
@ -79,6 +79,8 @@ typedef struct {
qboolean binocularsActive;
qboolean useHoldableItem;
qboolean toggleMainMenu;
int akimboTriggerState;
qboolean akimboFire;
//////////////////////////////////////
// Test stuff for weapon alignment

View file

@ -52,14 +52,6 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG
//Need this for the touch screen
ovrTracking * pWeapon = pDominantTracking;
ovrTracking * pOff = pOffTracking;
if (vr.weaponid == WP_AKIMBO &&
!vr.right_handed &&
!RTCWVR_useScreenLayer())
{
//Revert to same weapon controls as right-handed if using akimbo
pWeapon = pOffTracking;
pOff = pDominantTracking;
}
//All this to allow stick and button switching!
ovrVector2f *pPrimaryJoystick;
@ -111,24 +103,27 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG
QuatToYawPitchRoll(pDominantTracking->HeadPose.Pose.Orientation, rotation, vr.dominanthandangles);
rotation[PITCH] = 30;
QuatToYawPitchRoll(pWeapon->HeadPose.Pose.Orientation, rotation, vr.weaponangles_knife);
rotation[PITCH] = vr_weapon_pitchadjust->value +
(vr.pistol ? vr.weapon_recoil : 0.0f); // Our hacked recoil effect
vr.weapon_recoil *= 0.8f; // quick reduction on synthetic recoil
qboolean addRecoil = vr.pistol && (vr.weaponid != WP_AKIMBO || vr.akimboFire);
rotation[PITCH] = vr_weapon_pitchadjust->value + (addRecoil ? vr.weapon_recoil : 0.0f); // Our hacked recoil effect
QuatToYawPitchRoll(pWeapon->HeadPose.Pose.Orientation, rotation, vr.weaponangles);
VectorSubtract(vr.weaponangles_last, vr.weaponangles, vr.weaponangles_delta);
VectorCopy(vr.weaponangles, vr.weaponangles_last);
ALOGV(" weaponangles_last: %f, %f, %f",
vr.weaponangles_last[0], vr.weaponangles_last[1], vr.weaponangles_last[2]);
ALOGV(" weaponangles_last: %f, %f, %f", vr.weaponangles_last[0], vr.weaponangles_last[1], vr.weaponangles_last[2]);
//GB Also set offhand angles just in case we want to use those.
vec3_t rotation_off = {0};
rotation_off[PITCH] = -25;
QuatToYawPitchRoll(pOff->HeadPose.Pose.Orientation, rotation_off, vr.offhandangles);
qboolean addRecoil_off = vr.pistol && (vr.weaponid != WP_AKIMBO || !vr.akimboFire);
rotation_off[PITCH] = vr_weapon_pitchadjust->value + (addRecoil_off ? vr.weapon_recoil : 0.0f); // Our hacked recoil effect
QuatToYawPitchRoll(pOff->HeadPose.Pose.Orientation, rotation_off, vr.offhandweaponangles);
VectorSubtract(vr.offhandangles_last, vr.offhandangles, vr.offhandangles_delta);
VectorCopy(vr.offhandangles, vr.offhandangles_last);
vr.weapon_recoil *= 0.8f; // quick reduction on synthetic recoil
}
//Menu button
@ -279,10 +274,9 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG
sendButtonAction("+attack", velocityTriggeredAttack);
}
if (vr.weapon_stabilised || vr.dualwield)
if (vr.weapon_stabilised)
{
if (vr.scopeengaged || (vr_virtual_stock->integer == 1 && // Classic Virtual Stock
!vr.dualwield))
if (vr.scopeengaged || vr_virtual_stock->integer == 1)
{
//offset to the appropriate eye a little bit
vec2_t xy;
@ -305,16 +299,8 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG
float zxDist = length(x, z);
if (zxDist != 0.0f && z != 0.0f) {
if (vr.dualwield) {
//SUPER FUDGE
VectorSet(vr.weaponangles, vr.weaponangles[PITCH],
-90.0f-degrees(atan2f(x, -z)), degrees(atanf(y / zxDist)));
}
else
{
VectorSet(vr.weaponangles, -degrees(atanf(y / zxDist)),
-degrees(atan2f(x, -z)), vr.weaponangles[ROLL] / 2.0f); //Dampen roll on stabilised weapon
}
VectorSet(vr.weaponangles, -degrees(atanf(y / zxDist)),
-degrees(atan2f(x, -z)), vr.weaponangles[ROLL] / 2.0f); //Dampen roll on stabilised weapon
}
}
}
@ -583,6 +569,7 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG
else if (firing)
{
//no longer firing
vr.akimboTriggerState = 0;
firing = qfalse;
ALOGV("**WEAPON EVENT** Grip Pushed %sattack", (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger) ? "+" : "-");
sendButtonAction("+attack", firing);
@ -599,9 +586,22 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG
else
{
//Just ignore grip and fire
firing = (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger);
ALOGV("**WEAPON EVENT** Grip Pushed %sattack", (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger) ? "+" : "-");
sendButtonAction("+attack", firing);
firing = (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger);
if (vr.weaponid == WP_AKIMBO) {
if (firing) {
vr.akimboTriggerState |= ACTIVE_WEAPON_HAND;
sendButtonAction("+attack", firing);
} else {
vr.akimboTriggerState &= ~ACTIVE_WEAPON_HAND;
if (!vr.akimboTriggerState) { // Stop firing only if we are not firing with off-hand weapon
sendButtonAction("+attack", firing);
}
}
} else {
vr.akimboTriggerState = 0;
sendButtonAction("+attack", firing);
}
}
}
}
@ -615,7 +615,20 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG
ALOGV("**WEAPON EVENT** Not Grip Pushed %sattack", (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger) ? "+" : "-");
firing = (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger);
sendButtonAction("+attack", firing);
if (vr.weaponid == WP_AKIMBO) {
if (firing) {
vr.akimboTriggerState |= ACTIVE_WEAPON_HAND;
sendButtonAction("+attack", firing);
} else {
vr.akimboTriggerState &= ~ACTIVE_WEAPON_HAND;
if (!vr.akimboTriggerState) { // Stop firing only if we are not still firing with off-hand weapon
sendButtonAction("+attack", firing);
}
}
} else {
vr.akimboTriggerState = 0;
sendButtonAction("+attack", firing);
}
}
else if (binocularsactive) // trigger can zoom-in binoculars, remove from face to reset
{
@ -748,11 +761,30 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG
//in meantime, then it wouldn't stop the gun firing and it would get stuck
if (!vr.teleportenabled)
{
//Run
handleTrackedControllerButton(pOffTrackedRemoteNew,
pOffTrackedRemoteOld,
ovrButton_Trigger, K_SHIFT);
if (vr.weaponid == WP_AKIMBO && vr.backpackitemactive != 3 && !vr.binocularsActive) {
// Fire off-hand weapon
if ((pOffTrackedRemoteNew->Buttons & ovrButton_Trigger) != (pOffTrackedRemoteOld->Buttons & ovrButton_Trigger)) {
ALOGV("**WEAPON EVENT** Off-hand trigger %sattack", (pOffTrackedRemoteNew->Buttons & ovrButton_Trigger) ? "+" : "-");
qboolean firing = (pOffTrackedRemoteNew->Buttons & ovrButton_Trigger);
if (firing) {
vr.akimboTriggerState |= ACTIVE_OFF_HAND;
sendButtonAction("+attack", firing);
} else {
vr.akimboTriggerState &= ~ACTIVE_OFF_HAND;
if (!vr.akimboTriggerState) { // Stop firing only if we are not still firing with main weapon
sendButtonAction("+attack", firing);
}
}
}
} else {
if (vr.akimboTriggerState) {
// Akimbo no longer active, stop attacking
vr.akimboTriggerState = 0;
sendButtonAction("+attack", qfalse);
}
// Run
handleTrackedControllerButton(pOffTrackedRemoteNew, pOffTrackedRemoteOld, ovrButton_Trigger, K_SHIFT);
}
} else {
if (pOffTrackedRemoteNew->Buttons & ovrButton_Trigger)
{
@ -861,34 +893,34 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG
// Off-hand gesture
float distanceToBody = sqrt(vr.offhandoffset[0]*vr.offhandoffset[0] + vr.offhandoffset[2]*vr.offhandoffset[2]);
if (gestureUseAllowed && (distanceToBody > vr_use_gesture_boundary->value)) {
if (!(vr.useGestureState & USE_GESTURE_OFF_HAND)) {
if (!(vr.useGestureState & ACTIVE_OFF_HAND)) {
sendButtonAction("+activate2", true);
}
vr.useGestureState |= USE_GESTURE_OFF_HAND;
vr.useGestureState |= ACTIVE_OFF_HAND;
} else {
if (vr.useGestureState & USE_GESTURE_OFF_HAND) {
if (vr.useGestureState & ACTIVE_OFF_HAND) {
sendButtonAction("+activate2", false);
}
vr.useGestureState &= ~USE_GESTURE_OFF_HAND;
vr.useGestureState &= ~ACTIVE_OFF_HAND;
}
// Weapon-hand gesture
distanceToBody = sqrt(vr.current_weaponoffset[0]*vr.current_weaponoffset[0] + vr.current_weaponoffset[2]*vr.current_weaponoffset[2]);
if (gestureUseAllowed && (distanceToBody > vr_use_gesture_boundary->value)) {
if (!(vr.useGestureState & USE_GESTURE_WEAPON_HAND)) {
if (!(vr.useGestureState & ACTIVE_WEAPON_HAND)) {
sendButtonAction("+activate", true);
}
vr.useGestureState |= USE_GESTURE_WEAPON_HAND;
vr.useGestureState |= ACTIVE_WEAPON_HAND;
} else {
if (vr.useGestureState & USE_GESTURE_WEAPON_HAND) {
if (vr.useGestureState & ACTIVE_WEAPON_HAND) {
sendButtonAction("+activate", false);
}
vr.useGestureState &= ~USE_GESTURE_WEAPON_HAND;
vr.useGestureState &= ~ACTIVE_WEAPON_HAND;
}
} else {
if (vr.useGestureState & USE_GESTURE_OFF_HAND) {
if (vr.useGestureState & ACTIVE_OFF_HAND) {
sendButtonAction("+activate2", false);
}
if (vr.useGestureState & USE_GESTURE_WEAPON_HAND) {
if (vr.useGestureState & ACTIVE_WEAPON_HAND) {
sendButtonAction("+activate", false);
}
vr.useGestureState = 0;

View file

@ -1947,6 +1947,9 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
case EV_EMPTYCLIP:
DEBUGNAME( "EV_EMPTYCLIP" );
if ( ( es->weapon != WP_GRENADE_LAUNCHER ) && ( es->weapon != WP_GRENADE_PINEAPPLE ) && ( es->weapon != WP_DYNAMITE ) ) {
trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.noAmmoSound );
}
break;
case EV_FILL_CLIP:
@ -2022,8 +2025,10 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
CG_FireWeapon( cent );
if ( event == EV_FIRE_WEAPONB ) { // akimbo firing colt
cent->akimboFire = qtrue;
cgVR->akimboFire = qtrue;
} else {
cent->akimboFire = qfalse;
cgVR->akimboFire = qfalse;
}
break;
case EV_FIRE_WEAPON_LASTSHOT:

View file

@ -2097,7 +2097,7 @@ void CG_Bullet( vec3_t origin, int sourceEntityNum, vec3_t normal, qboolean fles
void CG_RailTrail( clientInfo_t *ci, vec3_t start, vec3_t end, int type ); //----(SA) added 'type'
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 );
void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent, qboolean akimbo );
void CG_DrawWeaponSelect( void );
void CG_DrawHoldableSelect( void );
void CG_AddViewHand( playerState_t *ps );

View file

@ -1436,7 +1436,11 @@ float CG_GetValue( int ownerDraw, int type ) {
case CG_PLAYER_AMMOCLIP_VALUE:
if ( cent->currentState.weapon ) {
if ( type == RANGETYPE_RELATIVE ) {
return (float)ps->ammoclip[BG_FindClipForWeapon( cent->currentState.weapon )] / (float)ammoTable[cent->currentState.weapon].maxclip;
if (cent->currentState.weapon == WP_AKIMBO) {
return (float)(ps->ammoclip[WP_AKIMBO] + ps->ammoclip[WP_COLT]) / (float)(ammoTable[WP_AKIMBO].maxclip * 4);
} else {
return (float)ps->ammoclip[BG_FindClipForWeapon( cent->currentState.weapon )] / (float)ammoTable[cent->currentState.weapon].maxclip;
}
} else {
return ps->ammoclip[BG_FindClipForWeapon( cent->currentState.weapon )];
}

View file

@ -5021,7 +5021,7 @@ void CG_Player( centity_t *cent ) {
//
// add the gun / barrel / flash
//
CG_AddPlayerWeapon( &torso, NULL, cent );
CG_AddPlayerWeapon( &torso, NULL, cent, qfalse );
cent->lastWeaponClientFrame = cg.clientFrame;

View file

@ -1607,7 +1607,8 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo
CG_DrawWheelSelector();
} else if (!cgVR->screen){
CG_AddViewWeapon( &cg.predictedPlayerState );
if (trap_Cvar_VariableIntegerValue("vr_gesture_triggered_use") && !cgVR->weapon_stabilised && !cg.renderingThirdPerson) {
qboolean usingAkimbo = cg.predictedPlayerState.weapon == WP_AKIMBO;
if (!usingAkimbo && !cgVR->weapon_stabilised && !cg.renderingThirdPerson && trap_Cvar_VariableIntegerValue("vr_gesture_triggered_use")) {
CG_AddViewHand( &cg.predictedPlayerState);
}
}

View file

@ -1977,17 +1977,9 @@ void convertFromVR(vec3_t in, vec3_t offset, vec3_t out)
}
void CG_CalculateVRWeaponPosition( int weaponNum, vec3_t origin, vec3_t angles ) {
if (weaponNum != WP_AKIMBO || BG_AkimboFireSequence(weaponNum, cg.predictedPlayerState.ammoclip[WP_AKIMBO], cg.predictedPlayerState.ammoclip[WP_COLT] ))
{
convertFromVR(cgVR->calculated_weaponoffset, cg.refdef.vieworg, origin);
} else{
convertFromVR(cgVR->offhandoffset, cg.refdef.vieworg, origin);
}
convertFromVR(cgVR->calculated_weaponoffset, cg.refdef.vieworg, origin);
origin[2] -= 64;
origin[2] += (cgVR->hmdposition[1] + cg_heightAdjust.value) * cg_worldScale.value;
switch (cg.predictedPlayerState.weapon)
{
case WP_KNIFE:
@ -1997,7 +1989,6 @@ void CG_CalculateVRWeaponPosition( int weaponNum, vec3_t origin, vec3_t angles )
VectorCopy(cgVR->weaponangles, angles);
break;
}
angles[YAW] += cg.refdefViewAngles[YAW] - cgVR->hmdorientation[YAW];
}
@ -2017,6 +2008,14 @@ void CG_CalculateVROffHandPosition( vec3_t origin, vec3_t angles ) {
angles[YAW] += cg.refdefViewAngles[YAW] - cgVR->hmdorientation[YAW];
}
void CG_CalculateVROffHandWeaponPosition( vec3_t origin, vec3_t angles ) {
convertFromVR(cgVR->offhandoffset, cg.refdef.vieworg, origin);
origin[2] -= 64;
origin[2] += (cgVR->hmdposition[1] + cg_heightAdjust.value) * cg_worldScale.value;
VectorCopy(cgVR->offhandweaponangles, angles);
angles[YAW] += cg.refdefViewAngles[YAW] - cgVR->hmdorientation[YAW];
}
void CG_CalculateVRPositionInWorld( const vec3_t in_position, vec3_t in_offset, vec3_t in_orientation, vec3_t origin, vec3_t angles )
{
vec3_t offset;
@ -2036,9 +2035,13 @@ CG_CalculateWeaponPositionAndScale
*/
static float CG_CalculateWeaponPositionAndScale( playerState_t *ps, vec3_t origin, vec3_t angles ) {
static float CG_CalculateWeaponPositionAndScale( playerState_t *ps, vec3_t origin, vec3_t angles, qboolean akimbo ) {
CG_CalculateVRWeaponPosition(0, origin, angles);
if (akimbo) {
CG_CalculateVROffHandWeaponPosition(origin, angles);
} else {
CG_CalculateVRWeaponPosition(0, origin, angles);
}
vec3_t offset;
@ -2080,7 +2083,11 @@ static float CG_CalculateWeaponPositionAndScale( playerState_t *ps, vec3_t origi
else if (ps->weapon != 0)
{
char cvar_name[64];
Com_sprintf(cvar_name, sizeof(cvar_name), "vr_weapon_adjustment_%i", ps->weapon);
if (ps->weapon == WP_AKIMBO) {
Com_sprintf(cvar_name, sizeof(cvar_name), "vr_weapon_adjustment_%i", WP_COLT);
} else {
Com_sprintf(cvar_name, sizeof(cvar_name), "vr_weapon_adjustment_%i", ps->weapon);
}
char weapon_adjustment[256];
trap_Cvar_VariableStringBuffer(cvar_name, weapon_adjustment, 256);
@ -2096,7 +2103,7 @@ static float CG_CalculateWeaponPositionAndScale( playerState_t *ps, vec3_t origi
&(adjust[PITCH]), &(adjust[YAW]), &(adjust[ROLL]));
VectorScale(temp_offset, scale, offset);
if (!cgVR->right_handed)
if (!cgVR->right_handed != akimbo)
{
//yaw needs to go in the other direction as left handed model is reversed
adjust[YAW] *= -1.0f;
@ -2120,7 +2127,7 @@ static float CG_CalculateWeaponPositionAndScale( playerState_t *ps, vec3_t origi
AngleVectors( angles, forward, right, up );
VectorMA( origin, offset[2], forward, origin );
VectorMA( origin, offset[1], up, origin );
if (cgVR->right_handed) {
if (cgVR->right_handed != akimbo) {
VectorMA(origin, offset[0], right, origin);
} else {
VectorMA(origin, -offset[0], right, origin);
@ -2866,7 +2873,11 @@ static qboolean CG_CalcMuzzlePoint( int entityNum, int dist, vec3_t muzzle ) {
cent = &cg_entities[entityNum];
if ( entityNum == cg.snap->ps.clientNum ) {
vec3_t angles;
CG_CalculateVRWeaponPosition(cent->currentState.weapon, muzzle, angles);
if (cent->currentState.weapon == WP_AKIMBO && BG_AkimboFireSequence(WP_AKIMBO, cg.snap->ps.ammoclip[WP_AKIMBO], cg.snap->ps.ammoclip[WP_COLT], cgVR->akimboTriggerState)) {
CG_CalculateVROffHandWeaponPosition(muzzle, angles);
} else {
CG_CalculateVRWeaponPosition(cent->currentState.weapon, muzzle, angles);
}
AngleVectors( angles, forward, NULL, NULL );
VectorMA( muzzle, dist, forward, muzzle );
@ -2908,7 +2919,7 @@ sound should only be done on the world model case.
*/
static qboolean debuggingweapon = qfalse;
void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent ) {
void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent, qboolean akimbo ) {
refEntity_t gun;
refEntity_t barrel;
@ -2986,16 +2997,21 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
break;
}
} else {
CG_RegisterWeapon( weaponNum );
weapon = &cg_weapons[weaponNum];
if (weaponNum == WP_AKIMBO) {
CG_RegisterWeapon(WP_COLT);
weapon = &cg_weapons[WP_COLT];
} else {
CG_RegisterWeapon( weaponNum );
weapon = &cg_weapons[weaponNum];
}
}
// dhm - end
if ( isPlayer ) {
akimboFire = BG_AkimboFireSequence( weaponNum, cg.predictedPlayerState.ammoclip[WP_AKIMBO], cg.predictedPlayerState.ammoclip[WP_COLT] );
akimboFire = BG_AkimboFireSequence( weaponNum, cg.predictedPlayerState.ammoclip[WP_AKIMBO], cg.predictedPlayerState.ammoclip[WP_COLT], cgVR->akimboTriggerState );
} else if ( ps ) {
akimboFire = BG_AkimboFireSequence( weaponNum, ps->ammoclip[WP_AKIMBO], ps->ammoclip[WP_AKIMBO] );
akimboFire = BG_AkimboFireSequence( weaponNum, ps->ammoclip[WP_AKIMBO], ps->ammoclip[WP_AKIMBO], 0 );
}
// add the weapon
@ -3111,20 +3127,19 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
int brassOffset[WP_NUM_WEAPONS];
memset (brassOffset, 0, sizeof brassOffset);
brassOffset[WP_LUGER] = 1;
brassOffset[WP_SILENCER] = 1;
brassOffset[WP_COLT] = 1;
brassOffset[WP_AKIMBO] = 1;
brassOffset[WP_FG42] = 1;
brassOffset[WP_MP40] = 2;
brassOffset[WP_THOMPSON] = 2;
brassOffset[WP_STEN] = 6;
brassOffset[WP_VENOM] = 5;
// opposite tag in akimbo, since at this point the weapon
// has fired and the fire seq has switched over
if ( weaponNum == WP_AKIMBO && akimboFire ) {
CG_PositionRotatedEntityOnTag( &brass, &gun, "tag_brass2" );
} else if ( brassOffset[weaponNum] != 0) {
//Correct bad tag on certain models
CG_CalcMuzzlePoint(cent->currentState.clientNum, brassOffset[weaponNum], brass.origin);
if ( brassOffset[weaponNum] != 0) {
//Correct bad tag on certain models
CG_CalcMuzzlePoint(cent->currentState.clientNum, brassOffset[weaponNum], brass.origin);
MatrixMultiply( brass.axis, gun.axis, brass.axis );
} else {
CG_PositionRotatedEntityOnTag( &brass, &gun, "tag_brass" );
}
@ -3341,6 +3356,10 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
return;
}
if (isPlayer && akimbo != akimboFire) {
return; // We are firing the other gun
}
if ( weaponNum == WP_STEN ) { // sten has no muzzleflash
flash.hModel = 0;
}
@ -3357,15 +3376,6 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
}
}
if ( isPlayer ) {
if ( weaponNum == WP_AKIMBO ) {
if ( !cent->akimboFire ) {
CG_PositionRotatedEntityOnTag( &flash, &gun, "tag_flash2" );
}
}
}
if ( flash.hModel ) {
if ( weaponNum != WP_FLAMETHROWER && weaponNum != WP_TESLA ) { //Ridah, hide the flash also for now
// RF, changed this so the muzzle flash stays onscreen for long enough to be seen
@ -3481,7 +3491,7 @@ void CG_AddPlayerFoot( refEntity_t *parent, playerState_t *ps, centity_t *cent )
}
void CG_LaserSight(const playerState_t *ps) {
void CG_LaserSight(const playerState_t *ps, qboolean akimbo) {
if (trap_Cvar_VariableIntegerValue("vr_lasersight") != 0 &&
cgVR->backpackitemactive == 0 && !cgVR->binocularsActive &&
@ -3513,7 +3523,11 @@ void CG_LaserSight(const playerState_t *ps) {
vec3_t endForward;
vec3_t angles;
clientInfo_t ci;
CG_CalculateVRWeaponPosition(0, origin, angles);
if (akimbo) {
CG_CalculateVROffHandWeaponPosition(origin, angles);
} else {
CG_CalculateVRWeaponPosition(0, origin, angles);
}
vec3_t forward, right, up;
AngleVectors(angles, forward, right, up);
@ -3539,10 +3553,14 @@ Add the weapon, and flash for the player's view
*/
void CG_AddViewWeapon( playerState_t *ps ) {
refEntity_t hand;
refEntity_t handAkimbo;
float fovOffset;
vec3_t angles;
vec3_t anglesAkimbo;
vec3_t gunoff;
vec3_t gunoffAkimbo;
weaponInfo_t *weapon;
weaponInfo_t *weaponAkimbo;
if ( ps->persistant[PERS_TEAM] == TEAM_SPECTATOR ) {
return;
@ -3613,53 +3631,98 @@ void CG_AddViewWeapon( playerState_t *ps ) {
break;
}
} else {
CG_RegisterWeapon( ps->weapon );
weapon = &cg_weapons[ ps->weapon ];
if (ps->weapon == WP_AKIMBO) {
CG_RegisterWeapon( WP_COLT );
CG_RegisterWeapon( WP_AKIMBO );
weapon = &cg_weapons[ WP_COLT ];
weaponAkimbo = &cg_weapons[ WP_AKIMBO ];
} else {
CG_RegisterWeapon( ps->weapon );
weapon = &cg_weapons[ ps->weapon ];
}
}
// dhm - end
memset( &hand, 0, sizeof( hand ) );
memset( &handAkimbo, 0, sizeof( handAkimbo ) );
// set up gun position
float scale = CG_CalculateWeaponPositionAndScale( ps, hand.origin, angles );
float scale = CG_CalculateWeaponPositionAndScale( ps, hand.origin, angles, qfalse );
float scaleAkimbo = CG_CalculateWeaponPositionAndScale( ps, handAkimbo.origin, anglesAkimbo, qtrue );
gunoff[0] = cg_gun_x.value;
gunoff[1] = cg_gun_y.value;
gunoff[2] = cg_gun_z.value;
gunoffAkimbo[0] = cg_gun_x.value;
gunoffAkimbo[1] = cg_gun_y.value;
gunoffAkimbo[2] = cg_gun_z.value;
//----(SA) removed
VectorMA( hand.origin, gunoff[0], cg.refdef.viewaxis[0], hand.origin );
VectorMA( hand.origin, gunoff[1], cg.refdef.viewaxis[1], hand.origin );
VectorMA( hand.origin, gunoff[2], cg.refdef.viewaxis[2], hand.origin );
VectorMA( handAkimbo.origin, gunoffAkimbo[0], cg.refdef.viewaxis[0], handAkimbo.origin );
VectorMA( handAkimbo.origin, gunoffAkimbo[1], cg.refdef.viewaxis[1], handAkimbo.origin );
VectorMA( handAkimbo.origin, gunoffAkimbo[2], cg.refdef.viewaxis[2], handAkimbo.origin );
AnglesToAxis( angles, hand.axis );
AnglesToAxis( anglesAkimbo, handAkimbo.axis );
if ( cg_gun_frame.integer) {
hand.frame = hand.oldframe = cg_gun_frame.integer;
hand.backlerp = 0;
handAkimbo.frame = handAkimbo.oldframe = cg_gun_frame.integer;
handAkimbo.backlerp = 0;
} else { // get the animation state
CG_WeaponAnimation( ps, weapon, &hand.oldframe, &hand.frame, &hand.backlerp ); //----(SA) changed
if (ps->weapon == WP_AKIMBO) {
int weapAnim = ( ps->weapAnim & ~ANIM_TOGGLEBIT );
if (weapAnim == WEAP_ATTACK1 || weapAnim == WEAP_ATTACK2 || weapAnim == WEAP_ATTACK_LASTSHOT || weapAnim == WEAP_IDLE1 || weapAnim == WEAP_IDLE2) {
// For akimbo attack animation, animate only firing weapon
if (cgVR->akimboFire) {
CG_WeaponAnimation( ps, weapon, &hand.oldframe, &hand.frame, &hand.backlerp );
} else {
CG_WeaponAnimation( ps, weaponAkimbo, &handAkimbo.oldframe, &handAkimbo.frame, &handAkimbo.backlerp );
}
} else if (weapAnim == WEAP_RELOAD1 || weapAnim == WEAP_RELOAD2 || weapAnim == WEAP_RELOAD3) {
// For akimbo reload, do not animate weapon with full clip
if (ps->ammoclip[WP_COLT] < 8) {
CG_WeaponAnimation( ps, weapon, &hand.oldframe, &hand.frame, &hand.backlerp );
}
if (ps->ammoclip[WP_AKIMBO] < 8) {
CG_WeaponAnimation( ps, weaponAkimbo, &handAkimbo.oldframe, &handAkimbo.frame, &handAkimbo.backlerp );
}
} else {
CG_WeaponAnimation( ps, weapon, &hand.oldframe, &hand.frame, &hand.backlerp );
CG_WeaponAnimation( ps, weaponAkimbo, &handAkimbo.oldframe, &handAkimbo.frame, &handAkimbo.backlerp );
}
} else {
CG_WeaponAnimation( ps, weapon, &hand.oldframe, &hand.frame, &hand.backlerp ); //----(SA) changed
}
}
if (cgVR->backpackitemactive != 3 && !cgVR->binocularsActive)
{
hand.hModel = weapon->handsModel;
handAkimbo.hModel = weaponAkimbo->handsModel;
}
//Weapon offset debugging
if (weaponDebugging)
{
hand.renderfx = RF_FIRST_PERSON | RF_MINLIGHT | RF_VIEWWEAPON; //No depth hack for weapon adjusting mode
handAkimbo.renderfx = RF_FIRST_PERSON | RF_MINLIGHT | RF_VIEWWEAPON;
}
else
{
hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON | RF_MINLIGHT | RF_VIEWWEAPON; //----(SA)
handAkimbo.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON | RF_MINLIGHT | RF_VIEWWEAPON;
}
//scale the whole model (hand and weapon)
for ( int i = 0; i < 3; i++ ) {
VectorScale( hand.axis[i], (cgVR->right_handed || i != 1 || ps->weapon == WP_AKIMBO) ? scale : -scale, hand.axis[i] );
VectorScale( hand.axis[i], (cgVR->right_handed || i != 1) ? scale : -scale, hand.axis[i] );
VectorScale( handAkimbo.axis[i], (!cgVR->right_handed || i != 1) ? scaleAkimbo : -scaleAkimbo, handAkimbo.axis[i] );
}
@ -3701,7 +3764,10 @@ void CG_AddViewWeapon( playerState_t *ps ) {
}
// add everything onto the hand
CG_AddPlayerWeapon(&hand, ps, &cg.predictedPlayerEntity);
CG_AddPlayerWeapon(&hand, ps, &cg.predictedPlayerEntity, qfalse);
if (ps->weapon == WP_AKIMBO) {
CG_AddPlayerWeapon(&handAkimbo, ps, &cg.predictedPlayerEntity, qtrue);
}
// Ridah
} // end "if ( ps->weapon > WP_NONE)"
@ -3736,7 +3802,10 @@ void CG_AddViewWeapon( playerState_t *ps ) {
CG_RailTrail2(&ci, origin, endUp);
}
CG_LaserSight(ps);
CG_LaserSight(ps, qfalse);
if (ps->weapon == WP_AKIMBO) {
CG_LaserSight(ps, qtrue);
}
cg.predictedPlayerEntity.lastWeaponClientFrame = cg.clientFrame;
}
@ -3753,7 +3822,7 @@ void CG_AddViewHand( playerState_t *ps ) {
VectorScale( handEnt.axis[i], (cgVR->right_handed || i != 1) ? 1.0f : -1.0f, handEnt.axis[i] );
}
handEnt.renderfx = RF_DEPTHHACK; //| RF_VRVIEWMODEL;
handEnt.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON | RF_MINLIGHT | RF_VIEWWEAPON;
handEnt.hModel = cgs.media.handModel;
trap_R_AddRefEntityToScene( &handEnt );
@ -4562,6 +4631,8 @@ void CG_DrawWheelSelector( void )
memset(&item, 0, sizeof(item));
if (weaponNum == WP_LUGER && CG_WeaponAvailable(WP_SILENCER)) {
item.itemId = WP_SILENCER;
} else if (weaponNum == WP_COLT && CG_WeaponAvailable(WP_AKIMBO)) {
item.itemId = WP_AKIMBO;
} else {
item.itemId = weaponNum;
}
@ -4909,6 +4980,7 @@ void CG_WheelSelectorSelect_f( void )
if (cg.wheelSelectorType == WST_WEAPON) {
cgVR->binocularsActive = qfalse;
cgVR->weaponid = cg.wheelSelectorSelection;
if (cg.wheelSelectorSelection != cg.weaponSelect) {
cg.weaponSelectTime = cg.time;
cg.weaponSelect = cg.wheelSelectorSelection;
@ -4922,16 +4994,19 @@ void CG_WheelSelectorSelect_f( void )
}
else if (cg.wheelSelectorSelection == WSI_GRENADE) {
cgVR->binocularsActive = qfalse;
cgVR->weaponid = WP_GRENADE_LAUNCHER;
cg.weaponSelectTime = cg.time;
cg.weaponSelect = WP_GRENADE_LAUNCHER;
}
else if (cg.wheelSelectorSelection == WSI_PINEAPPLE) {
cgVR->binocularsActive = qfalse;
cgVR->weaponid = WP_GRENADE_PINEAPPLE;
cg.weaponSelectTime = cg.time;
cg.weaponSelect = WP_GRENADE_PINEAPPLE;
}
else if (cg.wheelSelectorSelection == WSI_DYNAMITE) {
cgVR->binocularsActive = qfalse;
cgVR->weaponid = WP_DYNAMITE;
cg.weaponSelectTime = cg.time;
cg.weaponSelect = WP_DYNAMITE;
}
@ -5154,8 +5229,6 @@ void CG_FinishWeaponChange( int lastweap, int newweap ) {
}
}
cgVR->dualwield = (newweap == WP_AKIMBO);
cg.weaponSelect = newweap;
cgVR->weaponid = newweap; //Store in case we use backpack
}

View file

@ -55,6 +55,8 @@ extern vmCvar_t g_gametype;
#define MAX_AMMO_FG42 MAX_AMMO_MAUSER
#define MAX_AMMO_BAR 200
#define TRIGGER_SECONDARY 1
#define TRIGGER_PRIMARY 2
// these defines are matched with the character torso animations
#define DELAY_LOW 100 // machineguns, tesla, spear, flame
@ -1073,9 +1075,9 @@ dual colts
{
"weapon_akimbo",
"sound/misc/w_pkup.wav",
{ "models/weapons2/colt2/colt2.md3",
"models/weapons2/colt2/v_colt2.md3",
"models/weapons2/colt2/pu_colt2.md3",
{ "models/weapons2/colt/colt.md3",
"models/weapons2/colt/v_colt.md3",
"models/weapons2/colt/pu_colt.md3",
0, 0 },
"icons/iconw_colt_1", // icon
@ -3621,30 +3623,33 @@ BG_AkimboFireSequence
==============
*/
//qboolean BG_AkimboFireSequence( playerState_t *ps ) {
qboolean BG_AkimboFireSequence( int weapon, int akimboClip, int coltClip ) {
qboolean BG_AkimboFireSequence( int weapon, int akimboClip, int coltClip, int triggerState ) {
// NOTE: this doesn't work when clips are turned off (dmflags 64)
if ( weapon != WP_AKIMBO ) {
return qfalse;
}
// If only one trigger is pushed, return weapon matching the trigger
if ((triggerState & TRIGGER_SECONDARY) && !(triggerState & TRIGGER_PRIMARY)) {
return qtrue; // Firing secondary weapon
}
if ((triggerState & TRIGGER_PRIMARY) && !(triggerState & TRIGGER_SECONDARY)) {
return qfalse; // Firing primary weapon
}
// If both triggers are pushed and one weapon is missing ammo, return the other
if ( !akimboClip ) {
return qfalse;
}
// no ammo in colt, must be akimbo turn
if ( !coltClip ) {
return qtrue;
}
// at this point, both have ammo
// now check 'cycle' // (removed old method 11/5/2001)
if ( ( akimboClip + coltClip ) & 1 ) {
return qfalse;
}
return qtrue;
// At this point, both have ammo and we are firing from both
// Switch between primary and secondary after each fired shot
return ( ( akimboClip + coltClip ) & 1 );
}
//----(SA) end

View file

@ -50,6 +50,8 @@ extern vmCvar_t g_gametype;
extern vr_client_info_t* gVR;
#endif
#define TRIGGER_SECONDARY 1
#define TRIGGER_PRIMARY 2
// JPW NERVE -- stuck this here so it can be seen client & server side
float Com_GetFlamethrowerRange( void ) {
@ -2373,14 +2375,14 @@ void PM_CheckForReload( int weapon ) {
// clip is empty, but you have reserves. (auto reload)
else if ( !( pm->ps->ammoclip[clipWeap] ) ) { // clip is empty...
if ( pm->ps->ammo[ammoWeap] ) { // and you have reserves
if ( weapon == WP_AKIMBO ) { // if colt's got ammo, don't force reload yet (you know you've got it 'out' since you've got the akimbo selected
if ( !( pm->ps->ammoclip[WP_COLT] ) ) {
if ( weapon == WP_AKIMBO ) { // reload only if both clips are empty
if ( !( pm->ps->ammoclip[WP_COLT] ) && !( pm->ps->ammoclip[WP_COLT] ) ) {
doReload = qtrue;
}
// likewise. however, you need to check if you've got the akimbo selected, since you could have the colt alone
} else if ( weapon == WP_COLT ) { // weapon checking for reload is colt...
if ( pm->ps->weapon == WP_AKIMBO ) { // you've got the akimbo selected...
if ( !( pm->ps->ammoclip[WP_AKIMBO] ) ) { // and it's got no ammo either
if ( pm->ps->weapon == WP_AKIMBO ) { // reload only if both clips are empty
if ( !( pm->ps->ammoclip[WP_COLT] ) && !( pm->ps->ammoclip[WP_AKIMBO] ) ) {
doReload = qtrue; // so reload
}
} else { // single colt selected
@ -2471,7 +2473,14 @@ void PM_WeaponUseAmmo( int wp, int amount ) {
} else {
takeweapon = BG_FindClipForWeapon( wp );
if ( wp == WP_AKIMBO ) {
if ( !BG_AkimboFireSequence( wp, pm->ps->ammoclip[WP_AKIMBO], pm->ps->ammoclip[WP_COLT] ) ) {
int triggerState = 0;
#ifdef CGAMEDLL
triggerState = cgVR->akimboTriggerState;
#endif
#ifdef GAMEDLL
triggerState = gVR->akimboTriggerState;
#endif
if ( !BG_AkimboFireSequence( wp, pm->ps->ammoclip[WP_AKIMBO], pm->ps->ammoclip[WP_COLT], triggerState ) ) {
takeweapon = WP_COLT;
}
}
@ -2496,7 +2505,14 @@ int PM_WeaponAmmoAvailable( int wp ) {
// return pm->ps->ammoclip[BG_FindClipForWeapon( wp )];
takeweapon = BG_FindClipForWeapon( wp );
if ( wp == WP_AKIMBO ) {
if ( !BG_AkimboFireSequence( pm->ps->weapon, pm->ps->ammoclip[WP_AKIMBO], pm->ps->ammoclip[WP_COLT] ) ) {
int triggerState = 0;
#ifdef CGAMEDLL
triggerState = cgVR->akimboTriggerState;
#endif
#ifdef GAMEDLL
triggerState = gVR->akimboTriggerState;
#endif
if ( !BG_AkimboFireSequence( pm->ps->weapon, pm->ps->ammoclip[WP_AKIMBO], pm->ps->ammoclip[WP_COLT], triggerState ) ) {
takeweapon = WP_COLT;
}
}
@ -2786,7 +2802,14 @@ static void PM_Weapon( void ) {
// RF, remoed this, was preventing lava from hurting player
//pm->watertype = 0;
akimboFire = BG_AkimboFireSequence( pm->ps->weapon, pm->ps->ammoclip[WP_AKIMBO], pm->ps->ammoclip[WP_COLT] );
int triggerState = 0;
#ifdef CGAMEDLL
triggerState = cgVR->akimboTriggerState;
#endif
#ifdef GAMEDLL
triggerState = gVR->akimboTriggerState;
#endif
akimboFire = BG_AkimboFireSequence( pm->ps->weapon, pm->ps->ammoclip[WP_AKIMBO], pm->ps->ammoclip[WP_COLT], triggerState );
if ( 0 ) {
switch ( pm->ps->weaponstate ) {
@ -3061,6 +3084,12 @@ if ( pm->ps->weapon == WP_NONE ) { // this is possible since the player starts
return;
}
// In case of akimbo, fire only if player still holds at least one of triggers
// (Sometimes with really quick tap +attack is spawned but trigger state is no longer
// set when reaching here. Exiting solves problem of "random" weapon fire)
if (pm->ps->weapon == WP_AKIMBO && !triggerState) {
return;
}
// JPW NERVE -- in multiplayer, don't allow panzerfaust or dynamite to fire if charge bar isn't full
#ifdef GAMEDLL
@ -3251,6 +3280,16 @@ if ( pm->ps->weapon ) {
playswitchsound = qfalse;
break;
case WP_AKIMBO:
// do not reload but continue fire if there is ammo in other gun
if (pm->ps->ammoclip[WP_AKIMBO] || pm->ps->ammoclip[WP_COLT]) {
reloadingW = qfalse;
playswitchsound = qfalse;
// notify player that one gun is empty
PM_AddEvent( EV_EMPTYCLIP );
}
break;
// some weapons not allowed to reload. must switch back to primary first
case WP_SNOOPERSCOPE:
case WP_SNIPERRIFLE:
@ -3395,17 +3434,21 @@ case WP_COLT:
//----(SA) added
case WP_AKIMBO:
// if you're firing an akimbo colt, and your other gun is dry,
// nextshot needs to take 2x time
// if you're firing an akimbo colt, and you are firing only single gun,
// or other gun is dry, nextshot needs to take 2x time
addTime = ammoTable[pm->ps->weapon].nextShotTime;
// (SA) (added check for last shot in both guns so there's no delay for the last shot)
if ( !pm->ps->ammoclip[WP_AKIMBO] || !pm->ps->ammoclip[WP_COLT] ) {
if ( ( !pm->ps->ammoclip[WP_AKIMBO] && !akimboFire ) || ( !pm->ps->ammoclip[WP_COLT] && akimboFire ) ) {
addTime = 2 * ammoTable[pm->ps->weapon].nextShotTime;
if (triggerState < 3) {
// firing only single gun
addTime = 2 * ammoTable[pm->ps->weapon].nextShotTime;
} else {
// (SA) (added check for last shot in both guns so there's no delay for the last shot)
if ( !pm->ps->ammoclip[WP_AKIMBO] || !pm->ps->ammoclip[WP_COLT] ) {
if ( ( !pm->ps->ammoclip[WP_AKIMBO] && !akimboFire ) || ( !pm->ps->ammoclip[WP_COLT] && akimboFire ) ) {
addTime = 2 * ammoTable[pm->ps->weapon].nextShotTime;
}
}
}
}
aimSpreadScaleAdd = 20;
break;

View file

@ -1312,7 +1312,7 @@ gitem_t *BG_FindItemForKey( wkey_t k, int *index );
weapon_t BG_FindAmmoForWeapon( weapon_t weapon );
weapon_t BG_FindClipForWeapon( weapon_t weapon );
qboolean BG_AkimboFireSequence( int weapon, int akimboClip, int coltClip );
qboolean BG_AkimboFireSequence( int weapon, int akimboClip, int coltClip, int triggerState );
//qboolean BG_AkimboFireSequence ( playerState_t *ps ); //----(SA) added
#define ITEM_INDEX( x ) ( ( x ) - bg_itemlist )

View file

@ -1092,7 +1092,7 @@ extern gitem_t * BG_FindItem2 ( const char * name ) ;
extern gitem_t * BG_FindItem ( const char * pickupName ) ;
extern gitem_t * BG_FindItemForAmmo ( int ammo ) ;
extern gitem_t * BG_FindItemForKey ( wkey_t k , int * indexreturn ) ;
extern qboolean BG_AkimboFireSequence ( int weapon , int akimboClip , int coltClip ) ;
extern qboolean BG_AkimboFireSequence ( int weapon , int akimboClip , int coltClip, int triggerState ) ;
extern weapon_t BG_FindAmmoForWeapon ( weapon_t weapon ) ;
extern weapon_t BG_FindClipForWeapon ( weapon_t weapon ) ;
extern gitem_t * BG_FindItemForWeapon ( weapon_t weapon ) ;

View file

@ -968,8 +968,8 @@ void Bullet_Fire( gentity_t *ent, float spread, int damage ) {
sprintf(fire_command, "fire_%i", ent->s.weapon);
if (ent->s.weapon == WP_AKIMBO)
{
right = BG_AkimboFireSequence(ent->s.weapon, ent->client->ps.ammoclip[WP_AKIMBO], ent->client->ps.ammoclip[WP_COLT] );
trap_Vibrate(100, right ? 1 : 0, 1.0, fire_command, 0.0, 0.0);
qboolean akimbo = BG_AkimboFireSequence(ent->s.weapon, ent->client->ps.ammoclip[WP_AKIMBO], ent->client->ps.ammoclip[WP_COLT], gVR->akimboTriggerState );
trap_Vibrate(100, right != akimbo ? 1 : 0, 1.0, fire_command, 0.0, 0.0);
} else{
trap_Vibrate(100, right ? 1 : 0, 1.0, fire_command, 0.0, 0.0);
if (gVR->weapon_stabilised) {
@ -1746,7 +1746,11 @@ void CalcMuzzlePoint( gentity_t *ent, int weapon, vec3_t forward, vec3_t right,
float worldscale = trap_Cvar_VariableIntegerValue("cg_worldScale");
float heightAdjust = 0;
trap_Cvar_VariableValue("cg_heightAdjust", &heightAdjust);
convertFromVR(worldscale, ent, gVR->calculated_weaponoffset, ent->r.currentOrigin, muzzlePoint);
if (weapon == WP_AKIMBO && BG_AkimboFireSequence(WP_AKIMBO, ent->client->ps.ammoclip[WP_AKIMBO], ent->client->ps.ammoclip[WP_COLT], gVR->akimboTriggerState)) {
convertFromVR(worldscale, ent, gVR->offhandoffset, ent->r.currentOrigin, muzzlePoint);
} else {
convertFromVR(worldscale, ent, gVR->calculated_weaponoffset, ent->r.currentOrigin, muzzlePoint);
}
muzzlePoint[2] += (ent->client->ps.viewheight - 64);
muzzlePoint[2] += (gVR->hmdposition[1] + heightAdjust) * worldscale;
return;
@ -1773,9 +1777,6 @@ void CalcMuzzlePoint( gentity_t *ent, int weapon, vec3_t forward, vec3_t right,
case WP_GRENADE_LAUNCHER:
VectorMA( muzzlePoint, 20, right, muzzlePoint );
break;
case WP_AKIMBO: // left side rather than right
VectorMA( muzzlePoint, -6, right, muzzlePoint );
VectorMA( muzzlePoint, -4, up, muzzlePoint );
default:
VectorMA( muzzlePoint, 6, right, muzzlePoint );
VectorMA( muzzlePoint, -4, up, muzzlePoint );
@ -1807,7 +1808,11 @@ void CalcMuzzlePointForActivate( gentity_t *ent, vec3_t forward, vec3_t right, v
float worldscale = trap_Cvar_VariableIntegerValue("cg_worldScale");
float heightAdjust = 0;
trap_Cvar_VariableValue("cg_heightAdjust", &heightAdjust);
convertFromVR(worldscale, ent, gVR->calculated_weaponoffset, ent->r.currentOrigin, muzzlePoint);
if (ent->client->ps.weapon == WP_AKIMBO && BG_AkimboFireSequence(WP_AKIMBO, ent->client->ps.ammoclip[WP_AKIMBO], ent->client->ps.ammoclip[WP_COLT], gVR->akimboTriggerState)) {
convertFromVR(worldscale, ent, gVR->offhandoffset, ent->r.currentOrigin, muzzlePoint);
} else {
convertFromVR(worldscale, ent, gVR->calculated_weaponoffset, ent->r.currentOrigin, muzzlePoint);
}
muzzlePoint[2] += (ent->client->ps.viewheight - 64);
muzzlePoint[2] += (gVR->hmdposition[1] + heightAdjust) * worldscale;
return;
@ -1863,10 +1868,13 @@ void CalcMuzzlePoints( gentity_t *ent, int weapon ) {
phase = level.time / 1000.0 * ZOOM_YAW_FREQUENCY * M_PI * 2;
viewang[YAW] += ZOOM_YAW_AMPLITUDE * sin( phase ) * ( spreadfrac + ZOOM_YAW_MIN_AMPLITUDE );
*/
VectorCopy(gVR->weaponangles, viewang);
viewang[YAW] = ent->client->ps.viewangles[YAW] + (gVR->weaponangles[YAW] - gVR->hmdorientation[YAW]);
if (weapon == WP_AKIMBO && BG_AkimboFireSequence(WP_AKIMBO, ent->client->ps.ammoclip[WP_AKIMBO], ent->client->ps.ammoclip[WP_COLT], gVR->akimboTriggerState)) {
VectorCopy(gVR->offhandweaponangles, viewang);
viewang[YAW] = ent->client->ps.viewangles[YAW] + (gVR->offhandweaponangles[YAW] - gVR->hmdorientation[YAW]);
} else {
VectorCopy(gVR->weaponangles, viewang);
viewang[YAW] = ent->client->ps.viewangles[YAW] + (gVR->weaponangles[YAW] - gVR->hmdorientation[YAW]);
}
} else {
VectorCopy( ent->client->ps.viewangles, viewang );
@ -1931,7 +1939,8 @@ void FireWeapon( gentity_t *ent ) {
case WP_SILENCER:
case WP_COLT:
case WP_AKIMBO:
aimSpreadScale += 0.4f;
// No need for penalty, dual wield penalizes enough :-)
// aimSpreadScale += 0.4f;
break;
case WP_PANZERFAUST: