Add dual wield for MP40 and Thompson; some dual wield fixes

This commit is contained in:
Petr Bartos 2023-10-28 23:21:06 +02:00
parent 1c563a2081
commit 7cfc695809
31 changed files with 501 additions and 171 deletions

View file

@ -22,6 +22,8 @@ Authors : Simon Brown
#define WP_AKIMBO 20
#define WP_AKIMBO_MP40 23
#define WP_AKIMBO_THOMPSON 24
void SV_Trace( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentmask, int capsule );
@ -183,7 +185,8 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG
float controllerYawHeading = 0.0f;
//Turn on weapon stabilisation?
qboolean stabilised = qfalse;
if (!vr.pistol && // Don't stabilise pistols
qboolean usingAkimbo = vr.weaponid == WP_AKIMBO || vr.weaponid == WP_AKIMBO_MP40 || vr.weaponid == WP_AKIMBO_THOMPSON;
if (!vr.pistol && !usingAkimbo && // Don't stabilise pistols and dual guns
(pOffTrackedRemoteNew->Buttons & ovrButton_GripTrigger) && (distance < STABILISATION_DISTANCE))
{
stabilised = qtrue;
@ -570,7 +573,7 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG
ALOGV("**WEAPON EVENT** Not Grip Pushed %sattack", (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger) ? "+" : "-");
qboolean firing = (pDominantTrackedRemoteNew->Buttons & ovrButton_Trigger);
if (vr.weaponid == WP_AKIMBO) {
if (usingAkimbo) {
if (firing) {
vr.akimboTriggerState |= ACTIVE_WEAPON_HAND;
sendButtonAction("+attack", firing);
@ -712,9 +715,9 @@ void HandleInput_Default( ovrInputStateGamepad *pFootTrackingNew, ovrInputStateG
//We need to record if we have started firing primary so that releasing trigger will stop definitely firing, if user has pushed grip
//in meantime, then it wouldn't stop the gun firing and it would get stuck
if (!vr.teleportenabled || vr.weaponid == WP_AKIMBO)
if (!vr.teleportenabled || usingAkimbo)
{
if (vr.weaponid == WP_AKIMBO && vr.backpackitemactive != 3 && !vr.binocularsActive) {
if ((usingAkimbo) && 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) ? "+" : "-");

View file

@ -275,6 +275,12 @@ static void CG_Obituary( entityState_t *ent ) {
case MOD_AKIMBO:
message = "was killed (dual colts) by";
break;
case MOD_AKIMBO_MP40:
message = "was killed (dual MP40) by";
break;
case MOD_AKIMBO_THOMPSON:
message = "was killed (dual thompson) by";
break;
case MOD_ROCKET_LAUNCHER:
message = "was killed (rl) by";
break;
@ -446,9 +452,9 @@ static void CG_ItemPickup( int itemNum ) {
weapon = itemid;
if ( weapon == WP_COLT ) {
if ( weapon == WP_COLT || weapon == WP_MP40 || weapon == WP_THOMPSON ) {
if ( COM_BitCheck( cg.snap->ps.weapons, weapon ) ) {
weapon = WP_AKIMBO; // you have colt, now get akimbo (second)
weapon = weapAlts[weapon]; // you have one, now get akimbo (second)
}
}
@ -525,6 +531,9 @@ static void CG_ItemPickup( int itemNum ) {
if ( selectIt ) {
cg.weaponSelectTime = cg.time;
cg.weaponSelect = weapon;
if (cgVR) {
cgVR->weaponid = weapon;
}
}
} // end bg_itemlist[itemNum].giType == IT_WEAPON

View file

@ -1126,8 +1126,8 @@ typedef struct {
qhandle_t loadIcon;
qhandle_t loadIconSelect;
qhandle_t arrowIcon;
qhandle_t weaponIcons[SELECTABLE_WEAPONS_NUM];
qhandle_t weaponIconsSelect[SELECTABLE_WEAPONS_NUM];
qhandle_t weaponIcons[WP_NUM_WEAPONS];
qhandle_t weaponIconsSelect[WP_NUM_WEAPONS];
qhandle_t itemSelectCursor;
qhandle_t reticleShader;

View file

@ -1316,32 +1316,40 @@ static void CG_RegisterGraphics( void ) {
// Z-order of icon rendering is based on order they were registered, not based on depth
// they are rendered at. So we are registering weapon icons again so they are properly
// rendered on weapon wheel including no-ammo overlay icon
cgs.media.weaponIcons[0] = trap_R_RegisterShader( "icons/iconw_knife_1.tga" );
cgs.media.weaponIcons[1] = trap_R_RegisterShader( "icons/iconw_luger_1.tga" );
cgs.media.weaponIcons[2] = trap_R_RegisterShader( "icons/iconw_colt_1.tga" );
cgs.media.weaponIcons[3] = trap_R_RegisterShader( "icons/iconw_MP40_1.tga" );
cgs.media.weaponIcons[4] = trap_R_RegisterShader( "icons/iconw_thompson_1.tga" );
cgs.media.weaponIcons[5] = trap_R_RegisterShader( "icons/iconw_sten_1.tga" );
cgs.media.weaponIcons[6] = trap_R_RegisterShader( "icons/iconw_mauser_1.tga" );
cgs.media.weaponIcons[7] = trap_R_RegisterShader( "icons/iconw_garand_1.tga" );
cgs.media.weaponIcons[8] = trap_R_RegisterShader( "icons/iconw_fg42_1.tga" );
cgs.media.weaponIcons[9] = trap_R_RegisterShader( "icons/iconw_panzerfaust_1.tga" );
cgs.media.weaponIcons[10] = trap_R_RegisterShader( "icons/iconw_venom_1.tga" );
cgs.media.weaponIcons[11] = trap_R_RegisterShader( "icons/iconw_flamethrower_1.tga" );
cgs.media.weaponIcons[12] = trap_R_RegisterShader( "icons/iconw_tesla_1.tga" );
cgs.media.weaponIconsSelect[0] = trap_R_RegisterShader( "icons/iconw_knife_1_select.tga" );
cgs.media.weaponIconsSelect[1] = trap_R_RegisterShader( "icons/iconw_luger_1_select.tga" );
cgs.media.weaponIconsSelect[2] = trap_R_RegisterShader( "icons/iconw_colt_1_select.tga" );
cgs.media.weaponIconsSelect[3] = trap_R_RegisterShader( "icons/iconw_MP40_1_select.tga" );
cgs.media.weaponIconsSelect[4] = trap_R_RegisterShader( "icons/iconw_thompson_1_select.tga" );
cgs.media.weaponIconsSelect[5] = trap_R_RegisterShader( "icons/iconw_sten_1_select.tga" );
cgs.media.weaponIconsSelect[6] = trap_R_RegisterShader( "icons/iconw_mauser_1_select.tga" );
cgs.media.weaponIconsSelect[7] = trap_R_RegisterShader( "icons/iconw_garand_1_select.tga" );
cgs.media.weaponIconsSelect[8] = trap_R_RegisterShader( "icons/iconw_fg42_1_select.tga" );
cgs.media.weaponIconsSelect[9] = trap_R_RegisterShader( "icons/iconw_panzerfaust_1_select.tga" );
cgs.media.weaponIconsSelect[10] = trap_R_RegisterShader( "icons/iconw_venom_1_select.tga" );
cgs.media.weaponIconsSelect[11] = trap_R_RegisterShader( "icons/iconw_flamethrower_1_select.tga" );
cgs.media.weaponIconsSelect[12] = trap_R_RegisterShader( "icons/iconw_tesla_1_select.tga" );
cgs.media.weaponIcons[WP_KNIFE] = trap_R_RegisterShader( "icons/iconw_knife_1.tga" );
cgs.media.weaponIcons[WP_LUGER] = trap_R_RegisterShader( "icons/iconw_luger_1.tga" );
cgs.media.weaponIcons[WP_SILENCER] = trap_R_RegisterShader( "icons/iconw_sluger_1.tga" );
cgs.media.weaponIcons[WP_COLT] = trap_R_RegisterShader( "icons/iconw_colt_1.tga" );
cgs.media.weaponIcons[WP_AKIMBO] = trap_R_RegisterShader( "icons/iconw_acolt_1.tga" );
cgs.media.weaponIcons[WP_MP40] = trap_R_RegisterShader( "icons/iconw_mp40_1.tga" );
cgs.media.weaponIcons[WP_AKIMBO_MP40] = trap_R_RegisterShader( "icons/iconw_amp40_1.tga" );
cgs.media.weaponIcons[WP_THOMPSON] = trap_R_RegisterShader( "icons/iconw_thompson_1.tga" );
cgs.media.weaponIcons[WP_AKIMBO_THOMPSON] = trap_R_RegisterShader( "icons/iconw_athompson_1.tga" );
cgs.media.weaponIcons[WP_STEN] = trap_R_RegisterShader( "icons/iconw_sten_1.tga" );
cgs.media.weaponIcons[WP_MAUSER] = trap_R_RegisterShader( "icons/iconw_mauser_1.tga" );
cgs.media.weaponIcons[WP_GARAND] = trap_R_RegisterShader( "icons/iconw_garand_1.tga" );
cgs.media.weaponIcons[WP_FG42] = trap_R_RegisterShader( "icons/iconw_fg42_1.tga" );
cgs.media.weaponIcons[WP_PANZERFAUST] = trap_R_RegisterShader( "icons/iconw_panzerfaust_1.tga" );
cgs.media.weaponIcons[WP_VENOM] = trap_R_RegisterShader( "icons/iconw_venom_1.tga" );
cgs.media.weaponIcons[WP_FLAMETHROWER] = trap_R_RegisterShader( "icons/iconw_flamethrower_1.tga" );
cgs.media.weaponIcons[WP_TESLA] = trap_R_RegisterShader( "icons/iconw_tesla_1.tga" );
cgs.media.weaponIconsSelect[WP_KNIFE] = trap_R_RegisterShader( "icons/iconw_knife_1_select.tga" );
cgs.media.weaponIconsSelect[WP_LUGER] = trap_R_RegisterShader( "icons/iconw_luger_1_select.tga" );
cgs.media.weaponIconsSelect[WP_SILENCER] = trap_R_RegisterShader( "icons/iconw_sluger_1_select.tga" );
cgs.media.weaponIconsSelect[WP_COLT] = trap_R_RegisterShader( "icons/iconw_colt_1_select.tga" );
cgs.media.weaponIconsSelect[WP_AKIMBO] = trap_R_RegisterShader( "icons/iconw_acolt_1_select.tga" );
cgs.media.weaponIconsSelect[WP_MP40] = trap_R_RegisterShader( "icons/iconw_mp40_1_select.tga" );
cgs.media.weaponIconsSelect[WP_AKIMBO_MP40] = trap_R_RegisterShader( "icons/iconw_amp40_1_select.tga" );
cgs.media.weaponIconsSelect[WP_THOMPSON] = trap_R_RegisterShader( "icons/iconw_thompson_1_select.tga" );
cgs.media.weaponIconsSelect[WP_AKIMBO_THOMPSON] = trap_R_RegisterShader( "icons/iconw_athompson_1_select.tga" );
cgs.media.weaponIconsSelect[WP_STEN] = trap_R_RegisterShader( "icons/iconw_sten_1_select.tga" );
cgs.media.weaponIconsSelect[WP_MAUSER] = trap_R_RegisterShader( "icons/iconw_mauser_1_select.tga" );
cgs.media.weaponIconsSelect[WP_GARAND] = trap_R_RegisterShader( "icons/iconw_garand_1_select.tga" );
cgs.media.weaponIconsSelect[WP_FG42] = trap_R_RegisterShader( "icons/iconw_fg42_1_select.tga" );
cgs.media.weaponIconsSelect[WP_PANZERFAUST] = trap_R_RegisterShader( "icons/iconw_panzerfaust_1_select.tga" );
cgs.media.weaponIconsSelect[WP_VENOM] = trap_R_RegisterShader( "icons/iconw_venom_1_select.tga" );
cgs.media.weaponIconsSelect[WP_FLAMETHROWER] = trap_R_RegisterShader( "icons/iconw_flamethrower_1_select.tga" );
cgs.media.weaponIconsSelect[WP_TESLA] = trap_R_RegisterShader( "icons/iconw_tesla_1_select.tga" );
cgs.media.noammoIcon = trap_R_RegisterShader( "icons/noammo2" );
cgs.media.itemSelectCursor = trap_R_RegisterShader( "icons/item_select_cursor.tga" );

View file

@ -255,6 +255,9 @@ static int weapIconDrawSize( int weap ) {
case WP_FG42SCOPE:
case WP_SNOOPERSCOPE:
case WP_SNIPERRIFLE:
case WP_SILENCER:
case WP_AKIMBO_MP40:
case WP_AKIMBO_THOMPSON:
return 2;
}
@ -602,6 +605,8 @@ static void CG_DrawPlayerAmmoValue( rectDef_t *rect, int font, float scale, vec4
return;
case WP_AKIMBO:
case WP_AKIMBO_MP40:
case WP_AKIMBO_THOMPSON:
special = qtrue;
break;
@ -645,7 +650,11 @@ static void CG_DrawPlayerAmmoValue( rectDef_t *rect, int font, float scale, vec4
// if(special) { // draw '0' for akimbo guns
if ( value2 || ( special && type == 1 ) ) {
Com_sprintf( num, sizeof( num ), "%i /", value2 );
if (weap == WP_AKIMBO_MP40 || weap == WP_AKIMBO_THOMPSON) {
Com_sprintf( num, sizeof( num ), "%i/ ", value2 );
} else {
Com_sprintf( num, sizeof( num ), "%i /", value2 );
}
value = CG_Text_Width( num, font, scale, 0 );
CG_Text_Paint( -30 + rect->x + ( rect->w - value ) / 2, rect->y + rect->h, font, scale, color, num, 0, 0, textStyle );
}
@ -1436,8 +1445,9 @@ float CG_GetValue( int ownerDraw, int type ) {
case CG_PLAYER_AMMOCLIP_VALUE:
if ( cent->currentState.weapon ) {
if ( type == RANGETYPE_RELATIVE ) {
if (cent->currentState.weapon == WP_AKIMBO) {
return (float)(ps->ammoclip[WP_AKIMBO] + ps->ammoclip[WP_COLT]) / (float)(ammoTable[WP_AKIMBO].maxclip * 4);
int weapon = cent->currentState.weapon;
if (weapon == WP_AKIMBO || weapon == WP_AKIMBO_MP40 || weapon == WP_AKIMBO_THOMPSON) {
return (float)(ps->ammoclip[BG_FindClipForWeapon(weapon)] + ps->ammoclip[BG_FindClipForWeapon(weapAlts[weapon])]) / (float)(ammoTable[weapon].maxclip * 4);
} else {
return (float)ps->ammoclip[BG_FindClipForWeapon( cent->currentState.weapon )] / (float)ammoTable[cent->currentState.weapon].maxclip;
}

View file

@ -74,7 +74,9 @@ void CG_CheckAmmo( void ) {
case WP_FG42:
case WP_FG42SCOPE:
case WP_MP40:
case WP_AKIMBO_MP40:
case WP_THOMPSON:
case WP_AKIMBO_THOMPSON:
case WP_STEN:
case WP_VENOM:
case WP_TESLA:

View file

@ -377,10 +377,10 @@ static void CG_TouchItem( centity_t *cent ) {
//----(SA) added
weapon = item->giTag;
if ( weapon == WP_COLT ) {
if ( COM_BitCheck( cg.predictedPlayerState.weapons, WP_COLT ) ) {
// you got the colt, you gettin' another
weapon = WP_AKIMBO;
if ( weapon == WP_COLT || weapon == WP_MP40 || weapon == WP_THOMPSON ) {
if ( COM_BitCheck( cg.predictedPlayerState.weapons, weapon ) ) {
// you got one, you gettin' another
weapon = weapAlts[weapon];
}
}
//----(SA) end

View file

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

View file

@ -250,7 +250,7 @@ int weapBanks[MAX_WEAP_BANKS][MAX_WEAPS_IN_BANK] = {
{WP_KNIFE, 0, 0 }, // 1
{WP_LUGER, WP_COLT, 0 }, // 2 // WP_AKIMBO
{WP_MP40, WP_THOMPSON, WP_STEN }, // 3
{WP_MP40, WP_THOMPSON, WP_STEN }, // 3 // WP_AKIMBO MP40 & THOMPSON
{WP_MAUSER, WP_GARAND, 0 }, // 4
{WP_FG42, 0, 0 }, // 5
{WP_GRENADE_LAUNCHER, WP_GRENADE_PINEAPPLE, WP_DYNAMITE }, // 6
@ -1504,6 +1504,16 @@ void CG_RegisterWeapon( int weaponNum ) {
weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
break;
case WP_AKIMBO_THOMPSON:
// same as thompson
MAKERGB( weaponInfo->flashDlightColor, 1.0, 0.6, 0.23 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/thompson/thompson.wav" );
weaponInfo->flashEchoSound[0] = trap_S_RegisterSound( "sound/weapons/mp40/mp40e1.wav" ); // use same as mp40
weaponInfo->reloadSound = trap_S_RegisterSound( "sound/weapons/thompson/thompson_reload.wav" );
weaponInfo->overheatSound = trap_S_RegisterSound( "sound/weapons/thompson/thompson_overheat.wav" );
weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
break;
case WP_THOMPSON:
MAKERGB( weaponInfo->flashDlightColor, 1.0, 0.6, 0.23 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/thompson/thompson.wav" );
@ -1513,6 +1523,16 @@ void CG_RegisterWeapon( int weaponNum ) {
weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
break;
case WP_AKIMBO_MP40:
// same as MP40
MAKERGB( weaponInfo->flashDlightColor, 1.0, 0.6, 0.23 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/mp40/mp40f1.wav" );
weaponInfo->flashEchoSound[0] = trap_S_RegisterSound( "sound/weapons/mp40/mp40e1.wav" );
weaponInfo->reloadSound = trap_S_RegisterSound( "sound/weapons/mp40/mp40_reload.wav" );
weaponInfo->overheatSound = trap_S_RegisterSound( "sound/weapons/mp40/mp40_overheat.wav" );
weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
break;
case WP_MP40:
MAKERGB( weaponInfo->flashDlightColor, 1.0, 0.6, 0.23 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/mp40/mp40f1.wav" );
@ -2087,8 +2107,8 @@ static float CG_CalculateWeaponPositionAndScale( playerState_t *ps, vec3_t origi
else if (ps->weapon != 0)
{
char cvar_name[64];
if (ps->weapon == WP_AKIMBO) {
Com_sprintf(cvar_name, sizeof(cvar_name), "vr_weapon_adjustment_%i", WP_COLT);
if (ps->weapon == WP_AKIMBO || ps->weapon == WP_AKIMBO_MP40 || ps->weapon == WP_AKIMBO_THOMPSON) {
Com_sprintf(cvar_name, sizeof(cvar_name), "vr_weapon_adjustment_%i", weapAlts[ps->weapon]);
} else {
Com_sprintf(cvar_name, sizeof(cvar_name), "vr_weapon_adjustment_%i", ps->weapon);
}
@ -2877,8 +2897,13 @@ static qboolean CG_CalcMuzzlePoint( int entityNum, int dist, vec3_t muzzle ) {
cent = &cg_entities[entityNum];
if ( entityNum == cg.snap->ps.clientNum ) {
vec3_t 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);
int weapon = cent->currentState.weapon;
if (weapon == WP_AKIMBO || weapon == WP_AKIMBO_MP40 || weapon == WP_AKIMBO_THOMPSON) {
if (BG_AkimboFireSequence(weapon, cg.snap->ps.ammoclip[weapon], cg.snap->ps.ammoclip[weapAlts[weapon]], cgVR->akimboTriggerState)) {
CG_CalculateVROffHandWeaponPosition(muzzle, angles);
} else {
CG_CalculateVRWeaponPosition(weapon, muzzle, angles);
}
} else {
CG_CalculateVRWeaponPosition(cent->currentState.weapon, muzzle, angles);
}
@ -2935,6 +2960,7 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
qboolean firing; // Ridah
qboolean akimboFire = qfalse; //----(SA) added
qboolean useAkimbo = qfalse;
qboolean playerScaled;
qboolean drawpart, drawrealweap;
@ -3002,8 +3028,20 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
}
} else {
if (weaponNum == WP_AKIMBO) {
CG_RegisterWeapon(WP_AKIMBO);
CG_RegisterWeapon(WP_COLT);
weapon = &cg_weapons[WP_COLT];
useAkimbo = qtrue;
} else if (weaponNum == WP_AKIMBO_MP40) {
CG_RegisterWeapon(WP_AKIMBO_MP40);
CG_RegisterWeapon(WP_MP40);
weapon = &cg_weapons[WP_MP40];
useAkimbo = qtrue;
} else if (weaponNum == WP_AKIMBO_THOMPSON) {
CG_RegisterWeapon(WP_AKIMBO_THOMPSON);
CG_RegisterWeapon(WP_THOMPSON);
weapon = &cg_weapons[WP_THOMPSON];
useAkimbo = qtrue;
} else {
CG_RegisterWeapon( weaponNum );
weapon = &cg_weapons[weaponNum];
@ -3013,9 +3051,13 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
if ( isPlayer ) {
akimboFire = BG_AkimboFireSequence( weaponNum, cg.predictedPlayerState.ammoclip[WP_AKIMBO], cg.predictedPlayerState.ammoclip[WP_COLT], cgVR->akimboTriggerState );
if (useAkimbo) {
akimboFire = BG_AkimboFireSequence( weaponNum, cg.predictedPlayerState.ammoclip[weaponNum], cg.predictedPlayerState.ammoclip[weapAlts[weaponNum]], cgVR->akimboTriggerState );
}
} else if ( ps ) {
akimboFire = BG_AkimboFireSequence( weaponNum, ps->ammoclip[WP_AKIMBO], ps->ammoclip[WP_AKIMBO], 0 );
if (useAkimbo) {
akimboFire = BG_AkimboFireSequence( weaponNum, ps->ammoclip[weaponNum], ps->ammoclip[weapAlts[weaponNum]], 0 );
}
}
// add the weapon
@ -3136,7 +3178,9 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
brassOffset[WP_AKIMBO] = 1;
brassOffset[WP_FG42] = 1;
brassOffset[WP_MP40] = 2;
brassOffset[WP_AKIMBO_MP40] = 2;
brassOffset[WP_THOMPSON] = 2;
brassOffset[WP_AKIMBO_THOMPSON] = 2;
brassOffset[WP_STEN] = 6;
brassOffset[WP_VENOM] = 5;
@ -3555,6 +3599,8 @@ CG_AddViewWeapon
Add the weapon, and flash for the player's view
==============
*/
#define TRIGGER_SECONDARY 1
#define TRIGGER_PRIMARY 2
void CG_AddViewWeapon( playerState_t *ps ) {
refEntity_t hand;
refEntity_t handAkimbo;
@ -3565,6 +3611,7 @@ void CG_AddViewWeapon( playerState_t *ps ) {
vec3_t gunoffAkimbo;
weaponInfo_t *weapon;
weaponInfo_t *weaponAkimbo;
qboolean useAkimbo = qfalse;
if ( ps->persistant[PERS_TEAM] == TEAM_SPECTATOR ) {
return;
@ -3640,6 +3687,19 @@ void CG_AddViewWeapon( playerState_t *ps ) {
CG_RegisterWeapon( WP_AKIMBO );
weapon = &cg_weapons[ WP_COLT ];
weaponAkimbo = &cg_weapons[ WP_AKIMBO ];
useAkimbo = qtrue;
} else if (ps->weapon == WP_AKIMBO_MP40) {
CG_RegisterWeapon( WP_MP40 );
CG_RegisterWeapon( WP_AKIMBO_MP40 );
weapon = &cg_weapons[ WP_MP40 ];
weaponAkimbo = &cg_weapons[ WP_AKIMBO_MP40 ];
useAkimbo = qtrue;
} else if (ps->weapon == WP_AKIMBO_THOMPSON) {
CG_RegisterWeapon( WP_THOMPSON );
CG_RegisterWeapon( WP_AKIMBO_THOMPSON );
weapon = &cg_weapons[ WP_THOMPSON ];
weaponAkimbo = &cg_weapons[ WP_AKIMBO_THOMPSON ];
useAkimbo = qtrue;
} else {
CG_RegisterWeapon( ps->weapon );
weapon = &cg_weapons[ ps->weapon ];
@ -3679,21 +3739,24 @@ void CG_AddViewWeapon( playerState_t *ps ) {
handAkimbo.frame = handAkimbo.oldframe = cg_gun_frame.integer;
handAkimbo.backlerp = 0;
} else { // get the animation state
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) {
if (useAkimbo) {
int weapAnim = 0;
if ( ps->weapAnim & ~ANIM_TOGGLEBIT ) {
weapAnim = ps->weapAnim & ~ANIM_TOGGLEBIT;
}
if (ps->weaponstate == WEAPON_FIRING || 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) {
} else if (ps->weaponstate == WEAPON_RELOADING || 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) {
if (ps->ammoclip[weapAlts[ps->weapon]] < ammoTable[weapAlts[ps->weapon]].maxclip) {
CG_WeaponAnimation( ps, weapon, &hand.oldframe, &hand.frame, &hand.backlerp );
}
if (ps->ammoclip[WP_AKIMBO] < 8) {
if (ps->ammoclip[ps->weapon] < ammoTable[ps->weapon].maxclip) {
CG_WeaponAnimation( ps, weaponAkimbo, &handAkimbo.oldframe, &handAkimbo.frame, &handAkimbo.backlerp );
}
} else {
@ -3708,7 +3771,9 @@ void CG_AddViewWeapon( playerState_t *ps ) {
if (cgVR->backpackitemactive != 3 && !cgVR->binocularsActive)
{
hand.hModel = weapon->handsModel;
handAkimbo.hModel = weaponAkimbo->handsModel;
if (useAkimbo) {
handAkimbo.hModel = weaponAkimbo->handsModel;
}
}
//Weapon offset debugging
@ -3769,7 +3834,7 @@ void CG_AddViewWeapon( playerState_t *ps ) {
// add everything onto the hand
CG_AddPlayerWeapon(&hand, ps, &cg.predictedPlayerEntity, qfalse);
if (ps->weapon == WP_AKIMBO && cgVR->backpackitemactive != 3 && !cgVR->binocularsActive) {
if (useAkimbo && cgVR->backpackitemactive != 3 && !cgVR->binocularsActive) {
CG_AddPlayerWeapon(&handAkimbo, ps, &cg.predictedPlayerEntity, qtrue);
}
// Ridah
@ -3807,7 +3872,7 @@ void CG_AddViewWeapon( playerState_t *ps ) {
}
CG_LaserSight(ps, qfalse);
if (ps->weapon == WP_AKIMBO) {
if (useAkimbo) {
CG_LaserSight(ps, qtrue);
}
@ -3932,6 +3997,9 @@ void CG_DrawWeaponSelect( void ) {
case WP_FLAMETHROWER:
case WP_FG42:
case WP_FG42SCOPE:
case WP_SILENCER:
case WP_AKIMBO_MP40:
case WP_AKIMBO_THOMPSON:
wideweap = qtrue;
break;
default:
@ -4634,9 +4702,22 @@ void CG_DrawWheelSelector( void )
selectorWheelEntity_t item;
memset(&item, 0, sizeof(item));
if (weaponNum == WP_LUGER && CG_WeaponAvailable(WP_SILENCER)) {
item.itemId = WP_SILENCER;
item.itemId = weapBanks[2][0];
} else if (weaponNum == WP_COLT && CG_WeaponAvailable(WP_AKIMBO)) {
item.itemId = WP_AKIMBO;
item.itemId = weapBanks[2][1];
if (!CG_WeaponHasAmmo(item.itemId)) {
item.itemId = weapAlts[item.itemId];
}
} else if (weaponNum == WP_MP40 && CG_WeaponAvailable(WP_AKIMBO_MP40)) {
item.itemId = weapBanks[3][0];
if (!CG_WeaponHasAmmo(item.itemId)) {
item.itemId = weapAlts[item.itemId];
}
} else if (weaponNum == WP_THOMPSON && CG_WeaponAvailable(WP_AKIMBO_THOMPSON)) {
item.itemId = weapBanks[3][1];
if (!CG_WeaponHasAmmo(item.itemId)) {
item.itemId = weapAlts[item.itemId];
}
} else {
item.itemId = weaponNum;
}
@ -4644,7 +4725,7 @@ void CG_DrawWheelSelector( void )
refEntity_t icon;
memset(&icon, 0, sizeof(icon));
icon.reType = RT_SPRITE;
icon.customShader = cgs.media.weaponIcons[i];
icon.customShader = cgs.media.weaponIcons[item.itemId];
icon.radius = 0.8f;
memset(icon.shaderRGBA, 0xff, 4);
item.icon = icon;
@ -4652,12 +4733,12 @@ void CG_DrawWheelSelector( void )
refEntity_t iconSelected;
memset(&iconSelected, 0, sizeof(iconSelected));
iconSelected.reType = RT_SPRITE;
iconSelected.customShader = cgs.media.weaponIconsSelect[i];
iconSelected.customShader = cgs.media.weaponIconsSelect[item.itemId];
iconSelected.radius = 1.3f;
memset(iconSelected.shaderRGBA, 0xff, 4);
item.iconSelected = iconSelected;
if (!CG_WeaponHasAmmo(weaponNum)) {
if (!CG_WeaponHasAmmo(item.itemId)) {
item.notSelectable = qtrue;
refEntity_t labelNotSelectable;
memset(&labelNotSelectable, 0, sizeof(labelNotSelectable));
@ -5310,6 +5391,20 @@ void CG_AltWeapon_f( void ) {
case WP_COLT:
weapBanks[2][1] = WP_AKIMBO;
break;
case WP_AKIMBO_MP40:
weapBanks[3][0] = WP_MP40;
break;
case WP_MP40:
weapBanks[3][0] = WP_AKIMBO_MP40;
break;
case WP_AKIMBO_THOMPSON:
weapBanks[3][1] = WP_THOMPSON;
break;
case WP_THOMPSON:
weapBanks[3][1] = WP_AKIMBO_THOMPSON;
break;
}
//----(SA) end
@ -6062,7 +6157,9 @@ void CG_WeaponFireRecoil( int weapon ) {
case WP_FG42SCOPE:
case WP_FG42:
case WP_MP40:
case WP_AKIMBO_MP40:
case WP_THOMPSON:
case WP_AKIMBO_THOMPSON:
case WP_STEN:
//pitchRecoilAdd = 1;
pitchAdd = 1 + rand() % 3;
@ -6528,9 +6625,11 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, in
case WP_SNIPERRIFLE:
case WP_SNOOPERSCOPE:
case WP_MP40:
case WP_AKIMBO_MP40:
case WP_FG42:
case WP_FG42SCOPE:
case WP_THOMPSON:
case WP_AKIMBO_THOMPSON:
case WP_STEN:
case WP_SILENCER:
case WP_VENOM:

View file

@ -1070,7 +1070,7 @@ typedef enum
#define MAX_WEAPS_IN_BANK_MP 8
#define MAX_WEAP_BANKS_MP 7
// jpw
#define MAX_WEAP_ALTS WP_DYNAMITE
#define MAX_WEAP_ALTS WP_AKIMBO_THOMPSON
// bit field limits

View file

@ -1866,6 +1866,8 @@ float AICast_GetWeaponSoundRange( int weapon ) {
case WP_MP40:
case WP_THOMPSON:
case WP_AKIMBO_MP40:
case WP_AKIMBO_THOMPSON:
return 1000;
case WP_FG42:

View file

@ -2896,7 +2896,7 @@ char *AIFunc_BattleChase( cast_state_t *cs ) {
//
// if they are visible, but not attackable, look for a spot where we can attack them, and head
// for there. This should prevent AI's getting stuck in a bunch.
if ( !moved && cs->weaponNum >= WP_LUGER && cs->weaponNum <= WP_AKIMBO && cs->attributes[TACTICAL] >= 0.1 ) {
if ( !moved && ((cs->weaponNum >= WP_LUGER && cs->weaponNum <= WP_AKIMBO) || cs->weaponNum == WP_AKIMBO_MP40 || cs->weaponNum == WP_AKIMBO_THOMPSON ) && cs->attributes[TACTICAL] >= 0.1 ) {
//
// check for another movement we should be making
if ( cs->obstructingTime > level.time ) {

View file

@ -1321,10 +1321,10 @@ qboolean AICast_ScriptAction_GiveWeapon( cast_state_t *cs, char *params ) {
}
}
if ( weapon == WP_COLT ) {
// if you had the colt already, now you've got two!
if ( COM_BitCheck( g_entities[cs->entityNum].client->ps.weapons, WP_COLT ) ) {
weapon = WP_AKIMBO;
if ( weapon == WP_COLT || weapon == WP_MP40 || weapon == WP_THOMPSON ) {
// if you had one already, now you've got two!
if ( COM_BitCheck( g_entities[cs->entityNum].client->ps.weapons, weapon ) ) {
weapon = weapAlts[weapon];
}
}
@ -1407,13 +1407,13 @@ qboolean AICast_ScriptAction_TakeWeapon( cast_state_t *cs, char *params ) {
if ( weapon != WP_NONE ) {
qboolean clear;
if ( weapon == WP_AKIMBO ) {
// take both the colt /and/ the akimbo weapons when 'akimbo' is specified
COM_BitClear( g_entities[cs->entityNum].client->ps.weapons, WP_COLT );
} else if ( weapon == WP_COLT ) {
// take 'akimbo' first if it's there, then take 'colt'
if ( COM_BitCheck( g_entities[cs->entityNum].client->ps.weapons, WP_AKIMBO ) ) {
weapon = WP_AKIMBO;
if ( weapon == WP_AKIMBO || weapon == WP_AKIMBO_MP40 || weapon == WP_AKIMBO_THOMPSON ) {
// take both the main gun /and/ the akimbo weapons when 'akimbo' is specified
COM_BitClear( g_entities[cs->entityNum].client->ps.weapons, weapAlts[weapon] );
} else if ( weapon == WP_COLT || weapon == WP_MP40 || weapon == WP_THOMPSON ) {
// take 'akimbo' first if it's there, then take single gun
if ( COM_BitCheck( g_entities[cs->entityNum].client->ps.weapons, weapAlts[weapon] ) ) {
weapon = weapAlts[weapon];
}
}

View file

@ -130,13 +130,15 @@ ammotable_t ammoTable[] = {
// { 100, 1, 100, 1000, DELAY_PISTOL, 900, 0, 0, MOD_CROSS }, // WP_CROSS // 29
{ 10, 1, 10, 1000, DELAY_THROW_VR, 1600, 0, 0, MOD_DYNAMITE }, // WP_DYNAMITE // 30
// { 10, 1, 10, 1000, DELAY_THROW, 1600, 0, 0, MOD_DYNAMITE }, // WP_DYNAMITE2 // 31
{ MAX_AMMO_9MM, 1, 32, 2600, DELAY_LOW, 70, 0, 0, MOD_AKIMBO_MP40 }, // WP_AKIMBO_MP40 // 32
{ MAX_AMMO_45, 1, 30, 2400, DELAY_LOW, 90, 0, 0, MOD_AKIMBO_THOMPSON }, // WP_AKIMBO_THOMPSON // 33
// stubs for some "not-real" weapons (so they always return "yes, you have enough ammo for that gauntlet", etc.)
// { 5, 1, 5, 1000, DELAY_SHOULDER, 1200, 0, 0, 0 /*mod_prox*/ }, // WP_PROX // 32
{ 999, 0, 999, 0, 50, 0, 0, 0, 0 }, // WP_MONSTER_ATTACK1 // 33
{ 999, 0, 999, 0, 50, 0, 0, 0, 0 }, // WP_MONSTER_ATTACK2 // 34
{ 999, 0, 999, 0, 50, 0, 0, 0, 0 }, // WP_MONSTER_ATTACK3 // 35
{ 999, 0, 999, 0, 50, 0, 0, 0, 0 } // WP_GAUNTLET // 36
// { 5, 1, 5, 1000, DELAY_SHOULDER, 1200, 0, 0, 0 /*mod_prox*/ }, // WP_PROX // 34
{ 999, 0, 999, 0, 50, 0, 0, 0, 0 }, // WP_MONSTER_ATTACK1 // 35
{ 999, 0, 999, 0, 50, 0, 0, 0, 0 }, // WP_MONSTER_ATTACK2 // 36
{ 999, 0, 999, 0, 50, 0, 0, 0, 0 }, // WP_MONSTER_ATTACK3 // 37
{ 999, 0, 999, 0, 50, 0, 0, 0, 0 } // WP_GAUNTLET // 38
};
@ -145,7 +147,7 @@ int weapAlts[] = {
WP_NONE, // 0 WP_NONE
WP_NONE, // 1 WP_KNIFE
WP_SILENCER, // 2 WP_LUGER
WP_NONE, // 3 WP_MP40
WP_AKIMBO_MP40, // 3 WP_MP40
WP_SNIPERRIFLE, // 4 WP_MAUSER
WP_FG42SCOPE, // 5 WP_FG42 // was SP5
WP_NONE, // 6 WP_GRENADE_LAUNCHER
@ -156,7 +158,7 @@ int weapAlts[] = {
// WP_SPEARGUN_CO2, // 11 WP_SPEARGUN
// WP_NONE, // 12 WP_KNIFE2
WP_AKIMBO, // 13 WP_COLT //----(SA) new
WP_NONE, // 14 WP_THOMPSON
WP_AKIMBO_THOMPSON, // 14 WP_THOMPSON
WP_SNOOPERSCOPE, // 15 WP_GARAND
// WP_BAR2, // 16 WP_BAR //----(SA) modified
WP_NONE, // 17 WP_GRENADE_PINEAPPLE
@ -172,8 +174,10 @@ int weapAlts[] = {
WP_COLT, // 27 WP_AKIMBO //----(SA) new
WP_NONE, // 28 WP_CLASS_SPECIAL
// WP_NONE, // 29 WP_CROSS
WP_NONE // 30 WP_DYNAMITE //----(SA) modified (not in rotation yet)
WP_NONE, // 30 WP_DYNAMITE //----(SA) modified (not in rotation yet)
// WP_DYNAMITE // 31 WP_DYNAMITE2 //----(SA) new
WP_MP40, // 32 WP_AKIMBO_MP40
WP_THOMPSON // 33 WP_AKIMBO_THOMPSON
};
@ -1020,6 +1024,30 @@ model="models/weapons2/mauser/mauser.md3"
{0,0,0,0}
},
/*weapon_akimbo
dual thompson
*/
{
"weapon_akimbo_thompson",
"sound/misc/w_pkup.wav",
{ "models/weapons2/thompson/thompson.md3",
"models/weapons2/thompson/v_thompson.md3",
"models/weapons2/thompson/pu_thompson.md3",
0, 0 },
"icons/iconw_athompson_1", // icon
"icons/ammo2", // ammo icon
"Dual Thompsons", // pickup
30,
IT_WEAPON,
WP_AKIMBO_THOMPSON,
WP_COLT,
WP_AKIMBO_THOMPSON,
"", // precache
"", // sounds
{0,0,0,0}
},
/*QUAKED weapon_thompson (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
model="models/weapons2/thompson/thompson.md3"
@ -1080,7 +1108,7 @@ dual colts
"models/weapons2/colt/pu_colt.md3",
0, 0 },
"icons/iconw_colt_1", // icon
"icons/iconw_acolt_1", // icon
"icons/ammo2", // ammo icon
"Dual Colts", // pickup
50,
@ -1147,6 +1175,30 @@ model="models/weapons2/garand/garand.md3"
{0,0,0,0}
},
/*weapon_akimbo
dual MP40
*/
{
"weapon_akimbo_mp40",
"sound/misc/w_pkup.wav",
{ "models/weapons2/mp40/mp40.md3",
"models/weapons2/mp40/v_mp40.md3",
"models/weapons2/mp40/pu_mp40.md3",
0, 0 },
"icons/iconw_amp40_1", // icon
"icons/ammo2", // ammo icon
"Dual MP40", // pickup
30,
IT_WEAPON,
WP_AKIMBO_MP40,
WP_LUGER,
WP_AKIMBO_MP40,
"", // precache
"", // sounds
{0,0,0,0}
},
/*QUAKED weapon_mp40 (.3 .3 1) (-16 -16 -16) (16 16 16) SUSPENDED SPIN - RESPAWN
"stand" values:
no value: laying in a default position on it's side (default)
@ -1272,7 +1324,7 @@ model="models/weapons2/sp5/sp5.md3"
"models/weapons2/silencer/pu_silencer.md3",
0, 0},
"icons/iconw_silencer_1", // icon
"icons/iconw_sluger_1", // icon
"icons/ammo5", // ammo icon
// "Silencer", // pickup
"sp5 pistol",
@ -3623,10 +3675,10 @@ BG_AkimboFireSequence
==============
*/
//qboolean BG_AkimboFireSequence( playerState_t *ps ) {
qboolean BG_AkimboFireSequence( int weapon, int akimboClip, int coltClip, int triggerState ) {
qboolean BG_AkimboFireSequence( int weapon, int akimboClip, int mainClip, int triggerState ) {
// NOTE: this doesn't work when clips are turned off (dmflags 64)
if ( weapon != WP_AKIMBO ) {
if ( weapon != WP_AKIMBO && weapon != WP_AKIMBO_MP40 && weapon != WP_AKIMBO_THOMPSON ) {
return qfalse;
}
@ -3642,14 +3694,14 @@ qboolean BG_AkimboFireSequence( int weapon, int akimboClip, int coltClip, int tr
if ( !akimboClip ) {
return qfalse;
}
if ( !coltClip ) {
if ( !mainClip ) {
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 );
return ( ( akimboClip + mainClip ) & 1 );
}
//----(SA) end

View file

@ -2068,7 +2068,7 @@ static void PM_BeginWeaponReload( int weapon ) {
return;
}
if ( weapon < WP_BEGINGERMAN || weapon > WP_DYNAMITE ) {
if ( weapon < WP_BEGINGERMAN || weapon > WP_AKIMBO_THOMPSON ) {
return;
}
@ -2150,7 +2150,10 @@ static void PM_BeginWeaponChange( int oldweapon, int newweapon, qboolean reload
return;
}
altswitch = (qboolean)( newweapon == weapAlts[oldweapon] );
altswitch = (qboolean)( newweapon == weapAlts[oldweapon]
&& newweapon != WP_AKIMBO && newweapon != WP_COLT
&& newweapon != WP_AKIMBO_MP40 && newweapon != WP_MP40
&& newweapon != WP_AKIMBO_THOMPSON && newweapon != WP_THOMPSON );
showdrop = qtrue;
@ -2326,6 +2329,12 @@ PM_ReloadClip
==============
*/
static void PM_ReloadClip( int weapon ) {
if ( weapon == WP_AKIMBO || weapon == WP_AKIMBO_MP40 || weapon == WP_AKIMBO_THOMPSON ) {
// When using akimbo, reload main weapon first to be able
// to use it as single weapon in case ammo runs out.
PM_ReloadClip( weapAlts[weapon] );
}
int ammoreserve, ammoclip, ammomove;
ammoreserve = pm->ps->ammo[ BG_FindAmmoForWeapon( weapon )];
@ -2342,9 +2351,6 @@ static void PM_ReloadClip( int weapon ) {
pm->ps->ammoclip[BG_FindClipForWeapon( weapon )] += ammomove;
}
if ( weapon == WP_AKIMBO ) { // reload colt too
PM_ReloadClip( WP_COLT );
}
}
/*
@ -2429,9 +2435,9 @@ void PM_CheckForReload( int weapon ) {
if ( pm->ps->ammoclip[clipWeap] < ammoTable[weapon].maxclip ) {
doReload = qtrue;
}
if ( weapon == WP_AKIMBO ) {
// akimbo should also check Colt status
if ( pm->ps->ammoclip[BG_FindClipForWeapon( WP_COLT )] < ammoTable[BG_FindClipForWeapon( WP_COLT )].maxclip ) {
if ( weapon == WP_AKIMBO || weapon == WP_AKIMBO_MP40 || weapon == WP_AKIMBO_THOMPSON ) {
// akimbo should also check main status
if ( pm->ps->ammoclip[BG_FindClipForWeapon( weapAlts[weapon] )] < ammoTable[BG_FindClipForWeapon( weapAlts[weapon] )].maxclip ) {
doReload = qtrue;
}
}
@ -2440,14 +2446,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 ) { // reload only if both clips are empty
if ( !( pm->ps->ammoclip[WP_COLT] ) && !( pm->ps->ammoclip[WP_COLT] ) ) {
if ( weapon == WP_AKIMBO || weapon == WP_AKIMBO_MP40 || weapon == WP_AKIMBO_THOMPSON ) { // reload only if both clips are empty
if ( !( pm->ps->ammoclip[weapAlts[weapon]] ) ) {
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 ) { // reload only if both clips are empty
if ( !( pm->ps->ammoclip[WP_COLT] ) && !( pm->ps->ammoclip[WP_AKIMBO] ) ) {
// likewise. however, you need to check if you've got the akimbo selected, since you could have the main alone
} else if ( weapon == WP_COLT || weapon == WP_MP40 || weapon == WP_THOMPSON ) { // weapon checking for reload is colt...
if ( pm->ps->weapon == weapAlts[weapon] ) { // reload only if both clips are empty
if ( !( pm->ps->ammoclip[weapon] ) && !( pm->ps->ammoclip[weapAlts[weapon]] ) ) {
doReload = qtrue; // so reload
}
} else { // single colt selected
@ -2537,7 +2543,7 @@ void PM_WeaponUseAmmo( int wp, int amount ) {
pm->ps->ammo[ BG_FindAmmoForWeapon( wp )] -= amount;
} else {
takeweapon = BG_FindClipForWeapon( wp );
if ( wp == WP_AKIMBO ) {
if ( wp == WP_AKIMBO || wp == WP_AKIMBO_MP40 || wp == WP_AKIMBO_THOMPSON ) {
int triggerState = 0;
#ifdef CGAMEDLL
triggerState = cgVR->akimboTriggerState;
@ -2545,8 +2551,8 @@ void PM_WeaponUseAmmo( int wp, int amount ) {
#ifdef GAMEDLL
triggerState = gVR->akimboTriggerState;
#endif
if ( !BG_AkimboFireSequence( wp, pm->ps->ammoclip[WP_AKIMBO], pm->ps->ammoclip[WP_COLT], triggerState ) ) {
takeweapon = WP_COLT;
if ( !BG_AkimboFireSequence( wp, pm->ps->ammoclip[wp], pm->ps->ammoclip[weapAlts[wp]], triggerState ) ) {
takeweapon = weapAlts[wp];
}
}
@ -2569,7 +2575,7 @@ int PM_WeaponAmmoAvailable( int wp ) {
} else {
// return pm->ps->ammoclip[BG_FindClipForWeapon( wp )];
takeweapon = BG_FindClipForWeapon( wp );
if ( wp == WP_AKIMBO ) {
if ( wp == WP_AKIMBO || wp == WP_AKIMBO_MP40 || wp == WP_AKIMBO_THOMPSON ) {
int triggerState = 0;
#ifdef CGAMEDLL
triggerState = cgVR->akimboTriggerState;
@ -2577,8 +2583,8 @@ int PM_WeaponAmmoAvailable( int wp ) {
#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;
if ( !BG_AkimboFireSequence( pm->ps->weapon, pm->ps->ammoclip[wp], pm->ps->ammoclip[weapAlts[wp]], triggerState ) ) {
takeweapon = weapAlts[wp];
}
}
@ -2674,10 +2680,8 @@ void PM_AdjustAimSpreadScale( void ) {
case WP_SILENCER:
wpnScale = 0.5f;
break;
case WP_AKIMBO: //----(SA) added
wpnScale = 0.5;
break;
case WP_COLT:
case WP_AKIMBO:
wpnScale = 0.4f; // doesn't fire as fast, but easier to handle than luger
break;
case WP_VENOM:
@ -2696,6 +2700,7 @@ void PM_AdjustAimSpreadScale( void ) {
wpnScale = 0.5f;
break;
case WP_MP40:
case WP_AKIMBO_MP40:
wpnScale = 0.5f; // 2 handed, but not as long as mauser, so harder to keep aim
break;
case WP_FG42:
@ -2705,6 +2710,7 @@ void PM_AdjustAimSpreadScale( void ) {
wpnScale = 0.7f;
break;
case WP_THOMPSON:
case WP_AKIMBO_THOMPSON:
wpnScale = 0.4f;
break;
case WP_STEN:
@ -2878,7 +2884,11 @@ static void PM_Weapon( void ) {
triggerState = gVR->akimboTriggerState;
}
#endif
akimboFire = BG_AkimboFireSequence( pm->ps->weapon, pm->ps->ammoclip[WP_AKIMBO], pm->ps->ammoclip[WP_COLT], triggerState );
if (pm->ps->weapon == WP_AKIMBO || pm->ps->weapon == WP_AKIMBO_MP40 || pm->ps->weapon == WP_AKIMBO_THOMPSON) {
akimboFire = BG_AkimboFireSequence( pm->ps->weapon, pm->ps->ammoclip[pm->ps->weapon], pm->ps->ammoclip[weapAlts[pm->ps->weapon]], triggerState );
} else {
akimboFire = qfalse;
}
if ( 0 ) {
switch ( pm->ps->weaponstate ) {
@ -3153,13 +3163,6 @@ 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
if ( g_gametype.integer == GT_WOLF ) {
@ -3205,6 +3208,21 @@ if ( !( pm->cmd.buttons & ( BUTTON_ATTACK | WBUTTON_ATTACK2 ) ) && !delayedFire
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 || pm->ps->weapon == WP_AKIMBO_MP40 || pm->ps->weapon == WP_AKIMBO_THOMPSON) && !triggerState) {
pm->ps->weaponTime = 0;
pm->ps->weaponDelay = 0;
if ( weaponstateFiring ) { // you were just firing, time to relax
PM_ContinueWeaponAnim( WEAP_IDLE1 );
}
pm->ps->weaponstate = WEAPON_READY;
return;
}
if ( gameReloading ) {
return;
@ -3243,7 +3261,9 @@ default:
break;
// machineguns should continue the anim, rather than start each fire
case WP_MP40:
case WP_AKIMBO_MP40:
case WP_THOMPSON:
case WP_AKIMBO_THOMPSON:
case WP_STEN:
case WP_VENOM:
case WP_FG42:
@ -3350,8 +3370,10 @@ if ( pm->ps->weapon ) {
break;
case WP_AKIMBO:
case WP_AKIMBO_MP40:
case WP_AKIMBO_THOMPSON:
// do not reload but continue fire if there is ammo in other gun
if (pm->ps->ammoclip[WP_AKIMBO] || pm->ps->ammoclip[WP_COLT]) {
if (pm->ps->ammoclip[pm->ps->weapon] || pm->ps->ammoclip[weapAlts[pm->ps->weapon]]) {
reloadingW = qfalse;
playswitchsound = qfalse;
// notify player that one gun is empty
@ -3414,18 +3436,10 @@ if ( ammoTable[pm->ps->weapon].maxHeat ) {
// if this was the last round in the clip, play the 'lastshot' animation
// this animation has the weapon in a "ready to reload" state
if ( pm->ps->weapon == WP_AKIMBO ) {
if ( akimboFire ) {
weapattackanim = WEAP_ATTACK1; // attack1 is right hand
} else {
weapattackanim = WEAP_ATTACK2; // attack2 is left hand
}
if ( PM_WeaponClipEmpty( pm->ps->weapon ) ) {
weapattackanim = WEAP_ATTACK_LASTSHOT;
} else {
if ( PM_WeaponClipEmpty( pm->ps->weapon ) ) {
weapattackanim = WEAP_ATTACK_LASTSHOT;
} else {
weapattackanim = WEAP_ATTACK1;
}
weapattackanim = WEAP_ATTACK1;
}
switch ( pm->ps->weapon ) {
@ -3441,7 +3455,9 @@ case WP_DYNAMITE:
case WP_VENOM:
case WP_MP40:
case WP_AKIMBO_MP40:
case WP_THOMPSON:
case WP_AKIMBO_THOMPSON:
case WP_STEN:
PM_ContinueWeaponAnim( weapattackanim );
break;
@ -3455,9 +3471,9 @@ default:
if ( pm->ps->weapon == WP_AKIMBO ) {
if ( pm->ps->weapon == WP_AKIMBO && !akimboFire ) {
PM_AddEvent( EV_FIRE_WEAPONB ); // really firing colt
if ( pm->ps->weapon == WP_AKIMBO || pm->ps->weapon == WP_AKIMBO_MP40 || pm->ps->weapon == WP_AKIMBO_THOMPSON ) {
if ( !akimboFire ) {
PM_AddEvent( EV_FIRE_WEAPONB ); // really firing main
} else {
PM_AddEvent( EV_FIRE_WEAPON );
}
@ -3503,23 +3519,36 @@ case WP_COLT:
//----(SA) added
case WP_AKIMBO:
// if you're firing an akimbo colt, and you are firing only single gun,
case WP_AKIMBO_MP40:
case WP_AKIMBO_THOMPSON:
// if you're firing an akimbo, and you are firing only single gun,
// or other gun is dry, nextshot needs to take 2x time
addTime = ammoTable[pm->ps->weapon].nextShotTime;
if (triggerState < 3) {
// firing only single gun
addTime = 2 * ammoTable[pm->ps->weapon].nextShotTime;
addTime = ammoTable[weapAlts[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;
if ( !pm->ps->ammoclip[pm->ps->weapon] || !pm->ps->ammoclip[weapAlts[pm->ps->weapon]] ) {
if ( ( !pm->ps->ammoclip[pm->ps->weapon] && !akimboFire ) || ( !pm->ps->ammoclip[weapAlts[pm->ps->weapon]] && akimboFire ) ) {
addTime = ammoTable[weapAlts[pm->ps->weapon]].nextShotTime;
}
}
}
}
switch ( pm->ps->weapon ) {
case WP_AKIMBO:
aimSpreadScaleAdd = 20;
break;
case WP_AKIMBO_MP40:
aimSpreadScaleAdd = 15 + rand() % 10;
break;
case WP_AKIMBO_THOMPSON:
aimSpreadScaleAdd = 15 + rand() % 10;
break;
}
aimSpreadScaleAdd = 20;
break;
//----(SA) end

View file

@ -578,22 +578,24 @@ typedef enum {
// WP_CROSS, // 29
WP_DYNAMITE, // 22
// WP_DYNAMITE2, // 31
WP_AKIMBO_MP40, // 23 // dual MP40
WP_AKIMBO_THOMPSON, // 24 // dual thompson
// WP_PROX, // 32
WP_MONSTER_ATTACK1, // 23 // generic monster attack, slot 1
WP_MONSTER_ATTACK2, // 24 // generic monster attack, slot 2
WP_MONSTER_ATTACK3, // 25 // generic monster attack, slot 2
WP_MONSTER_ATTACK1, // 25 // generic monster attack, slot 1
WP_MONSTER_ATTACK2, // 26 // generic monster attack, slot 2
WP_MONSTER_ATTACK3, // 27 // generic monster attack, slot 2
WP_GAUNTLET, // 26
WP_GAUNTLET, // 28
WP_SNIPER, // 27
WP_GRENADE_SMOKE, // 28 // smoke grenade for LT multiplayer
WP_MEDIC_HEAL, // 29 // DHM - Nerve :: Medic special weapon
WP_MORTAR, // 30
WP_SNIPER, // 29
WP_GRENADE_SMOKE, // 30 // smoke grenade for LT multiplayer
WP_MEDIC_HEAL, // 31 // DHM - Nerve :: Medic special weapon
WP_MORTAR, // 32
VERYBIGEXPLOSION, // 31 // explosion effect for airplanes
VERYBIGEXPLOSION, // 33 // explosion effect for airplanes
WP_NUM_WEAPONS // 32 NOTE: this cannot be larger than 64 for AI/player weapons!
WP_NUM_WEAPONS // 34 NOTE: this cannot be larger than 64 for AI/player weapons!
} weapon_t;
@ -1190,7 +1192,9 @@ typedef enum {
MOD_LUGER,
MOD_COLT,
MOD_MP40,
MOD_AKIMBO_MP40,
MOD_THOMPSON,
MOD_AKIMBO_THOMPSON,
MOD_STEN,
MOD_MAUSER,
MOD_SNIPERRIFLE,
@ -1312,7 +1316,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, int triggerState );
qboolean BG_AkimboFireSequence( int weapon, int akimboClip, int mainClip, int triggerState );
//qboolean BG_AkimboFireSequence ( playerState_t *ps ); //----(SA) added
#define ITEM_INDEX( x ) ( ( x ) - bg_itemlist )

View file

@ -152,9 +152,11 @@ void P_DamageFeedback( gentity_t *player ) {
trap_Vibrate(1000, 1, (count / 255.0) + 0.5f, "damage_low_bullet", yaw, pitch);
break;
case MOD_THOMPSON:
case MOD_AKIMBO_THOMPSON:
case MOD_STEN:
case MOD_MAUSER:
case MOD_MP40:
case MOD_AKIMBO_MP40:
case MOD_GARAND:
case MOD_SPEARGUN:
case MOD_CROSS:

View file

@ -289,8 +289,8 @@ void Cmd_Give_f( gentity_t *ent ) {
if ( give_all || Q_stricmp( name, "weapons" ) == 0 ) {
//ent->client->ps.weapons[0] = (1 << (WP_MONSTER_ATTACK1)) - 1 - (1<<WP_NONE); //----(SA) gives the cross now as well
//(SA) we really don't want to give anything beyond WP_DYNAMITE
for ( i = 0; i <= WP_DYNAMITE; i++ )
//(SA) we really don't want to give anything beyond WP_AKIMBO_THOMPSON
for ( i = 0; i <= WP_AKIMBO_THOMPSON; i++ )
COM_BitSet( ent->client->ps.weapons, i );
// for (i=0; i<WP_NUM_WEAPONS; i++) {

View file

@ -127,6 +127,12 @@ void TossClientItems( gentity_t *self ) {
if ( weapon == WP_AKIMBO ) { //----(SA) added
weapon = WP_COLT;
}
if ( weapon == WP_AKIMBO_MP40 ) { //----(SA) added
weapon = WP_MP40;
}
if ( weapon == WP_AKIMBO_THOMPSON ) { //----(SA) added
weapon = WP_THOMPSON;
}
//----(SA) end
@ -273,7 +279,9 @@ char *modNames[] = {
"MOD_LUGER",
"MOD_COLT",
"MOD_MP40",
"MOD_AKIMBO_MP40",
"MOD_THOMPSON",
"MOD_AKIMBO_THOMPSON",
"MOD_STEN",
"MOD_MAUSER",
"MOD_SNIPERRIFLE",
@ -674,7 +682,9 @@ qboolean IsHeadShotWeapon( int mod, gentity_t *targ, gentity_t *attacker ) {
case MOD_COLT:
case MOD_AKIMBO:
case MOD_MP40:
case MOD_AKIMBO_MP40:
case MOD_THOMPSON:
case MOD_AKIMBO_THOMPSON:
case MOD_STEN:
case MOD_BAR:
case MOD_FG42:

View file

@ -442,10 +442,10 @@ int Pickup_Weapon( gentity_t *ent, gentity_t *other ) {
//----(SA) added
// check for special colt->akimbo add (if you've got a colt already, add the second now)
if ( weapon == WP_COLT ) {
if ( COM_BitCheck( other->client->ps.weapons, WP_COLT ) ) {
weapon = WP_AKIMBO;
// check for special gun->akimbo add (if you've got a gun already, add the second now)
if ( weapon == WP_COLT || weapon == WP_MP40 || weapon == WP_THOMPSON ) {
if ( COM_BitCheck( other->client->ps.weapons, weapon ) ) {
weapon = weapAlts[weapon];
}
}
//----(SA) end

View file

@ -627,7 +627,9 @@ int G_GetWeaponDamage( int weapon ) {
case WP_COLT:
case WP_AKIMBO: return 10; //---- Make pistols a little more powerful for VR
case WP_VENOM: return 12; // 15 ----(SA) slight modify for DM
case WP_AKIMBO_MP40:
case WP_MP40: return 6;
case WP_AKIMBO_THOMPSON:
case WP_THOMPSON: return 8;
case WP_STEN: return 10;
case WP_FG42SCOPE:
@ -657,7 +659,9 @@ int G_GetWeaponDamage( int weapon ) {
case WP_AKIMBO: return 18; //----(SA) added
case WP_VENOM: return 20;
case WP_MP40: return 14;
case WP_AKIMBO_MP40: return 14;
case WP_THOMPSON: return 18;
case WP_AKIMBO_THOMPSON: return 18;
case WP_STEN: return 14;
case WP_FG42SCOPE:
case WP_FG42: return 15;
@ -701,9 +705,11 @@ float G_GetWeaponSpread( int weapon ) {
case WP_AKIMBO: return 10;
case WP_VENOM: return 1000;
case WP_MP40: return 800;
case WP_AKIMBO_MP40: return 800;
case WP_FG42SCOPE: return 100;
case WP_FG42: return 200;
case WP_THOMPSON: return 1000;
case WP_AKIMBO_THOMPSON: return 1000;
case WP_STEN: return 800;//1200; Improve accuracy of Sten for more fun on stealth missions
case WP_MAUSER: return 200;
case WP_GARAND: return 500;
@ -718,9 +724,11 @@ float G_GetWeaponSpread( int weapon ) {
case WP_AKIMBO: return 30; //----(SA) added
case WP_VENOM: return 200;
case WP_MP40: return 200;
case WP_AKIMBO_MP40: return 200;
case WP_FG42SCOPE: return 10;
case WP_FG42: return 150;
case WP_THOMPSON: return 250;
case WP_AKIMBO_THOMPSON: return 250;
case WP_STEN: return 300;
case WP_MAUSER: return 15;
case WP_GARAND: return 25;
@ -736,9 +744,11 @@ float G_GetWeaponSpread( int weapon ) {
case WP_AKIMBO: return 800; //----(SA)added
case WP_VENOM: return 600;
case WP_MP40: return 400;
case WP_AKIMBO_MP40: return 400;
case WP_FG42SCOPE:
case WP_FG42: return 500;
case WP_THOMPSON: return 600;
case WP_AKIMBO_THOMPSON: return 600;
case WP_STEN: return 200;
case WP_MAUSER: return 700;
case WP_GARAND: return 600;
@ -966,11 +976,11 @@ void Bullet_Fire( gentity_t *ent, float spread, int damage ) {
// Allocates storage
char *fire_command = (char*)malloc(8 * sizeof(char));
sprintf(fire_command, "fire_%i", ent->s.weapon);
if (ent->s.weapon == WP_AKIMBO)
if (ent->s.weapon == WP_AKIMBO || ent->s.weapon == WP_AKIMBO_MP40 || ent->s.weapon == WP_AKIMBO_THOMPSON)
{
qboolean akimbo = BG_AkimboFireSequence(ent->s.weapon, ent->client->ps.ammoclip[WP_AKIMBO], ent->client->ps.ammoclip[WP_COLT], gVR->akimboTriggerState );
qboolean akimbo = BG_AkimboFireSequence(ent->s.weapon, ent->client->ps.ammoclip[ent->s.weapon], ent->client->ps.ammoclip[weapAlts[ent->s.weapon]], gVR->akimboTriggerState );
trap_Vibrate(100, right != akimbo ? 1 : 0, 1.0, fire_command, 0.0, 0.0);
} else{
} else {
trap_Vibrate(100, right ? 1 : 0, 1.0, fire_command, 0.0, 0.0);
if (gVR->weapon_stabilised) {
trap_Vibrate(100, right ? 0 : 1, 0.7, fire_command, 0.0, 0.0);
@ -1746,8 +1756,12 @@ 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);
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);
if (weapon == WP_AKIMBO || weapon == WP_AKIMBO_MP40 || weapon == WP_AKIMBO_THOMPSON) {
if (BG_AkimboFireSequence(weapon, ent->client->ps.ammoclip[weapon], ent->client->ps.ammoclip[weapAlts[weapon]], gVR->akimboTriggerState)) {
convertFromVR(worldscale, ent, gVR->offhandoffset, ent->r.currentOrigin, muzzlePoint);
} else {
convertFromVR(worldscale, ent, gVR->calculated_weaponoffset, ent->r.currentOrigin, muzzlePoint);
}
} else {
convertFromVR(worldscale, ent, gVR->calculated_weaponoffset, ent->r.currentOrigin, muzzlePoint);
}
@ -1812,8 +1826,13 @@ 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);
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);
int weapon = ent->client->ps.weapon;
if (weapon == WP_AKIMBO || weapon == WP_AKIMBO_MP40 || weapon == WP_AKIMBO_THOMPSON) {
if (BG_AkimboFireSequence(weapon, ent->client->ps.ammoclip[weapon], ent->client->ps.ammoclip[weapAlts[weapon]], gVR->akimboTriggerState)) {
convertFromVR(worldscale, ent, gVR->offhandoffset, ent->r.currentOrigin, muzzlePoint);
} else {
convertFromVR(worldscale, ent, gVR->calculated_weaponoffset, ent->r.currentOrigin, muzzlePoint);
}
} else {
convertFromVR(worldscale, ent, gVR->calculated_weaponoffset, ent->r.currentOrigin, muzzlePoint);
}
@ -1876,9 +1895,14 @@ 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 );
*/
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]);
if (weapon == WP_AKIMBO || weapon == WP_AKIMBO_MP40 || weapon == WP_AKIMBO_THOMPSON) {
if (BG_AkimboFireSequence(weapon, ent->client->ps.ammoclip[weapon], ent->client->ps.ammoclip[weapAlts[weapon]], 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(gVR->weaponangles, viewang);
viewang[YAW] = ent->client->ps.viewangles[YAW] + (gVR->weaponangles[YAW] - gVR->hmdorientation[YAW]);
@ -1947,6 +1971,8 @@ void FireWeapon( gentity_t *ent ) {
case WP_SILENCER:
case WP_COLT:
case WP_AKIMBO:
case WP_AKIMBO_MP40:
case WP_AKIMBO_THOMPSON:
// No need for penalty, dual wield penalizes enough :-)
// aimSpreadScale += 0.4f;
break;
@ -2068,9 +2094,11 @@ void FireWeapon( gentity_t *ent ) {
case WP_STEN:
Bullet_Fire( ent, STEN_SPREAD * aimSpreadScale, STEN_DAMAGE );
break;
case WP_AKIMBO_MP40:
case WP_MP40:
Bullet_Fire( ent, MP40_SPREAD * aimSpreadScale, MP40_DAMAGE );
break;
case WP_AKIMBO_THOMPSON:
case WP_THOMPSON:
Bullet_Fire( ent, THOMPSON_SPREAD * aimSpreadScale, THOMPSON_DAMAGE );
break;

View file

@ -1083,7 +1083,7 @@ typedef enum
#define MAX_WEAPS_IN_BANK_MP 8
#define MAX_WEAP_BANKS_MP 7
// jpw
#define MAX_WEAP_ALTS WP_DYNAMITE
#define MAX_WEAP_ALTS WP_AKIMBO_THOMPSON
// bit field limits

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View file

@ -0,0 +1,71 @@
"---"
"---"
"Treasure Item"
"Small Health"
"Med Health"
"Large Health"
"Hot Meal"
"Cold Meal"
"---"
"Health" // hanging kit
"Stamina" // stein
"Stamina" // brandy
"Flak Jacket"
"Flak Jacket" // hanging on hook
"Armored Helmet"
"---"
"Knife"
"Luger"
"Mauser Rifle"
"Dual Thompsons"
"Thompson"
"Sten"
"Dual Colts"
"Colt"
"---"
"Dual MP40s"
"MP40"
"FG42 Paratroop Rifle"
"Silencer"
"Panzerfaust"
"Grenade"
"Pineapple"
"---"
"Venom"
"Flamethrower"
"Tesla Gun"
"Sniper Scope"
"Snooper Rifle"
"---"
"---"
"---"
"---"
"---"
"9mm Rounds"
"9mm"
"9mm Box"
".45cal Rounds"
".45cal"
".45cal Box"
"7.92mm Rounds"
"7.92mm"
"7.92mm Box"
".30cal Rounds"
".30cal"
".30cal Box"
"12.7mm"
"Grenades"
"Pineapples"
"Dynamite"
"Cell"
"Fuel"
"Rockets"
"---"
"1938 Latour"
"Endurance"
"Venom Tech Manual"
"Project Book"
"Dr. Zemph's Journal"
"Red Flag"
"Blue Flag"
"Binoculars"