2019-09-19 22:42:45 +00:00
//-------------------------------------------------------------------------
/*
Copyright ( C ) 2010 - 2019 EDuke32 developers and contributors
Copyright ( C ) 2019 Nuke . YKT
This file is part of NBlood .
NBlood is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
//-------------------------------------------------------------------------
2019-09-21 18:59:54 +00:00
# include "ns.h" // Must come before everything else!
2019-09-19 22:42:45 +00:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "build.h"
2020-12-09 14:56:32 +00:00
2019-09-19 22:42:45 +00:00
# include "blood.h"
2020-12-03 17:00:07 +00:00
# include "bloodactor.h"
2019-09-19 22:42:45 +00:00
2019-09-22 06:39:22 +00:00
BEGIN_BLD_NS
2021-12-29 21:56:21 +00:00
void FirePitchfork ( int , PLAYER * pPlayer ) ;
void FireSpray ( int , PLAYER * pPlayer ) ;
void ThrowCan ( int , PLAYER * pPlayer ) ;
void DropCan ( int , PLAYER * pPlayer ) ;
void ExplodeCan ( int , PLAYER * pPlayer ) ;
void ThrowBundle ( int , PLAYER * pPlayer ) ;
void DropBundle ( int , PLAYER * pPlayer ) ;
void ExplodeBundle ( int , PLAYER * pPlayer ) ;
void ThrowProx ( int , PLAYER * pPlayer ) ;
void DropProx ( int , PLAYER * pPlayer ) ;
void ThrowRemote ( int , PLAYER * pPlayer ) ;
void DropRemote ( int , PLAYER * pPlayer ) ;
void FireRemote ( int , PLAYER * pPlayer ) ;
void FireShotgun ( int nTrigger , PLAYER * pPlayer ) ;
void EjectShell ( int , PLAYER * pPlayer ) ;
void FireTommy ( int nTrigger , PLAYER * pPlayer ) ;
void FireSpread ( int nTrigger , PLAYER * pPlayer ) ;
void AltFireSpread ( int nTrigger , PLAYER * pPlayer ) ;
void AltFireSpread2 ( int nTrigger , PLAYER * pPlayer ) ;
void FireFlare ( int nTrigger , PLAYER * pPlayer ) ;
void AltFireFlare ( int nTrigger , PLAYER * pPlayer ) ;
void FireVoodoo ( int nTrigger , PLAYER * pPlayer ) ;
void AltFireVoodoo ( int nTrigger , PLAYER * pPlayer ) ;
void DropVoodoo ( int nTrigger , PLAYER * pPlayer ) ;
void FireTesla ( int nTrigger , PLAYER * pPlayer ) ;
void AltFireTesla ( int nTrigger , PLAYER * pPlayer ) ;
void FireNapalm ( int nTrigger , PLAYER * pPlayer ) ;
void FireNapalm2 ( int nTrigger , PLAYER * pPlayer ) ;
void AltFireNapalm ( int nTrigger , PLAYER * pPlayer ) ;
void FireLifeLeech ( int nTrigger , PLAYER * pPlayer ) ;
void AltFireLifeLeech ( int nTrigger , PLAYER * pPlayer ) ;
void FireBeast ( int nTrigger , PLAYER * pPlayer ) ;
typedef void ( * QAVTypeCast ) ( int , void * ) ;
2019-09-19 22:42:45 +00:00
2020-11-17 08:03:10 +00:00
void ( * qavClientCallback [ ] ) ( int , void * ) =
2019-09-19 22:42:45 +00:00
{
2020-11-17 08:03:10 +00:00
( QAVTypeCast ) FirePitchfork ,
( QAVTypeCast ) FireSpray ,
( QAVTypeCast ) ThrowCan ,
( QAVTypeCast ) DropCan ,
( QAVTypeCast ) ExplodeCan ,
( QAVTypeCast ) ThrowBundle ,
( QAVTypeCast ) DropBundle ,
( QAVTypeCast ) ExplodeBundle ,
( QAVTypeCast ) ThrowProx ,
( QAVTypeCast ) DropProx ,
( QAVTypeCast ) ThrowRemote ,
( QAVTypeCast ) DropRemote ,
( QAVTypeCast ) FireRemote ,
( QAVTypeCast ) FireShotgun ,
( QAVTypeCast ) EjectShell ,
( QAVTypeCast ) FireTommy ,
( QAVTypeCast ) AltFireSpread2 ,
( QAVTypeCast ) FireSpread ,
( QAVTypeCast ) AltFireSpread ,
( QAVTypeCast ) FireFlare ,
( QAVTypeCast ) AltFireFlare ,
( QAVTypeCast ) FireVoodoo ,
( QAVTypeCast ) AltFireVoodoo ,
( QAVTypeCast ) FireTesla ,
( QAVTypeCast ) AltFireTesla ,
( QAVTypeCast ) FireNapalm ,
( QAVTypeCast ) FireNapalm2 ,
( QAVTypeCast ) FireLifeLeech ,
( QAVTypeCast ) FireBeast ,
( QAVTypeCast ) AltFireLifeLeech ,
( QAVTypeCast ) DropVoodoo ,
( QAVTypeCast ) AltFireNapalm ,
} ;
enum
2019-09-19 22:42:45 +00:00
{
2021-12-29 21:56:21 +00:00
nClientFirePitchfork ,
nClientFireSpray ,
nClientThrowCan ,
nClientDropCan ,
nClientExplodeCan ,
nClientThrowBundle ,
nClientDropBundle ,
nClientExplodeBundle ,
nClientThrowProx ,
nClientDropProx ,
nClientThrowRemote ,
nClientDropRemote ,
nClientFireRemote ,
nClientFireShotgun ,
nClientEjectShell ,
nClientFireTommy ,
nClientAltFireSpread2 ,
nClientFireSpread ,
nClientAltFireSpread ,
nClientFireFlare ,
nClientAltFireFlare ,
nClientFireVoodoo ,
nClientAltFireVoodoo ,
nClientFireTesla ,
nClientAltFireTesla ,
nClientFireNapalm ,
nClientFireNapalm2 ,
nClientFireLifeLeech ,
nClientFireBeast ,
nClientAltFireLifeLeech ,
nClientDropVoodoo ,
nClientAltFireNapalm ,
2020-11-17 08:03:10 +00:00
} ;
2022-09-29 11:17:27 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
double getThrowPower ( PLAYER * pPlayer )
{
return pPlayer - > throwPower * 23.46666 + 6.4 ;
}
void setThrowPower ( PLAYER * pPlayer )
{
pPlayer - > throwPower = min ( ( PlayClock - pPlayer - > throwTime ) / 240. , 1. ) ;
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2022-05-05 23:16:10 +00:00
bool checkLitSprayOrTNT ( PLAYER * pPlayer )
2021-12-29 21:56:21 +00:00
{
switch ( pPlayer - > curWeapon )
{
case kWeapSpraycan :
switch ( pPlayer - > weaponState )
{
case 5 :
case 6 :
return 1 ;
case 7 :
if ( VanillaMode ( ) )
return 0 ;
return 1 ;
}
break ;
case kWeapDynamite :
switch ( pPlayer - > weaponState )
{
case 4 :
case 5 :
case 6 :
return 1 ;
}
break ;
}
return 0 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-04-17 08:34:12 +00:00
static bool BannedUnderwater ( int nWeapon )
2019-09-19 22:42:45 +00:00
{
2021-12-29 21:56:21 +00:00
return nWeapon = = kWeapSpraycan | | nWeapon = = kWeapDynamite ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool CheckWeaponAmmo ( PLAYER * pPlayer , int weapon , int ammotype , int count )
{
if ( gInfiniteAmmo )
return 1 ;
if ( ammotype = = - 1 )
return 1 ;
if ( weapon = = kWeapRemote & & pPlayer - > weaponAmmo = = 11 & & pPlayer - > weaponState = = 11 )
return 1 ;
if ( weapon = = kWeapLifeLeech & & pPlayer - > actor - > xspr . health > 0 )
return 1 ;
return pPlayer - > ammoCount [ ammotype ] > = count ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool CheckAmmo ( PLAYER * pPlayer , int ammotype , int count )
{
if ( gInfiniteAmmo )
return 1 ;
if ( ammotype = = - 1 )
return 1 ;
if ( pPlayer - > curWeapon = = kWeapRemote & & pPlayer - > weaponAmmo = = 11 & & pPlayer - > weaponState = = 11 )
return 1 ;
if ( pPlayer - > curWeapon = = kWeapLifeLeech & & pPlayer - > actor - > xspr . health > = unsigned ( count < < 4 ) )
return 1 ;
return pPlayer - > ammoCount [ ammotype ] > = count ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool checkAmmo2 ( const PLAYER * pPlayer , int ammotype , int amount )
2019-09-19 22:42:45 +00:00
{
2021-12-29 21:56:21 +00:00
if ( gInfiniteAmmo )
return 1 ;
if ( ammotype = = - 1 )
return 1 ;
return pPlayer - > ammoCount [ ammotype ] > = amount ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2022-09-29 12:19:57 +00:00
void SpawnBulletEject ( PLAYER * pPlayer , double dist , int rdist )
2019-09-19 22:42:45 +00:00
{
2021-12-29 21:56:21 +00:00
POSTURE * pPosture = & pPlayer - > pPosture [ pPlayer - > lifeMode ] [ pPlayer - > posture ] ;
2022-09-11 13:33:14 +00:00
pPlayer - > zView = pPlayer - > actor - > spr . pos . Z - pPosture - > eyeAboveZ ;
2022-09-11 13:19:19 +00:00
double dz = pPlayer - > zWeapon - ( pPlayer - > zWeapon - pPlayer - > zView ) * 0.5 ;
2022-09-29 12:19:57 +00:00
fxSpawnEjectingBrass ( pPlayer - > actor , dz , dist , rdist ) ;
2019-09-19 22:42:45 +00:00
}
2022-09-29 12:19:57 +00:00
void SpawnShellEject ( PLAYER * pPlayer , double dist , int rdist )
2019-09-19 22:42:45 +00:00
{
2021-12-29 21:56:21 +00:00
POSTURE * pPosture = & pPlayer - > pPosture [ pPlayer - > lifeMode ] [ pPlayer - > posture ] ;
2022-09-11 13:33:14 +00:00
pPlayer - > zView = pPlayer - > actor - > spr . pos . Z - pPosture - > eyeAboveZ ;
2022-09-11 13:19:19 +00:00
double t = pPlayer - > zWeapon - pPlayer - > zView ;
double dz = pPlayer - > zWeapon - t + ( t * 0.25 ) ;
2022-09-29 12:19:57 +00:00
fxSpawnEjectingShell ( pPlayer - > actor , dz , dist , rdist ) ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-09-19 22:42:45 +00:00
void WeaponInit ( void )
{
2021-12-29 21:56:21 +00:00
auto doInit = [ ] ( const int base )
{
for ( int i = base ; i < ( kQAVEnd + base ) ; i + + )
{
auto pQAV = getQAV ( i ) ;
if ( ! pQAV )
I_Error ( " Could not load QAV %d \n " , i ) ;
}
} ;
doInit ( 0 ) ;
doInit ( 10000 ) ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-04-11 10:42:59 +00:00
void WeaponPrecache ( )
2020-01-02 11:01:18 +00:00
{
2021-12-29 21:56:21 +00:00
auto doPrecache = [ ] ( const int base )
{
for ( int i = base ; i < ( kQAVEnd + base ) ; i + + )
{
auto pQAV = getQAV ( i ) ;
if ( pQAV )
pQAV - > Precache ( ) ;
}
} ;
doPrecache ( 0 ) ;
doPrecache ( 10000 ) ;
2020-01-02 11:01:18 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2022-10-25 11:16:15 +00:00
void WeaponDraw ( PLAYER * pPlayer , int shade , double xpos , double ypos , int palnum , DAngle angle )
2021-12-29 21:56:21 +00:00
{
assert ( pPlayer ! = NULL ) ;
if ( pPlayer - > weaponQav = = kQAVNone )
return ;
auto pQAV = getQAV ( pPlayer - > weaponQav ) ;
int duration ;
2022-09-07 05:34:55 +00:00
double interpfrac ;
2021-12-29 21:56:21 +00:00
2022-09-07 05:34:55 +00:00
qavProcessTimer ( pPlayer , pQAV , & duration , & interpfrac , pPlayer - > weaponState = = - 1 , pPlayer - > curWeapon = = kWeapShotgun & & pPlayer - > weaponState = = 7 ) ;
2021-12-29 21:56:21 +00:00
2022-09-12 11:25:31 +00:00
pQAV - > x = xpos ;
pQAV - > y = ypos ;
2021-12-29 21:56:21 +00:00
int flags = 2 ;
int nInv = powerupCheck ( pPlayer , kPwUpShadowCloak ) ;
if ( nInv > = 120 * 8 | | ( nInv ! = 0 & & ( PlayClock & 32 ) ) )
{
shade = - 128 ;
flags | = 1 ;
}
2022-10-25 11:16:15 +00:00
pQAV - > Draw ( duration , flags , shade , palnum , true , interpfrac , angle ) ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void WeaponPlay ( PLAYER * pPlayer )
2019-09-19 22:42:45 +00:00
{
2021-12-29 21:56:21 +00:00
assert ( pPlayer ! = NULL ) ;
if ( pPlayer - > weaponQav = = kQAVNone )
return ;
auto pQAV = getQAV ( pPlayer - > weaponQav ) ;
int nTicks = pQAV - > duration - pPlayer - > weaponTimer ;
pQAV - > Play ( nTicks - 4 , nTicks , pPlayer - > qavCallback , pPlayer ) ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void StartQAV ( PLAYER * pPlayer , int nWeaponQAV , int callback = - 1 , bool looped = false )
{
assert ( nWeaponQAV < kQAVEnd ) ;
auto res_id = qavGetCorrectID ( nWeaponQAV ) ;
auto pQAV = getQAV ( res_id ) ;
pPlayer - > weaponQav = res_id ;
pPlayer - > weaponTimer = pQAV - > duration ;
pPlayer - > qavCallback = callback ;
pPlayer - > qavLoop = looped ;
pPlayer - > qavLastTick = I_GetTime ( pQAV - > ticrate ) ;
pPlayer - > qavTimer = pQAV - > duration ;
//pQAV->Preload();
WeaponPlay ( pPlayer ) ;
pPlayer - > weaponTimer - = 4 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
static void SetQAV ( PLAYER * pPlayer , int nWeaponQAV )
2021-08-28 06:36:27 +00:00
{
2021-12-29 21:56:21 +00:00
assert ( nWeaponQAV < kQAVEnd ) ;
pPlayer - > weaponQav = qavGetCorrectID ( nWeaponQAV ) ;
pPlayer - > qavTimer = 0 ;
pPlayer - > qavLastTick = 0 ;
2021-08-28 06:36:27 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-09-19 22:42:45 +00:00
struct WEAPONTRACK
{
2021-12-29 21:56:21 +00:00
int aimSpeedHorz ;
int aimSpeedVert ;
int angleRange ;
int thingAngle ;
int seeker ;
bool bIsProjectile ;
2019-09-19 22:42:45 +00:00
} ;
WEAPONTRACK gWeaponTrack [ ] = {
2021-12-29 21:56:21 +00:00
{ 0 , 0 , 0 , 0 , 0 , false } ,
{ 0x6000 , 0x6000 , 0x71 , 0x55 , 0x111111 , false } ,
{ 0x8000 , 0x8000 , 0x71 , 0x55 , 0x2aaaaa , true } ,
{ 0x10000 , 0x10000 , 0x38 , 0x1c , 0 , false } ,
{ 0x6000 , 0x8000 , 0x38 , 0x1c , 0 , false } ,
{ 0x6000 , 0x6000 , 0x38 , 0x1c , 0x2aaaaa , true } ,
{ 0x6000 , 0x6000 , 0x71 , 0x55 , 0 , true } ,
{ 0x6000 , 0x6000 , 0x71 , 0x38 , 0 , true } ,
{ 0x8000 , 0x10000 , 0x71 , 0x55 , 0x255555 , true } ,
{ 0x10000 , 0x10000 , 0x71 , 0 , 0 , true } ,
{ 0x10000 , 0x10000 , 0xaa , 0 , 0 , false } ,
{ 0x6000 , 0x6000 , 0x71 , 0x55 , 0 , true } ,
{ 0x6000 , 0x6000 , 0x71 , 0x55 , 0 , true } ,
{ 0x6000 , 0x6000 , 0x71 , 0x55 , 0 , false } ,
2019-09-19 22:42:45 +00:00
} ;
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void UpdateAimVector ( PLAYER * pPlayer )
{
assert ( pPlayer ! = NULL ) ;
auto plActor = pPlayer - > actor ;
2022-09-28 15:25:08 +00:00
DVector3 pos ( plActor - > spr . pos . XY ( ) , pPlayer - > zWeapon ) ;
2022-11-25 12:13:50 +00:00
DVector3 Aim ( plActor - > spr . Angles . Yaw . ToVector ( ) , pPlayer - > slope ) ;
2022-09-28 15:25:08 +00:00
2021-12-29 21:56:21 +00:00
WEAPONTRACK * pWeaponTrack = & gWeaponTrack [ pPlayer - > curWeapon ] ;
DBloodActor * targetactor = nullptr ;
pPlayer - > aimTargetsCount = 0 ;
int autoaim = Autoaim ( pPlayer - > nPlayer ) ;
if ( autoaim = = 1 | | ( autoaim = = 2 & & ! pWeaponTrack - > bIsProjectile ) | | pPlayer - > curWeapon = = kWeapVoodooDoll | | pPlayer - > curWeapon = = kWeapLifeLeech )
{
2022-09-28 15:25:08 +00:00
double nClosest = 0x7fffffff ;
2021-12-29 21:56:21 +00:00
BloodStatIterator it ( kStatDude ) ;
while ( auto actor = it . Next ( ) )
{
if ( plActor = = actor )
continue ;
if ( ! gGameOptions . bFriendlyFire & & IsTargetTeammate ( pPlayer , actor ) )
continue ;
if ( actor - > spr . flags & 32 )
continue ;
if ( ! ( actor - > spr . flags & 8 ) )
continue ;
2022-09-28 15:25:08 +00:00
auto pos2 = actor - > spr . pos ;
double nDist = ( pos2 . XY ( ) - pos . XY ( ) ) . Length ( ) ;
if ( nDist = = 0 | | nDist > 3200 )
2021-12-29 21:56:21 +00:00
continue ;
2022-09-28 15:25:08 +00:00
2021-12-29 21:56:21 +00:00
if ( pWeaponTrack - > seeker )
{
2022-09-28 15:25:08 +00:00
double t = nDist * 4096 / pWeaponTrack - > seeker ;
pos2 + = actor - > vel * t ;
2021-12-29 21:56:21 +00:00
}
2022-11-25 12:13:50 +00:00
DVector3 lpos = pos + DVector3 ( plActor - > spr . Angles . Yaw . ToVector ( ) , pPlayer - > slope ) * nDist ;
2022-09-28 15:25:08 +00:00
double zRange = nDist * ( 9460 / 16384. ) ;
double top , bottom ;
2021-12-29 21:56:21 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
2022-09-28 15:25:08 +00:00
if ( lpos . Z - zRange > bottom | | lpos . Z + zRange < top )
2021-12-29 21:56:21 +00:00
continue ;
2022-09-28 15:25:08 +00:00
2022-09-30 11:51:37 +00:00
DAngle angle = ( pos2 - pos ) . Angle ( ) ;
2022-11-25 12:13:50 +00:00
DAngle deltaangle = absangle ( angle , plActor - > spr . Angles . Yaw ) ;
2022-09-28 15:25:08 +00:00
if ( deltaangle > DAngle : : fromBuild ( pWeaponTrack - > angleRange ) )
2021-12-29 21:56:21 +00:00
continue ;
2022-09-28 15:25:08 +00:00
if ( pPlayer - > aimTargetsCount < 16 & & cansee ( pos , plActor - > sector ( ) , pos2 , actor - > sector ( ) ) )
2021-12-29 21:56:21 +00:00
pPlayer - > aimTargets [ pPlayer - > aimTargetsCount + + ] = actor ;
2022-09-28 15:25:08 +00:00
double nDist2 = ( lpos - pos2 ) . Length ( ) ;
2021-12-29 21:56:21 +00:00
if ( nDist2 > = nClosest )
continue ;
2022-09-28 15:25:08 +00:00
2023-09-30 08:16:06 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( actor ) ;
2022-09-28 15:25:08 +00:00
if ( cansee ( pos , plActor - > sector ( ) , pos2 , actor - > sector ( ) ) )
2021-12-29 21:56:21 +00:00
{
2022-10-07 21:33:37 +00:00
double center = ( actor - > spr . scale . Y * pDudeInfo - > aimHeight ) ;
2022-09-28 15:25:08 +00:00
double dzCenter = ( pos2 . Z - center ) - pos . Z ;
2021-12-29 21:56:21 +00:00
nClosest = nDist2 ;
2022-09-28 15:25:08 +00:00
Aim . XY ( ) = angle . ToVector ( ) ;
Aim . Z = dzCenter / nDist ;
2021-12-29 21:56:21 +00:00
targetactor = actor ;
}
}
if ( pWeaponTrack - > thingAngle > 0 )
{
BloodStatIterator itr ( kStatThing ) ;
while ( auto actor = itr . Next ( ) )
{
if ( ! gGameOptions . bFriendlyFire & & IsTargetTeammate ( pPlayer , actor ) )
continue ;
if ( ! ( actor - > spr . flags & 8 ) )
continue ;
2022-09-28 15:25:08 +00:00
auto pos2 = actor - > spr . pos ;
auto dv = pos2 - pos ;
double nDist = dv . Length ( ) ;
if ( nDist = = 0 | | nDist > 3200 )
2021-12-29 21:56:21 +00:00
continue ;
2022-09-28 15:25:08 +00:00
2022-11-25 12:13:50 +00:00
DVector3 lpos = pos + DVector3 ( plActor - > spr . Angles . Yaw . ToVector ( ) , pPlayer - > slope ) * nDist ;
2022-09-28 15:25:08 +00:00
double zRange = nDist * ( 9460 / 16384. ) ;
double top , bottom ;
2021-12-29 21:56:21 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
2022-09-28 15:25:08 +00:00
if ( lpos . Z - zRange > bottom | | lpos . Z + zRange < top )
2021-12-29 21:56:21 +00:00
continue ;
2022-09-28 15:25:08 +00:00
2022-09-30 11:36:50 +00:00
DAngle angle = dv . Angle ( ) ;
2022-11-25 12:13:50 +00:00
DAngle deltaangle = absangle ( angle , plActor - > spr . Angles . Yaw ) ;
2022-09-28 15:25:08 +00:00
if ( deltaangle > DAngle : : fromBuild ( pWeaponTrack - > thingAngle ) )
2021-12-29 21:56:21 +00:00
continue ;
2022-09-28 15:25:08 +00:00
if ( pPlayer - > aimTargetsCount < 16 & & cansee ( pos , plActor - > sector ( ) , pos2 , actor - > sector ( ) ) )
2021-12-29 21:56:21 +00:00
pPlayer - > aimTargets [ pPlayer - > aimTargetsCount + + ] = actor ;
2022-09-28 15:25:08 +00:00
double nDist2 = ( lpos - pos2 ) . Length ( ) ;
2021-12-29 21:56:21 +00:00
if ( nDist2 > = nClosest )
continue ;
2022-09-28 15:25:08 +00:00
if ( cansee ( pos , plActor - > sector ( ) , pos2 , actor - > sector ( ) ) )
2021-12-29 21:56:21 +00:00
{
nClosest = nDist2 ;
2022-09-28 15:25:08 +00:00
Aim . XY ( ) = angle . ToVector ( ) ;
Aim . Z = dv . Z / nDist ;
2021-12-29 21:56:21 +00:00
targetactor = actor ;
}
}
}
}
2022-09-28 15:25:08 +00:00
DVector3 Aim2 ( Aim ) ;
2022-11-25 12:13:50 +00:00
Aim2 . XY ( ) = Aim2 . XY ( ) . Rotated ( - plActor - > spr . Angles . Yaw ) ;
2022-09-28 15:58:22 +00:00
Aim2 . Z - = pPlayer - > slope ;
2022-09-28 15:25:08 +00:00
2022-09-28 17:20:57 +00:00
pPlayer - > relAim . X = interpolatedvalue ( pPlayer - > relAim . X , Aim2 . X , FixedToFloat ( pWeaponTrack - > aimSpeedHorz ) ) ;
pPlayer - > relAim . Y = interpolatedvalue ( pPlayer - > relAim . Y , Aim2 . Y , FixedToFloat ( pWeaponTrack - > aimSpeedHorz ) ) ;
pPlayer - > relAim . Z = interpolatedvalue ( pPlayer - > relAim . Z , Aim2 . Z , FixedToFloat ( pWeaponTrack - > aimSpeedVert ) ) ;
pPlayer - > aim = pPlayer - > relAim ;
2022-11-25 12:13:50 +00:00
pPlayer - > aim . XY ( ) = pPlayer - > aim . XY ( ) . Rotated ( plActor - > spr . Angles . Yaw ) ;
2022-09-28 17:20:57 +00:00
pPlayer - > aim . Z + = pPlayer - > slope ;
2021-12-29 21:56:21 +00:00
pPlayer - > aimTarget = targetactor ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-09-19 22:42:45 +00:00
struct t_WeaponModes
{
2021-12-29 21:56:21 +00:00
int update ;
int ammoType ;
2019-09-19 22:42:45 +00:00
} ;
t_WeaponModes weaponModes [ ] = {
2021-12-29 21:56:21 +00:00
{ 0 , - 1 } ,
{ 1 , - 1 } ,
{ 1 , 1 } ,
{ 1 , 2 } ,
{ 1 , 3 } ,
{ 1 , 4 } ,
{ 1 , 5 } ,
{ 1 , 6 } ,
{ 1 , 7 } ,
{ 1 , 8 } ,
{ 1 , 9 } ,
{ 1 , 10 } ,
{ 1 , 11 } ,
{ 0 , - 1 } ,
2019-09-19 22:42:45 +00:00
} ;
2021-12-29 21:56:21 +00:00
void WeaponRaise ( PLAYER * pPlayer )
{
assert ( pPlayer ! = NULL ) ;
int prevWeapon = pPlayer - > curWeapon ;
pPlayer - > curWeapon = pPlayer - > newWeapon ;
pPlayer - > newWeapon = kWeapNone ;
pPlayer - > weaponAmmo = weaponModes [ pPlayer - > curWeapon ] . ammoType ;
switch ( pPlayer - > curWeapon )
{
case kWeapPitchFork :
pPlayer - > weaponState = 0 ;
StartQAV ( pPlayer , kQAVFORKUP ) ;
break ;
case kWeapSpraycan :
if ( pPlayer - > weaponState = = 2 )
{
pPlayer - > weaponState = 3 ;
StartQAV ( pPlayer , kQAVCANPREF ) ;
}
else
{
pPlayer - > weaponState = 0 ;
StartQAV ( pPlayer , kQAVLITEOPEN ) ;
}
break ;
case kWeapDynamite :
if ( gInfiniteAmmo | | checkAmmo2 ( pPlayer , 5 , 1 ) )
{
pPlayer - > weaponState = 3 ;
if ( prevWeapon = = kWeapSpraycan )
StartQAV ( pPlayer , kQAVBUNUP ) ;
else
StartQAV ( pPlayer , kQAVBUNUP2 ) ;
}
break ;
case kWeapProximity :
if ( gInfiniteAmmo | | checkAmmo2 ( pPlayer , 10 , 1 ) )
{
pPlayer - > weaponState = 7 ;
StartQAV ( pPlayer , kQAVPROXUP ) ;
}
break ;
case kWeapRemote :
if ( gInfiniteAmmo | | checkAmmo2 ( pPlayer , 11 , 1 ) )
{
pPlayer - > weaponState = 10 ;
StartQAV ( pPlayer , kQAVREMUP2 ) ;
}
else
{
StartQAV ( pPlayer , kQAVREMUP3 ) ;
pPlayer - > weaponState = 11 ;
}
break ;
case kWeapShotgun :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) )
{
if ( gInfiniteAmmo | | pPlayer - > ammoCount [ 2 ] > = 4 )
StartQAV ( pPlayer , kQAV2SHOTUP ) ;
else
StartQAV ( pPlayer , kQAVSHOTUP ) ;
if ( gInfiniteAmmo | | pPlayer - > ammoCount [ 2 ] > = 4 )
pPlayer - > weaponState = 7 ;
else if ( pPlayer - > ammoCount [ 2 ] > 1 )
pPlayer - > weaponState = 3 ;
else if ( pPlayer - > ammoCount [ 2 ] > 0 )
pPlayer - > weaponState = 2 ;
else
pPlayer - > weaponState = 1 ;
}
else
{
if ( gInfiniteAmmo | | pPlayer - > ammoCount [ 2 ] > 1 )
pPlayer - > weaponState = 3 ;
else if ( pPlayer - > ammoCount [ 2 ] > 0 )
pPlayer - > weaponState = 2 ;
else
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVSHOTUP ) ;
}
break ;
case kWeapTommyGun :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & checkAmmo2 ( pPlayer , 3 , 2 ) )
{
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAV2TOMUP ) ;
}
else
{
pPlayer - > weaponState = 0 ;
StartQAV ( pPlayer , kQAVTOMUP ) ;
}
break ;
case kWeapVoodooDoll :
if ( gInfiniteAmmo | | checkAmmo2 ( pPlayer , 9 , 1 ) )
{
pPlayer - > weaponState = 2 ;
StartQAV ( pPlayer , kQAVVDUP ) ;
}
break ;
case kWeapFlareGun :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & checkAmmo2 ( pPlayer , 1 , 2 ) )
{
StartQAV ( pPlayer , kQAVFLAR2UP ) ;
pPlayer - > weaponState = 3 ;
}
else
{
StartQAV ( pPlayer , kQAVFLARUP ) ;
pPlayer - > weaponState = 2 ;
}
break ;
case kWeapTeslaCannon :
if ( checkAmmo2 ( pPlayer , 7 , 1 ) )
{
pPlayer - > weaponState = 2 ;
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) )
StartQAV ( pPlayer , kQAV2SGUNUP ) ;
else
StartQAV ( pPlayer , kQAVSGUNUP ) ;
}
else
{
pPlayer - > weaponState = 3 ;
StartQAV ( pPlayer , kQAVSGUNUP ) ;
}
break ;
case kWeapNapalm :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) )
{
StartQAV ( pPlayer , kQAV2NAPUP ) ;
pPlayer - > weaponState = 3 ;
}
else
{
StartQAV ( pPlayer , kQAVNAPUP ) ;
pPlayer - > weaponState = 2 ;
}
break ;
case kWeapLifeLeech :
pPlayer - > weaponState = 2 ;
StartQAV ( pPlayer , kQAVSTAFUP ) ;
break ;
case kWeapBeast :
pPlayer - > weaponState = 2 ;
StartQAV ( pPlayer , kQAVBSTUP ) ;
break ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void WeaponLower ( PLAYER * pPlayer )
{
assert ( pPlayer ! = NULL ) ;
2022-05-05 23:16:10 +00:00
if ( checkLitSprayOrTNT ( pPlayer ) )
2021-12-29 21:56:21 +00:00
return ;
pPlayer - > throwPower = 0 ;
int prevState = pPlayer - > weaponState ;
switch ( pPlayer - > curWeapon )
{
case kWeapPitchFork :
StartQAV ( pPlayer , kQAVFORKDOWN ) ;
break ;
case kWeapSpraycan :
sfxKill3DSound ( pPlayer - > actor , - 1 , 441 ) ;
switch ( prevState )
{
case 1 :
if ( VanillaMode ( ) )
{
StartQAV ( pPlayer , kQAVLITECLO2 ) ;
}
else
{
if ( pPlayer - > newWeapon = = kWeapDynamite ) // do not put away lighter if TNT was selected while throwing a spray can
{
pPlayer - > weaponState = 2 ;
StartQAV ( pPlayer , kQAVCANDOWN ) ;
WeaponRaise ( pPlayer ) ;
return ;
}
}
break ;
case 2 :
pPlayer - > weaponState = 1 ;
WeaponRaise ( pPlayer ) ;
return ;
case 4 :
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVCANDOWN ) ;
if ( VanillaMode ( ) )
{
pPlayer - > newWeapon = kWeapNone ;
WeaponLower ( pPlayer ) ;
}
else
{
if ( pPlayer - > newWeapon = = kWeapDynamite )
{
pPlayer - > weaponState = 2 ;
StartQAV ( pPlayer , kQAVCANDOWN ) ;
return ;
}
else
{
WeaponLower ( pPlayer ) ;
}
}
break ;
case 3 :
if ( pPlayer - > newWeapon = = kWeapDynamite )
{
pPlayer - > weaponState = 2 ;
StartQAV ( pPlayer , kQAVCANDOWN ) ;
return ;
}
else if ( pPlayer - > newWeapon = = kWeapSpraycan )
{
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVCANDOWN ) ;
pPlayer - > newWeapon = kWeapNone ;
WeaponLower ( pPlayer ) ;
}
else
{
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVCANDOWN ) ;
}
break ;
case 7 : // throwing ignited alt fire spray
if ( VanillaMode ( ) | | ( pPlayer - > newWeapon ! = 0 ) )
break ;
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVCANDOWN ) ;
break ;
}
break ;
case kWeapDynamite :
switch ( prevState )
{
case 1 :
if ( VanillaMode ( ) )
{
StartQAV ( pPlayer , kQAVLITECLO2 ) ;
}
else
{
if ( pPlayer - > newWeapon = = kWeapSpraycan ) // do not put away lighter if TNT was selected while throwing a spray can
{
pPlayer - > weaponState = 2 ;
StartQAV ( pPlayer , kQAVCANDOWN ) ;
WeaponRaise ( pPlayer ) ;
return ;
}
}
break ;
case 2 :
WeaponRaise ( pPlayer ) ;
break ;
case 3 :
if ( pPlayer - > newWeapon = = kWeapSpraycan )
{
pPlayer - > weaponState = 2 ;
StartQAV ( pPlayer , kQAVBUNDOWN ) ;
}
else
{
2023-03-16 04:50:52 +00:00
pPlayer - > weaponState = 1 ;
2021-12-29 21:56:21 +00:00
StartQAV ( pPlayer , kQAVBUNDOWN2 ) ;
}
break ;
default :
break ;
}
break ;
case kWeapProximity :
switch ( prevState )
{
case 7 :
StartQAV ( pPlayer , kQAVPROXDOWN ) ;
break ;
}
break ;
case kWeapRemote :
switch ( prevState )
{
case 10 :
StartQAV ( pPlayer , kQAVREMDOWN2 ) ;
break ;
case 11 :
StartQAV ( pPlayer , kQAVREMDOWN3 ) ;
break ;
}
break ;
case kWeapShotgun :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) )
StartQAV ( pPlayer , kQAV2SHOTDWN ) ;
else
StartQAV ( pPlayer , kQAVSHOTDOWN ) ;
break ;
case kWeapTommyGun :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & pPlayer - > weaponState = = 1 )
StartQAV ( pPlayer , kQAV2TOMDOWN ) ;
else
StartQAV ( pPlayer , kQAVTOMDOWN ) ;
break ;
case kWeapFlareGun :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & pPlayer - > weaponState = = 3 )
StartQAV ( pPlayer , kQAVFLAR2DWN ) ;
else
StartQAV ( pPlayer , kQAVFLARDOWN ) ;
break ;
case kWeapVoodooDoll :
StartQAV ( pPlayer , kQAVVDDOWN ) ;
break ;
case kWeapTeslaCannon :
if ( checkAmmo2 ( pPlayer , 7 , 10 ) & & powerupCheck ( pPlayer , kPwUpTwoGuns ) )
StartQAV ( pPlayer , kQAV2SGUNDWN ) ;
else
StartQAV ( pPlayer , kQAVSGUNDOWN ) ;
break ;
case kWeapNapalm :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) )
StartQAV ( pPlayer , kQAV2NAPDOWN ) ;
else
StartQAV ( pPlayer , kQAVNAPDOWN ) ;
break ;
case kWeapLifeLeech :
StartQAV ( pPlayer , kQAVSTAFDOWN ) ;
break ;
case kWeapBeast :
StartQAV ( pPlayer , kQAVBSTDOWN ) ;
break ;
}
pPlayer - > curWeapon = kWeapNone ;
pPlayer - > qavLoop = 0 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void WeaponUpdateState ( PLAYER * pPlayer )
{
static int lastWeapon = 0 ;
static int lastState = 0 ;
int va = pPlayer - > curWeapon ;
int vb = pPlayer - > weaponState ;
if ( va ! = lastWeapon | | vb ! = lastState )
{
lastWeapon = va ;
lastState = vb ;
}
switch ( lastWeapon )
{
case kWeapPitchFork :
SetQAV ( pPlayer , kQAVFORKIDLE ) ;
break ;
case kWeapSpraycan :
switch ( vb )
{
case 0 :
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVLITEFLAM ) ;
break ;
case 1 :
if ( CheckAmmo ( pPlayer , 6 , 1 ) )
{
pPlayer - > weaponState = 3 ;
StartQAV ( pPlayer , kQAVCANPREF ) ;
}
else
SetQAV ( pPlayer , kQAVLITEIDLE ) ;
break ;
case 3 :
SetQAV ( pPlayer , kQAVCANIDLE ) ;
break ;
case 4 :
if ( CheckAmmo ( pPlayer , 6 , 1 ) )
{
SetQAV ( pPlayer , kQAVCANIDLE ) ;
pPlayer - > weaponState = 3 ;
}
else
{
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVCANDOWN ) ;
}
sfxKill3DSound ( pPlayer - > actor , - 1 , 441 ) ;
break ;
}
break ;
case kWeapDynamite :
switch ( vb )
{
case 1 :
if ( pPlayer - > weaponAmmo = = 5 & & CheckAmmo ( pPlayer , 5 , 1 ) )
{
pPlayer - > weaponState = 3 ;
StartQAV ( pPlayer , kQAVBUNUP ) ;
}
break ;
case 0 :
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVLITEFLAM ) ;
break ;
case 2 :
if ( pPlayer - > ammoCount [ 5 ] > 0 )
{
pPlayer - > weaponState = 3 ;
StartQAV ( pPlayer , kQAVBUNUP ) ;
}
else
SetQAV ( pPlayer , kQAVLITEIDLE ) ;
break ;
case 3 :
SetQAV ( pPlayer , kQAVBUNIDLE ) ;
break ;
}
break ;
case kWeapProximity :
switch ( vb )
{
case 7 :
SetQAV ( pPlayer , kQAVPROXIDLE ) ;
break ;
case 8 :
pPlayer - > weaponState = 7 ;
StartQAV ( pPlayer , kQAVPROXUP ) ;
break ;
}
break ;
case kWeapRemote :
switch ( vb )
{
case 10 :
SetQAV ( pPlayer , kQAVREMIDLE1 ) ;
break ;
case 11 :
SetQAV ( pPlayer , kQAVREMIDLE2 ) ;
break ;
case 12 :
if ( pPlayer - > ammoCount [ 11 ] > 0 )
{
pPlayer - > weaponState = 10 ;
StartQAV ( pPlayer , kQAVREMUP2 ) ;
}
else
pPlayer - > weaponState = - 1 ;
break ;
}
break ;
case kWeapShotgun :
switch ( vb )
{
case 6 :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & ( gInfiniteAmmo | | CheckAmmo ( pPlayer , 2 , 4 ) ) )
pPlayer - > weaponState = 7 ;
else
pPlayer - > weaponState = 1 ;
break ;
case 7 :
SetQAV ( pPlayer , kQAV2SHOTI ) ;
break ;
case 1 :
if ( CheckAmmo ( pPlayer , 2 , 1 ) )
{
sfxPlay3DSound ( pPlayer - > actor , 410 , 3 , 2 ) ;
StartQAV ( pPlayer , kQAVSHOTL1 , nClientEjectShell ) ;
if ( gInfiniteAmmo | | pPlayer - > ammoCount [ 2 ] > 1 )
pPlayer - > weaponState = 3 ;
else
pPlayer - > weaponState = 2 ;
}
else
SetQAV ( pPlayer , kQAVSHOTI3 ) ;
break ;
case 2 :
SetQAV ( pPlayer , kQAVSHOTI2 ) ;
break ;
case 3 :
SetQAV ( pPlayer , kQAVSHOTI1 ) ;
break ;
}
break ;
case kWeapTommyGun :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & checkAmmo2 ( pPlayer , 3 , 2 ) )
{
SetQAV ( pPlayer , kQAV2TOMIDLE ) ;
pPlayer - > weaponState = 1 ;
}
else
{
SetQAV ( pPlayer , kQAVTOMIDLE ) ;
pPlayer - > weaponState = 0 ;
}
break ;
case kWeapFlareGun :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) )
{
if ( vb = = 3 & & checkAmmo2 ( pPlayer , 1 , 2 ) )
SetQAV ( pPlayer , kQAVFLAR2I ) ;
else
{
SetQAV ( pPlayer , kQAVFLARIDLE ) ;
pPlayer - > weaponState = 2 ;
}
}
else
SetQAV ( pPlayer , kQAVFLARIDLE ) ;
break ;
case kWeapVoodooDoll :
if ( pPlayer - > actor - > xspr . height < 256 & & pPlayer - > swayHeight ! = 0 )
StartQAV ( pPlayer , kQAVVDIDLE2 ) ;
else
SetQAV ( pPlayer , kQAVVDIDLE1 ) ;
break ;
case kWeapTeslaCannon :
switch ( vb )
{
case 2 :
if ( checkAmmo2 ( pPlayer , 7 , 10 ) & & powerupCheck ( pPlayer , kPwUpTwoGuns ) )
SetQAV ( pPlayer , kQAV2SGUNIDL ) ;
else
SetQAV ( pPlayer , kQAVSGUNIDL1 ) ;
break ;
case 3 :
SetQAV ( pPlayer , kQAVSGUNIDL2 ) ;
break ;
}
break ;
case kWeapNapalm :
switch ( vb )
{
case 3 :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & ( gInfiniteAmmo | | CheckAmmo ( pPlayer , 4 , 4 ) ) )
SetQAV ( pPlayer , kQAV2NAPIDLE ) ;
else
SetQAV ( pPlayer , kQAVNAPIDLE ) ;
break ;
case 2 :
SetQAV ( pPlayer , kQAVNAPIDLE ) ;
break ;
}
break ;
case kWeapLifeLeech :
switch ( vb )
{
case 2 :
SetQAV ( pPlayer , kQAVSTAFIDL1 ) ;
break ;
}
break ;
case kWeapBeast :
SetQAV ( pPlayer , kQAVBSTIDLE ) ;
break ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void FirePitchfork ( int , PLAYER * pPlayer )
{
DBloodActor * actor = pPlayer - > actor ;
2022-09-28 16:45:40 +00:00
double r1 = Random2F ( 2000 , 14 ) ;
double r2 = Random2F ( 2000 , 14 ) ;
double r3 = Random2F ( 2000 , 14 ) ;
2021-12-29 21:56:21 +00:00
for ( int i = 0 ; i < 4 ; i + + )
2023-09-28 09:43:14 +00:00
actFireVector ( actor , ( 2 * i - 3 ) * 2.5 , pPlayer - > zWeapon - pPlayer - > actor - > spr . pos . Z , pPlayer - > aim + DVector3 ( r1 , r2 , r3 ) , kVectorTine ) ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void FireSpray ( int , PLAYER * pPlayer )
2019-09-19 22:42:45 +00:00
{
2023-09-28 09:43:14 +00:00
playerFireMissile ( pPlayer , 0 , pPlayer - > aim , kMissileFlameSpray ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 6 , 4 ) ;
if ( CheckAmmo ( pPlayer , 6 , 1 ) )
sfxPlay3DSound ( pPlayer - > actor , 441 , 1 , 2 ) ;
else
sfxKill3DSound ( pPlayer - > actor , - 1 , 441 ) ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void ThrowCan ( int , PLAYER * pPlayer )
{
sfxKill3DSound ( pPlayer - > actor , - 1 , 441 ) ;
2022-09-29 11:17:27 +00:00
double nSpeed = getThrowPower ( pPlayer ) ;
2021-12-29 21:56:21 +00:00
sfxPlay3DSound ( pPlayer - > actor , 455 , 1 , 0 ) ;
2022-09-29 10:53:11 +00:00
auto spawned = playerFireThing ( pPlayer , 0 , - 9460 / 65536. , kThingArmedSpray , nSpeed ) ;
2021-12-29 21:56:21 +00:00
if ( spawned )
{
sfxPlay3DSound ( spawned , 441 , 0 , 0 ) ;
2022-05-05 23:40:27 +00:00
spawned - > spr . shade = - 128 ;
2022-08-10 21:45:29 +00:00
evPostActor ( spawned , pPlayer - > fuseTime , kCmdOn , pPlayer - > actor ) ;
2021-12-29 21:56:21 +00:00
spawned - > xspr . Impact = 1 ;
UseAmmo ( pPlayer , 6 , gAmmoItemData [ 0 ] . count ) ;
pPlayer - > throwPower = 0 ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DropCan ( int , PLAYER * pPlayer )
{
sfxKill3DSound ( pPlayer - > actor , - 1 , 441 ) ;
auto spawned = playerFireThing ( pPlayer , 0 , 0 , kThingArmedSpray , 0 ) ;
if ( spawned )
{
2022-08-10 21:45:29 +00:00
evPostActor ( spawned , pPlayer - > fuseTime , kCmdOn , pPlayer - > actor ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 6 , gAmmoItemData [ 0 ] . count ) ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void ExplodeCan ( int , PLAYER * pPlayer )
{
sfxKill3DSound ( pPlayer - > actor , - 1 , 441 ) ;
auto spawned = playerFireThing ( pPlayer , 0 , 0 , kThingArmedSpray , 0 ) ;
if ( spawned )
{
2022-08-10 21:45:29 +00:00
evPostActor ( spawned , 0 , kCmdOn , pPlayer - > actor ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 6 , gAmmoItemData [ 0 ] . count ) ;
StartQAV ( pPlayer , kQAVCANBOOM ) ;
pPlayer - > curWeapon = kWeapNone ;
pPlayer - > throwPower = 0 ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void ThrowBundle ( int , PLAYER * pPlayer )
{
sfxKill3DSound ( pPlayer - > actor , 16 , - 1 ) ;
2022-09-29 11:17:27 +00:00
double nSpeed = getThrowPower ( pPlayer ) ;
2021-12-29 21:56:21 +00:00
sfxPlay3DSound ( pPlayer - > actor , 455 , 1 , 0 ) ;
2022-09-29 10:53:11 +00:00
auto spawned = playerFireThing ( pPlayer , 0 , - 9460 / 65536. , kThingArmedTNTBundle , nSpeed ) ;
2021-12-29 21:56:21 +00:00
if ( spawned )
{
if ( pPlayer - > fuseTime < 0 )
spawned - > xspr . Impact = 1 ;
else
2022-08-10 21:45:29 +00:00
evPostActor ( spawned , pPlayer - > fuseTime , kCmdOn , pPlayer - > actor ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 5 , 1 ) ;
pPlayer - > throwPower = 0 ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DropBundle ( int , PLAYER * pPlayer )
{
sfxKill3DSound ( pPlayer - > actor , 16 , - 1 ) ;
auto spawned = playerFireThing ( pPlayer , 0 , 0 , kThingArmedTNTBundle , 0 ) ;
if ( spawned )
{
2022-08-10 21:45:29 +00:00
evPostActor ( spawned , pPlayer - > fuseTime , kCmdOn , pPlayer - > actor ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 5 , 1 ) ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void ExplodeBundle ( int , PLAYER * pPlayer )
{
sfxKill3DSound ( pPlayer - > actor , 16 , - 1 ) ;
auto spawned = playerFireThing ( pPlayer , 0 , 0 , kThingArmedTNTBundle , 0 ) ;
if ( spawned )
{
2022-08-10 21:45:29 +00:00
evPostActor ( spawned , 0 , kCmdOn , pPlayer - > actor ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 5 , 1 ) ;
StartQAV ( pPlayer , kQAVDYNEXPLO ) ;
pPlayer - > curWeapon = kWeapNone ;
pPlayer - > throwPower = 0 ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void ThrowProx ( int , PLAYER * pPlayer )
{
2022-09-29 11:17:27 +00:00
double nSpeed = getThrowPower ( pPlayer ) ;
2021-12-29 21:56:21 +00:00
sfxPlay3DSound ( pPlayer - > actor , 455 , 1 , 0 ) ;
2022-09-29 10:53:11 +00:00
auto spawned = playerFireThing ( pPlayer , 0 , - 9460 / 65536. , kThingArmedProxBomb , nSpeed ) ;
2021-12-29 21:56:21 +00:00
if ( spawned )
{
2022-08-10 21:45:29 +00:00
evPostActor ( spawned , 240 , kCmdOn , pPlayer - > actor ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 10 , 1 ) ;
pPlayer - > throwPower = 0 ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DropProx ( int , PLAYER * pPlayer )
2019-09-19 22:42:45 +00:00
{
2021-12-29 21:56:21 +00:00
auto spawned = playerFireThing ( pPlayer , 0 , 0 , kThingArmedProxBomb , 0 ) ;
if ( spawned )
{
2022-08-10 21:45:29 +00:00
evPostActor ( spawned , 240 , kCmdOn , pPlayer - > actor ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 10 , 1 ) ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void ThrowRemote ( int , PLAYER * pPlayer )
{
2022-09-29 11:17:27 +00:00
double nSpeed = getThrowPower ( pPlayer ) ;
2021-12-29 21:56:21 +00:00
sfxPlay3DSound ( pPlayer - > actor , 455 , 1 , 0 ) ;
2022-09-29 10:53:11 +00:00
auto spawned = playerFireThing ( pPlayer , 0 , - 9460 / 65536. , kThingArmedRemoteBomb , nSpeed ) ;
2021-12-29 21:56:21 +00:00
if ( spawned )
{
2023-09-30 08:58:12 +00:00
spawned - > xspr . rxID = 90 + ( pPlayer - > actor - > GetType ( ) - kDudePlayer1 ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 11 , 1 ) ;
pPlayer - > throwPower = 0 ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DropRemote ( int , PLAYER * pPlayer )
2019-09-19 22:42:45 +00:00
{
2021-12-29 21:56:21 +00:00
auto spawned = playerFireThing ( pPlayer , 0 , 0 , kThingArmedRemoteBomb , 0 ) ;
if ( spawned )
{
2023-09-30 08:58:12 +00:00
spawned - > xspr . rxID = 90 + ( pPlayer - > actor - > GetType ( ) - kDudePlayer1 ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 11 , 1 ) ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
void FireRemote ( int , PLAYER * pPlayer )
2019-09-19 22:42:45 +00:00
{
2023-09-30 08:58:12 +00:00
evSendGame ( 90 + ( pPlayer - > actor - > GetType ( ) - kDudePlayer1 ) , kCmdOn ) ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-10-11 10:18:25 +00:00
enum { kMaxShotgunBarrels = 4 } ;
2019-09-19 22:42:45 +00:00
2021-12-29 21:56:21 +00:00
void FireShotgun ( int nTrigger , PLAYER * pPlayer )
{
DBloodActor * actor = pPlayer - > actor ;
assert ( nTrigger > 0 & & nTrigger < = kMaxShotgunBarrels ) ;
if ( nTrigger = = 1 )
{
sfxPlay3DSound ( pPlayer - > actor , 411 , 2 , 0 ) ;
pPlayer - > tiltEffect = 30 ;
pPlayer - > visibility = 20 ;
}
else
{
sfxPlay3DSound ( pPlayer - > actor , 412 , 2 , 0 ) ;
pPlayer - > tiltEffect = 50 ;
pPlayer - > visibility = 40 ;
}
int n = nTrigger < < 4 ;
for ( int i = 0 ; i < n ; i + + )
{
2022-09-28 16:45:40 +00:00
double r1 , r2 , r3 ;
2021-12-29 21:56:21 +00:00
VECTOR_TYPE nType ;
if ( nTrigger = = 1 )
{
2022-09-28 16:45:40 +00:00
r1 = Random3F ( 1500 , 14 ) ;
r2 = Random3F ( 1500 , 14 ) ;
r3 = Random3F ( 500 , 14 ) ;
2021-12-29 21:56:21 +00:00
nType = kVectorShell ;
}
else
{
2022-09-28 16:45:40 +00:00
r1 = Random3F ( 2500 , 14 ) ;
r2 = Random3F ( 2500 , 14 ) ;
r3 = Random3F ( 1500 , 14 ) ;
2021-12-29 21:56:21 +00:00
nType = kVectorShellAP ;
}
2023-09-28 09:43:14 +00:00
actFireVector ( actor , 0 , pPlayer - > zWeapon - pPlayer - > actor - > spr . pos . Z , pPlayer - > aim + DVector3 ( r1 , r2 , r3 ) , nType ) ;
2021-12-29 21:56:21 +00:00
}
UseAmmo ( pPlayer , pPlayer - > weaponAmmo , nTrigger ) ;
pPlayer - > flashEffect = 1 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void EjectShell ( int , PLAYER * pPlayer )
2019-09-19 22:42:45 +00:00
{
2022-09-29 12:19:57 +00:00
SpawnShellEject ( pPlayer , 25 / 16. , 35 ) ;
SpawnShellEject ( pPlayer , 3 , 35 ) ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
void FireTommy ( int nTrigger , PLAYER * pPlayer )
{
DBloodActor * actor = pPlayer - > actor ;
sfxPlay3DSound ( pPlayer - > actor , 431 , - 1 , 0 ) ;
switch ( nTrigger )
{
case 1 :
{
2022-09-28 16:45:40 +00:00
double r1 = Random3F ( 400 , 14 ) ;
double r2 = Random3F ( 1200 , 14 ) ;
double r3 = Random3F ( 1200 , 14 ) ;
2023-09-28 09:43:14 +00:00
actFireVector ( actor , 0 , pPlayer - > zWeapon - pPlayer - > actor - > spr . pos . Z , pPlayer - > aim + DVector3 ( r3 , r2 , r1 ) , kVectorTommyRegular ) ;
2022-09-29 12:19:57 +00:00
SpawnBulletEject ( pPlayer , - 15 / 16. , - 45 ) ;
2021-12-29 21:56:21 +00:00
pPlayer - > visibility = 20 ;
break ;
}
case 2 :
{
2022-09-28 16:45:40 +00:00
double r1 = Random3F ( 400 , 14 ) ;
double r2 = Random3F ( 1200 , 14 ) ;
double r3 = Random3F ( 1200 , 14 ) ;
2023-09-28 09:43:14 +00:00
actFireVector ( actor , - 7.5 , pPlayer - > zWeapon - pPlayer - > actor - > spr . pos . Z , pPlayer - > aim + DVector3 ( r3 , r2 , r1 ) , kVectorTommyRegular ) ;
2022-09-29 12:19:57 +00:00
SpawnBulletEject ( pPlayer , - 140 / 16. , - 45 ) ;
2021-12-29 21:56:21 +00:00
r1 = Random3 ( 400 ) ;
r2 = Random3 ( 1200 ) ;
r3 = Random3 ( 1200 ) ;
2023-09-28 09:43:14 +00:00
actFireVector ( actor , 7.5 , pPlayer - > zWeapon - pPlayer - > actor - > spr . pos . Z , pPlayer - > aim + DVector3 ( r3 , r2 , r1 ) , kVectorTommyRegular ) ;
2022-09-29 12:19:57 +00:00
SpawnBulletEject ( pPlayer , 140 / 16. , 45 ) ;
2021-12-29 21:56:21 +00:00
pPlayer - > visibility = 30 ;
break ;
}
}
UseAmmo ( pPlayer , pPlayer - > weaponAmmo , nTrigger ) ;
pPlayer - > flashEffect = 1 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-10-11 10:18:25 +00:00
enum { kMaxSpread = 14 } ;
2022-09-28 17:15:56 +00:00
static constexpr DAngle DAngle10 = DAngle : : fromDeg ( 10 ) ;
static constexpr DAngle DAngle20 = DAngle : : fromDeg ( 20 ) ;
2019-09-19 22:42:45 +00:00
2021-12-29 21:56:21 +00:00
void FireSpread ( int nTrigger , PLAYER * pPlayer )
{
DBloodActor * actor = pPlayer - > actor ;
assert ( nTrigger > 0 & & nTrigger < = kMaxSpread ) ;
2023-09-28 09:43:14 +00:00
DVector3 aim = pPlayer - > aim ;
2022-09-30 11:38:21 +00:00
DAngle angle = ( ( aim . XY ( ) ) . Angle ( ) + ( ( DAngle20 * ( nTrigger - 1 ) ) / kMaxSpread - DAngle10 ) ) ;
2022-09-28 17:15:56 +00:00
DVector3 dv = DVector3 ( angle . ToVector ( ) , aim . Z ) ;
2021-12-29 21:56:21 +00:00
sfxPlay3DSound ( pPlayer - > actor , 431 , - 1 , 0 ) ;
2022-09-28 17:15:56 +00:00
double r1 , r2 , r3 ;
r1 = Random3F ( 300 , 14 ) ;
r2 = Random3F ( 600 , 14 ) ;
r3 = Random3F ( 600 , 14 ) ;
actFireVector ( actor , 0 , pPlayer - > zWeapon - pPlayer - > actor - > spr . pos . Z , dv + DVector3 ( r3 , r2 , r1 ) , kVectorTommyAP ) ;
2022-09-29 12:19:57 +00:00
int ri = Random2 ( 90 ) ;
r2 = Random2F ( 30 , 4 ) ;
SpawnBulletEject ( pPlayer , r2 , ri ) ;
2021-12-29 21:56:21 +00:00
pPlayer - > visibility = 20 ;
UseAmmo ( pPlayer , pPlayer - > weaponAmmo , 1 ) ;
pPlayer - > flashEffect = 1 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void AltFireSpread ( int nTrigger , PLAYER * pPlayer )
{
DBloodActor * actor = pPlayer - > actor ;
assert ( nTrigger > 0 & & nTrigger < = kMaxSpread ) ;
2023-09-28 09:43:14 +00:00
DVector3 aim = pPlayer - > aim ;
2022-09-30 11:38:21 +00:00
DAngle angle = ( ( aim . XY ( ) ) . Angle ( ) + ( ( DAngle20 * ( nTrigger - 1 ) ) / kMaxSpread - DAngle10 ) ) ;
2022-09-28 17:15:56 +00:00
DVector3 dv = DVector3 ( angle . ToVector ( ) , aim . Z ) ;
2021-12-29 21:56:21 +00:00
sfxPlay3DSound ( pPlayer - > actor , 431 , - 1 , 0 ) ;
2022-09-28 17:15:56 +00:00
double r1 , r2 , r3 ;
r1 = Random3F ( 300 , 14 ) ;
r2 = Random3F ( 600 , 14 ) ;
r3 = Random3F ( 600 , 14 ) ;
actFireVector ( actor , - 7.5 , pPlayer - > zWeapon - pPlayer - > actor - > spr . pos . Z , dv + DVector3 ( r3 , r2 , r1 ) , kVectorTommyAP ) ;
2022-09-29 12:19:57 +00:00
int ri = Random2 ( 45 ) ;
r2 = Random2F ( 120 , 4 ) ;
SpawnBulletEject ( pPlayer , r2 , ri ) ;
2022-09-28 17:15:56 +00:00
r1 = Random3F ( 300 , 14 ) ;
r2 = Random3F ( 600 , 14 ) ;
r3 = Random3F ( 600 , 14 ) ;
actFireVector ( actor , 7.5 , pPlayer - > zWeapon - pPlayer - > actor - > spr . pos . Z , dv + DVector3 ( r3 , r2 , r1 ) , kVectorTommyAP ) ;
2022-09-29 12:19:57 +00:00
ri = Random2 ( - 45 ) ;
r2 = Random2F ( - 120 , 4 ) ;
SpawnBulletEject ( pPlayer , r2 , ri ) ;
2021-12-29 21:56:21 +00:00
pPlayer - > tiltEffect = 20 ;
pPlayer - > visibility = 30 ;
UseAmmo ( pPlayer , pPlayer - > weaponAmmo , 2 ) ;
pPlayer - > flashEffect = 1 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void AltFireSpread2 ( int nTrigger , PLAYER * pPlayer )
{
DBloodActor * actor = pPlayer - > actor ;
assert ( nTrigger > 0 & & nTrigger < = kMaxSpread ) ;
2023-09-28 09:43:14 +00:00
DVector3 aim = pPlayer - > aim ;
2022-09-30 11:38:21 +00:00
DAngle angle = ( ( aim . XY ( ) ) . Angle ( ) + ( ( DAngle20 * ( nTrigger - 1 ) ) / kMaxSpread - DAngle10 ) ) ;
2022-09-28 17:15:56 +00:00
DVector3 dv = DVector3 ( angle . ToVector ( ) , aim . Z ) ;
2021-12-29 21:56:21 +00:00
sfxPlay3DSound ( pPlayer - > actor , 431 , - 1 , 0 ) ;
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & checkAmmo2 ( pPlayer , 3 , 2 ) )
{
2022-09-28 17:15:56 +00:00
double r1 , r2 , r3 ;
r1 = Random3F ( 300 , 14 ) ;
r2 = Random3F ( 600 , 14 ) ;
r3 = Random3F ( 600 , 14 ) ;
actFireVector ( actor , - 7.5 , pPlayer - > zWeapon - pPlayer - > actor - > spr . pos . Z , dv + DVector3 ( r3 , r2 , r1 ) , kVectorTommyAP ) ;
2022-09-29 12:19:57 +00:00
int ri = Random2 ( 45 ) ;
r2 = Random2F ( 120 , 4 ) ;
SpawnBulletEject ( pPlayer , r2 , ri ) ;
2022-09-28 17:15:56 +00:00
r1 = Random3F ( 300 , 14 ) ;
r2 = Random3F ( 600 , 14 ) ;
r3 = Random3F ( 600 , 14 ) ;
actFireVector ( actor , 7.5 , pPlayer - > zWeapon - pPlayer - > actor - > spr . pos . Z , dv + DVector3 ( r3 , r2 , r1 ) , kVectorTommyAP ) ;
2022-09-29 12:19:57 +00:00
ri = Random2 ( - 45 ) ;
r2 = Random2F ( - 120 , 4 ) ;
SpawnBulletEject ( pPlayer , r2 , ri ) ;
2021-12-29 21:56:21 +00:00
pPlayer - > tiltEffect = 30 ;
pPlayer - > visibility = 45 ;
UseAmmo ( pPlayer , pPlayer - > weaponAmmo , 2 ) ;
}
else
{
2022-09-28 17:15:56 +00:00
double r1 , r2 , r3 ;
r1 = Random3F ( 300 , 14 ) ;
r2 = Random3F ( 600 , 14 ) ;
r3 = Random3F ( 600 , 14 ) ;
actFireVector ( actor , 0 , pPlayer - > zWeapon - pPlayer - > actor - > spr . pos . Z , dv + DVector3 ( r3 , r2 , r1 ) , kVectorTommyAP ) ;
2022-09-29 12:19:57 +00:00
int ri = Random2 ( 90 ) ;
r2 = Random2F ( 30 , 4 ) ;
SpawnBulletEject ( pPlayer , r2 , ri ) ;
2021-12-29 21:56:21 +00:00
pPlayer - > tiltEffect = 20 ;
pPlayer - > visibility = 30 ;
UseAmmo ( pPlayer , pPlayer - > weaponAmmo , 1 ) ;
}
pPlayer - > flashEffect = 1 ;
if ( ! checkAmmo2 ( pPlayer , 3 , 1 ) )
{
WeaponLower ( pPlayer ) ;
pPlayer - > weaponState = - 1 ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void FireFlare ( int nTrigger , PLAYER * pPlayer )
{
auto plActor = pPlayer - > actor ;
2022-09-28 16:45:40 +00:00
double offset = 0 ;
2021-12-29 21:56:21 +00:00
switch ( nTrigger )
{
case 2 :
2022-09-28 16:45:40 +00:00
offset = - 7.5 ;
2021-12-29 21:56:21 +00:00
break ;
case 3 :
2022-09-28 16:45:40 +00:00
offset = 7.5 ;
2021-12-29 21:56:21 +00:00
break ;
}
2023-09-28 09:43:14 +00:00
playerFireMissile ( pPlayer , offset , pPlayer - > aim , kMissileFlareRegular ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 1 , 1 ) ;
sfxPlay3DSound ( pPlayer - > actor , 420 , 2 , 0 ) ;
pPlayer - > visibility = 30 ;
pPlayer - > flashEffect = 1 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void AltFireFlare ( int nTrigger , PLAYER * pPlayer )
{
auto plActor = pPlayer - > actor ;
2022-09-28 16:45:40 +00:00
double offset = 0 ;
2021-12-29 21:56:21 +00:00
switch ( nTrigger )
{
case 2 :
2022-09-28 16:45:40 +00:00
offset = - 7.5 ;
2021-12-29 21:56:21 +00:00
break ;
case 3 :
2022-09-28 16:45:40 +00:00
offset = 7.5 ;
2021-12-29 21:56:21 +00:00
break ;
}
2023-09-28 09:43:14 +00:00
playerFireMissile ( pPlayer , offset , pPlayer - > aim , kMissileFlareAlt ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 1 , 8 ) ;
sfxPlay3DSound ( pPlayer - > actor , 420 , 2 , 0 ) ;
pPlayer - > visibility = 45 ;
pPlayer - > flashEffect = 1 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void FireVoodoo ( int nTrigger , PLAYER * pPlayer )
{
nTrigger - - ;
DBloodActor * actor = pPlayer - > actor ;
auto plActor = pPlayer - > actor ;
if ( nTrigger = = 4 )
{
actDamageSprite ( actor , actor , kDamageBullet , 1 < < 4 ) ;
return ;
}
DBloodActor * targetactor = pPlayer - > voodooTarget ;
if ( ! targetactor ) return ;
if ( ! gGameOptions . bFriendlyFire & & IsTargetTeammate ( pPlayer , targetactor ) )
return ;
switch ( nTrigger )
{
case 0 :
{
sfxPlay3DSound ( actor , 460 , 2 , 0 ) ;
fxSpawnBlood ( targetactor , 17 < < 4 ) ;
int nDamage = actDamageSprite ( actor , targetactor , kDamageSpirit , 17 < < 4 ) ;
UseAmmo ( pPlayer , 9 , nDamage / 4 ) ;
break ;
}
case 1 :
{
sfxPlay3DSound ( actor , 460 , 2 , 0 ) ;
fxSpawnBlood ( targetactor , 17 < < 4 ) ;
int nDamage = actDamageSprite ( actor , targetactor , kDamageSpirit , 9 < < 4 ) ;
if ( targetactor - > IsPlayerActor ( ) )
2023-09-30 08:58:12 +00:00
WeaponLower ( getPlayer ( targetactor ) ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , 9 , nDamage / 4 ) ;
break ;
}
case 3 :
{
sfxPlay3DSound ( actor , 463 , 2 , 0 ) ;
fxSpawnBlood ( targetactor , 17 < < 4 ) ;
int nDamage = actDamageSprite ( actor , targetactor , kDamageSpirit , 49 < < 4 ) ;
UseAmmo ( pPlayer , 9 , nDamage / 4 ) ;
break ;
}
case 2 :
{
sfxPlay3DSound ( actor , 460 , 2 , 0 ) ;
fxSpawnBlood ( targetactor , 17 < < 4 ) ;
int nDamage = actDamageSprite ( actor , targetactor , kDamageSpirit , 11 < < 4 ) ;
if ( targetactor - > IsPlayerActor ( ) )
{
2023-09-30 08:58:12 +00:00
PLAYER * pOtherPlayer = getPlayer ( targetactor ) ;
2021-12-29 21:56:21 +00:00
pOtherPlayer - > blindEffect = 128 ;
}
UseAmmo ( pPlayer , 9 , nDamage / 4 ) ;
break ;
}
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void AltFireVoodoo ( int nTrigger , PLAYER * pPlayer )
{
DBloodActor * actor = pPlayer - > actor ;
if ( nTrigger = = 2 ) {
// by NoOne: trying to simulate v1.0x voodoo here.
// dunno how exactly it works, but at least it not spend all the ammo on alt fire
if ( gGameOptions . weaponsV10x & & ! VanillaMode ( ) ) {
int nCount = ClipHigh ( pPlayer - > ammoCount [ 9 ] , pPlayer - > aimTargetsCount ) ;
if ( nCount > 0 )
{
for ( int i = 0 ; i < pPlayer - > aimTargetsCount ; i + + )
{
DBloodActor * targetactor = pPlayer - > aimTargets [ i ] ;
if ( ! targetactor ) continue ;
if ( ! gGameOptions . bFriendlyFire & & IsTargetTeammate ( pPlayer , targetactor ) )
continue ;
2022-09-28 15:27:33 +00:00
double nDist = ( targetactor - > spr . pos . XY ( ) - pPlayer - > actor - > spr . pos . XY ( ) ) . Length ( ) ;
if ( nDist > 0 & & nDist < 3200 )
2021-12-29 21:56:21 +00:00
{
int vc = pPlayer - > ammoCount [ 9 ] > > 3 ;
int v8 = pPlayer - > ammoCount [ 9 ] < < 1 ;
int nDamage = ( v8 + Random ( vc ) ) < < 4 ;
2022-09-28 15:27:33 +00:00
nDamage = int ( ( nDamage * ( ( 3200 - nDist ) + 1 / 16. ) ) / 3200 ) ;
2021-12-29 21:56:21 +00:00
nDamage = actDamageSprite ( actor , targetactor , kDamageSpirit , nDamage ) ;
if ( targetactor - > IsPlayerActor ( ) )
{
2023-09-30 08:58:12 +00:00
PLAYER * pOtherPlayer = getPlayer ( targetactor ) ;
2021-12-29 21:56:21 +00:00
if ( ! pOtherPlayer - > godMode | | ! powerupCheck ( pOtherPlayer , kPwUpDeathMask ) )
powerupActivate ( pOtherPlayer , kPwUpDeliriumShroom ) ;
}
fxSpawnBlood ( targetactor , 0 ) ;
}
}
}
UseAmmo ( pPlayer , 9 , 20 ) ;
pPlayer - > weaponState = 0 ;
return ;
}
//int nAmmo = pPlayer->ammCount[9];
int nCount = ClipHigh ( pPlayer - > ammoCount [ 9 ] , pPlayer - > aimTargetsCount ) ;
if ( nCount > 0 )
{
int v4 = pPlayer - > ammoCount [ 9 ] - ( pPlayer - > ammoCount [ 9 ] / nCount ) * nCount ;
for ( int i = 0 ; i < pPlayer - > aimTargetsCount ; i + + )
{
DBloodActor * targetactor = pPlayer - > aimTargets [ i ] ;
if ( ! targetactor ) continue ;
if ( ! gGameOptions . bFriendlyFire & & IsTargetTeammate ( pPlayer , targetactor ) )
continue ;
if ( v4 > 0 )
v4 - - ;
2022-09-28 15:27:33 +00:00
double nDist = ( targetactor - > spr . pos . XY ( ) - pPlayer - > actor - > spr . pos . XY ( ) ) . Length ( ) ;
if ( nDist > 0 & & nDist < 3200 )
2021-12-29 21:56:21 +00:00
{
int vc = pPlayer - > ammoCount [ 9 ] > > 3 ;
int v8 = pPlayer - > ammoCount [ 9 ] < < 1 ;
int nDamage = ( v8 + Random2 ( vc ) ) < < 4 ;
2022-09-28 15:27:33 +00:00
nDamage = int ( ( nDamage * ( ( 3200 - nDist ) + 1 / 16. ) ) / 3200 ) ;
2021-12-29 21:56:21 +00:00
nDamage = actDamageSprite ( actor , targetactor , kDamageSpirit , nDamage ) ;
UseAmmo ( pPlayer , 9 , nDamage ) ;
if ( targetactor - > IsPlayerActor ( ) )
{
2023-09-30 08:58:12 +00:00
PLAYER * pOtherPlayer = getPlayer ( targetactor ) ;
2021-12-29 21:56:21 +00:00
if ( ! pOtherPlayer - > godMode | | ! powerupCheck ( pOtherPlayer , kPwUpDeathMask ) )
powerupActivate ( pOtherPlayer , kPwUpDeliriumShroom ) ;
}
fxSpawnBlood ( targetactor , 0 ) ;
}
}
}
UseAmmo ( pPlayer , 9 , pPlayer - > ammoCount [ 9 ] ) ;
2022-01-12 11:22:48 +00:00
pPlayer - > hasWeapon [ kWeapVoodooDoll ] = 0 ;
2021-12-29 21:56:21 +00:00
pPlayer - > weaponState = - 1 ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DropVoodoo ( int , PLAYER * pPlayer )
{
sfxPlay3DSound ( pPlayer - > actor , 455 , 2 , 0 ) ;
2022-09-29 10:53:11 +00:00
auto spawned = playerFireThing ( pPlayer , 0 , - 4730 / 65536. , kThingVoodooHead , 12.8 ) ;
2021-12-29 21:56:21 +00:00
if ( spawned )
{
spawned - > xspr . data1 = pPlayer - > ammoCount [ 9 ] ;
evPostActor ( spawned , 90 , kCallbackDropVoodoo ) ;
UseAmmo ( pPlayer , 6 , gAmmoItemData [ 0 ] . count ) ;
UseAmmo ( pPlayer , 9 , pPlayer - > ammoCount [ 9 ] ) ;
2022-01-12 11:22:48 +00:00
pPlayer - > hasWeapon [ kWeapVoodooDoll ] = 0 ;
2021-12-29 21:56:21 +00:00
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-09-19 22:42:45 +00:00
struct TeslaMissile
{
2022-09-29 12:24:26 +00:00
float offset ; // offset
2021-12-29 21:56:21 +00:00
int id ; // id
int ammouse ; // ammo use
int sound ; // sound
int light ; // light
int flash ; // weapon flash
2019-09-19 22:42:45 +00:00
} ;
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void FireTesla ( int nTrigger , PLAYER * pPlayer )
{
TeslaMissile teslaMissile [ 6 ] =
{
{ 0 , 306 , 1 , 470 , 20 , 1 } ,
2022-09-29 12:24:26 +00:00
{ - 8.75f , 306 , 1 , 470 , 30 , 1 } ,
{ 8.75f , 306 , 1 , 470 , 30 , 1 } ,
2021-12-29 21:56:21 +00:00
{ 0 , 302 , 35 , 471 , 40 , 1 } ,
2022-09-29 12:24:26 +00:00
{ - 8.75f , 302 , 35 , 471 , 50 , 1 } ,
{ 8.75f , 302 , 35 , 471 , 50 , 1 } ,
2021-12-29 21:56:21 +00:00
} ;
if ( nTrigger > 0 & & nTrigger < = 6 )
{
nTrigger - - ;
auto plActor = pPlayer - > actor ;
TeslaMissile * pMissile = & teslaMissile [ nTrigger ] ;
if ( ! checkAmmo2 ( pPlayer , 7 , pMissile - > ammouse ) )
{
pMissile = & teslaMissile [ 0 ] ;
if ( ! checkAmmo2 ( pPlayer , 7 , pMissile - > ammouse ) )
{
pPlayer - > weaponState = - 1 ;
SetQAV ( pPlayer , kQAVSGUNIDL2 ) ;
pPlayer - > flashEffect = 0 ;
return ;
}
}
2023-09-28 09:43:14 +00:00
playerFireMissile ( pPlayer , pMissile - > offset , pPlayer - > aim , pMissile - > id ) ;
2022-05-05 23:40:27 +00:00
UseAmmo ( pPlayer , pPlayer - > weaponAmmo , pMissile - > ammouse ) ;
2021-12-29 21:56:21 +00:00
sfxPlay3DSound ( pPlayer - > actor , pMissile - > sound , 1 , 0 ) ;
pPlayer - > visibility = pMissile - > light ;
pPlayer - > flashEffect = pMissile - > flash ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void AltFireTesla ( int , PLAYER * pPlayer )
2019-09-19 22:42:45 +00:00
{
2021-12-29 21:56:21 +00:00
auto plActor = pPlayer - > actor ;
2023-09-28 09:43:14 +00:00
playerFireMissile ( pPlayer , 0. , pPlayer - > aim , kMissileTeslaAlt ) ;
2021-12-29 21:56:21 +00:00
UseAmmo ( pPlayer , pPlayer - > weaponAmmo , 35 ) ;
sfxPlay3DSound ( pPlayer - > actor , 471 , 2 , 0 ) ;
pPlayer - > visibility = 40 ;
pPlayer - > flashEffect = 1 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void FireNapalm ( int nTrigger , PLAYER * pPlayer )
{
auto plActor = pPlayer - > actor ;
2022-09-28 16:45:40 +00:00
double offset = 0 ;
2021-12-29 21:56:21 +00:00
switch ( nTrigger )
{
case 2 :
2022-09-28 16:45:40 +00:00
offset = - 3.125 ;
2021-12-29 21:56:21 +00:00
break ;
case 3 :
2022-09-28 16:45:40 +00:00
offset = 3.125 ;
2021-12-29 21:56:21 +00:00
break ;
}
2023-09-28 09:43:14 +00:00
playerFireMissile ( pPlayer , offset , pPlayer - > aim , kMissileFireballNapalm ) ;
2021-12-29 21:56:21 +00:00
sfxPlay3DSound ( pPlayer - > actor , 480 , 2 , 0 ) ;
UseAmmo ( pPlayer , 4 , 1 ) ;
pPlayer - > flashEffect = 1 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
void FireNapalm2 ( int , PLAYER * pPlayer )
2019-09-19 22:42:45 +00:00
{
2021-12-29 21:56:21 +00:00
auto plActor = pPlayer - > actor ;
2023-09-28 09:43:14 +00:00
playerFireMissile ( pPlayer , - 7.5 , pPlayer - > aim , kMissileFireballNapalm ) ;
playerFireMissile ( pPlayer , 7.5 , pPlayer - > aim , kMissileFireballNapalm ) ;
2021-12-29 21:56:21 +00:00
sfxPlay3DSound ( pPlayer - > actor , 480 , 2 , 0 ) ;
UseAmmo ( pPlayer , 4 , 2 ) ;
pPlayer - > flashEffect = 1 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void AltFireNapalm ( int , PLAYER * pPlayer )
{
2022-09-29 10:53:11 +00:00
auto missile = playerFireThing ( pPlayer , 0 , - 4730 / 65536. , kThingNapalmBall , 18.13333 ) ;
2021-12-29 21:56:21 +00:00
if ( missile )
{
missile - > xspr . data4 = ClipHigh ( pPlayer - > ammoCount [ 4 ] , 12 ) ;
UseAmmo ( pPlayer , 4 , missile - > xspr . data4 ) ;
seqSpawn ( 22 , missile , - 1 ) ;
actBurnSprite ( pPlayer - > actor , missile , 600 ) ;
evPostActor ( missile , 0 , kCallbackFXFlameLick ) ;
sfxPlay3DSound ( missile , 480 , 2 , 0 ) ;
pPlayer - > visibility = 30 ;
pPlayer - > flashEffect = 1 ;
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void FireLifeLeech ( int nTrigger , PLAYER * pPlayer )
{
if ( ! CheckAmmo ( pPlayer , 8 , 1 ) )
return ;
2022-09-28 16:45:40 +00:00
double r1 = Random2F ( 2000 , 14 ) ;
double r2 = Random2F ( 2000 , 14 ) ;
double r3 = Random2F ( 1000 , 14 ) ;
2021-12-29 21:56:21 +00:00
DBloodActor * actor = pPlayer - > actor ;
2023-09-28 09:43:14 +00:00
auto missileActor = playerFireMissile ( pPlayer , 0 , pPlayer - > aim + DVector3 ( r1 , r2 , r3 ) , 315 ) ;
2021-12-29 21:56:21 +00:00
if ( missileActor )
{
missileActor - > SetTarget ( pPlayer - > aimTarget ) ;
2022-11-25 12:13:50 +00:00
missileActor - > spr . Angles . Yaw = ( ( nTrigger = = 2 ) ? DAngle180 : nullAngle ) ;
2021-12-29 21:56:21 +00:00
}
if ( checkAmmo2 ( pPlayer , 8 , 1 ) )
UseAmmo ( pPlayer , 8 , 1 ) ;
else
actDamageSprite ( actor , actor , kDamageSpirit , 16 ) ;
pPlayer - > visibility = ClipHigh ( pPlayer - > visibility + 5 , 50 ) ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void AltFireLifeLeech ( int , PLAYER * pPlayer )
{
DBloodActor * actor = pPlayer - > actor ;
sfxPlay3DSound ( pPlayer - > actor , 455 , 2 , 0 ) ;
2022-09-29 10:53:11 +00:00
auto missile = playerFireThing ( pPlayer , 0 , - 4730 / 65536. , kThingDroppedLifeLeech , 1.6 ) ;
2021-12-29 21:56:21 +00:00
if ( missile )
{
missile - > spr . cstat | = CSTAT_SPRITE_BLOOD_BIT1 ;
missile - > xspr . Push = 1 ;
missile - > xspr . Proximity = 1 ;
missile - > xspr . DudeLockout = 1 ;
missile - > xspr . stateTimer = 1 ;
evPostActor ( missile , 120 , kCallbackLeechStateTimer ) ;
if ( gGameOptions . nGameType < = 1 )
{
int nAmmo = pPlayer - > ammoCount [ 8 ] ;
if ( nAmmo < 25 & & pPlayer - > actor - > xspr . health > unsigned ( ( 25 - nAmmo ) < < 4 ) )
{
actDamageSprite ( actor , actor , kDamageSpirit , ( ( 25 - nAmmo ) < < 4 ) ) ;
nAmmo = 25 ;
}
missile - > xspr . data3 = nAmmo ;
UseAmmo ( pPlayer , 8 , nAmmo ) ;
}
else
{
missile - > xspr . data3 = pPlayer - > ammoCount [ 8 ] ;
pPlayer - > ammoCount [ 8 ] = 0 ;
}
2022-01-12 11:22:48 +00:00
pPlayer - > hasWeapon [ kWeapLifeLeech ] = 0 ;
2021-12-29 21:56:21 +00:00
}
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void FireBeast ( int , PLAYER * pPlayer )
2019-09-19 22:42:45 +00:00
{
2021-12-29 21:56:21 +00:00
DBloodActor * actor = pPlayer - > actor ;
2022-09-28 16:45:40 +00:00
double r1 = Random2F ( 2000 , 14 ) ;
double r2 = Random2F ( 2000 , 14 ) ;
double r3 = Random2F ( 2000 , 14 ) ;
2023-09-28 09:43:14 +00:00
actFireVector ( actor , 0 , pPlayer - > zWeapon - pPlayer - > actor - > spr . pos . Z , pPlayer - > aim + DVector3 ( r1 , r2 , r3 ) , kVectorBeastSlash ) ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static const uint8_t gWeaponUpgrade [ ] [ 13 ] = {
{ 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 } ,
{ 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 } ,
{ 0 , 0 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ 0 , 0 , 1 , 1 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ 0 , 0 , 1 , 1 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 } ,
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 } ,
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 } ,
{ 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 } ,
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 } ,
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } ,
2019-09-19 22:42:45 +00:00
} ;
2021-12-29 21:56:21 +00:00
int WeaponUpgrade ( PLAYER * pPlayer , int newWeapon )
2019-09-19 22:42:45 +00:00
{
2022-11-12 08:33:33 +00:00
int weaponswitch = WeaponSwitch ( pPlayer - gPlayer ) ;
2021-12-29 21:56:21 +00:00
int weapon = pPlayer - > curWeapon ;
2022-11-12 08:33:33 +00:00
if ( ! checkLitSprayOrTNT ( pPlayer ) & & ( weaponswitch & 1 ) & & ( gWeaponUpgrade [ pPlayer - > curWeapon ] [ newWeapon ] | | ( weaponswitch & 2 ) ) )
2021-12-29 21:56:21 +00:00
weapon = newWeapon ;
return weapon ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static const int OrderNext [ ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 1 , 1 } ;
static const int OrderPrev [ ] = { 12 , 12 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 1 } ;
static int WeaponFindNext ( PLAYER * pPlayer , int * a2 , int bDir )
{
int weapon = pPlayer - > curWeapon ;
do
{
if ( bDir )
weapon = OrderNext [ weapon ] ;
else
weapon = OrderPrev [ weapon ] ;
if ( weaponModes [ weapon ] . update & & pPlayer - > hasWeapon [ weapon ] )
{
if ( weapon = = kWeapLifeLeech )
{
if ( CheckAmmo ( pPlayer , weaponModes [ weapon ] . ammoType , 1 ) )
break ;
}
else
{
if ( checkAmmo2 ( pPlayer , weaponModes [ weapon ] . ammoType , 1 ) )
break ;
}
}
} while ( weapon ! = pPlayer - > curWeapon ) ;
if ( weapon = = pPlayer - > curWeapon )
{
if ( ! weaponModes [ weapon ] . update | | ! CheckAmmo ( pPlayer , weaponModes [ weapon ] . ammoType , 1 ) )
weapon = kWeapPitchFork ;
}
if ( a2 )
* a2 = 0 ;
return weapon ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static int WeaponFindLoaded ( PLAYER * pPlayer , int * a2 )
{
int v4 = 1 ;
int v14 = 0 ;
if ( weaponModes [ pPlayer - > curWeapon ] . update > 1 )
{
for ( int i = 0 ; i < weaponModes [ pPlayer - > curWeapon ] . update ; i + + )
{
if ( CheckAmmo ( pPlayer , weaponModes [ pPlayer - > curWeapon ] . ammoType , 1 ) )
{
v14 = i ;
v4 = pPlayer - > curWeapon ;
break ;
}
}
}
if ( v4 = = kWeapPitchFork )
{
int vc = 0 ;
for ( int i = 0 ; i < 14 ; i + + )
{
int weapon = pPlayer - > weaponOrder [ vc ] [ i ] ;
if ( pPlayer - > hasWeapon [ weapon ] )
{
for ( int j = 0 ; j < weaponModes [ weapon ] . update ; j + + )
{
if ( CheckWeaponAmmo ( pPlayer , weapon , weaponModes [ weapon ] . ammoType , 1 ) )
{
if ( a2 )
* a2 = j ;
return weapon ;
}
}
}
}
}
2022-05-05 23:40:27 +00:00
if ( a2 )
2021-12-29 21:56:21 +00:00
* a2 = v14 ;
return v4 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int processSprayCan ( PLAYER * pPlayer )
{
2023-01-02 08:33:51 +00:00
const char bUseShootAsThrow = ! VanillaMode ( ) & & ( pPlayer - > input . actions & SB_FIRE ) ;
2021-12-29 21:56:21 +00:00
switch ( pPlayer - > weaponState )
{
case 5 :
2022-09-17 05:56:11 +00:00
if ( ! ( pPlayer - > input . actions & SB_ALTFIRE ) | | bUseShootAsThrow )
2021-12-29 21:56:21 +00:00
pPlayer - > weaponState = 6 ;
return 1 ;
case 6 :
2022-09-17 05:56:11 +00:00
if ( ( pPlayer - > input . actions & SB_ALTFIRE ) & & ! bUseShootAsThrow )
2021-12-29 21:56:21 +00:00
{
pPlayer - > weaponState = 3 ;
pPlayer - > fuseTime = pPlayer - > weaponTimer ;
StartQAV ( pPlayer , kQAVCANDROP , nClientDropCan ) ;
}
else if ( pPlayer - > input . actions & SB_FIRE )
{
pPlayer - > weaponState = 7 ;
pPlayer - > fuseTime = 0 ;
pPlayer - > throwTime = PlayClock ;
}
return 1 ;
case 7 :
{
2022-09-29 11:17:27 +00:00
setThrowPower ( pPlayer ) ;
2021-12-29 21:56:21 +00:00
if ( ! ( pPlayer - > input . actions & SB_FIRE ) )
{
if ( ! pPlayer - > fuseTime )
pPlayer - > fuseTime = pPlayer - > weaponTimer ;
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVCANTHRO , nClientThrowCan ) ;
}
return 1 ;
}
}
return 0 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool processTNT ( PLAYER * pPlayer )
{
2023-01-02 08:33:51 +00:00
const char bUseShootAsThrow = ! VanillaMode ( ) & & ( pPlayer - > input . actions & SB_FIRE ) ;
2021-12-29 21:56:21 +00:00
switch ( pPlayer - > weaponState )
{
case 4 :
2022-09-17 05:56:11 +00:00
if ( ! ( pPlayer - > input . actions & SB_ALTFIRE ) | | bUseShootAsThrow )
2021-12-29 21:56:21 +00:00
pPlayer - > weaponState = 5 ;
return 1 ;
case 5 :
2022-09-17 05:56:11 +00:00
if ( ( pPlayer - > input . actions & SB_ALTFIRE ) & & ! bUseShootAsThrow )
2021-12-29 21:56:21 +00:00
{
pPlayer - > weaponState = 1 ;
pPlayer - > fuseTime = pPlayer - > weaponTimer ;
StartQAV ( pPlayer , kQAVBUNDROP , nClientDropBundle ) ;
}
else if ( pPlayer - > input . actions & SB_FIRE )
{
pPlayer - > weaponState = 6 ;
pPlayer - > fuseTime = 0 ;
pPlayer - > throwTime = PlayClock ;
}
return 1 ;
case 6 :
{
2022-09-29 11:17:27 +00:00
setThrowPower ( pPlayer ) ;
2021-12-29 21:56:21 +00:00
if ( ! ( pPlayer - > input . actions & SB_FIRE ) )
{
if ( ! pPlayer - > fuseTime )
pPlayer - > fuseTime = pPlayer - > weaponTimer ;
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVBUNTHRO , nClientThrowBundle ) ;
}
return 1 ;
}
}
return 0 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool processProxy ( PLAYER * pPlayer )
{
switch ( pPlayer - > weaponState )
{
case 9 :
2022-09-29 11:17:27 +00:00
setThrowPower ( pPlayer ) ;
2021-12-29 21:56:21 +00:00
pPlayer - > weaponTimer = 0 ;
pPlayer - > qavTimer = 0 ;
if ( ! ( pPlayer - > input . actions & SB_FIRE ) )
{
pPlayer - > weaponState = 8 ;
StartQAV ( pPlayer , kQAVPROXTHRO , nClientThrowProx ) ;
}
2022-05-05 23:40:27 +00:00
return true ;
2021-12-29 21:56:21 +00:00
}
2022-05-05 23:40:27 +00:00
return false ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool processRemote ( PLAYER * pPlayer )
{
switch ( pPlayer - > weaponState )
{
case 13 :
2022-09-29 11:17:27 +00:00
setThrowPower ( pPlayer ) ;
2021-12-29 21:56:21 +00:00
if ( ! ( pPlayer - > input . actions & SB_FIRE ) )
{
pPlayer - > weaponState = 11 ;
StartQAV ( pPlayer , kQAVREMTHRO , nClientThrowRemote ) ;
}
2022-05-05 23:40:27 +00:00
return true ;
2021-12-29 21:56:21 +00:00
}
2022-05-05 23:40:27 +00:00
return false ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool processLeech ( PLAYER * pPlayer )
{
switch ( pPlayer - > weaponState )
{
case 4 :
pPlayer - > weaponState = 6 ;
StartQAV ( pPlayer , kQAVSTAFIRE1 , nClientFireLifeLeech , 1 ) ;
return 1 ;
case 6 :
if ( ! ( pPlayer - > input . actions & SB_ALTFIRE ) )
{
pPlayer - > weaponState = 2 ;
StartQAV ( pPlayer , kQAVSTAFPOST ) ;
return 1 ;
}
break ;
case 8 :
pPlayer - > weaponState = 2 ;
StartQAV ( pPlayer , kQAVSTAFPOST ) ;
return 1 ;
}
return 0 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool processTesla ( PLAYER * pPlayer )
{
switch ( pPlayer - > weaponState )
{
case 4 :
pPlayer - > weaponState = 5 ;
if ( checkAmmo2 ( pPlayer , 7 , 10 ) & & powerupCheck ( pPlayer , kPwUpTwoGuns ) )
StartQAV ( pPlayer , kQAV2SGUNFIR , nClientFireTesla , 1 ) ;
else
StartQAV ( pPlayer , kQAVSGUNFIR1 , nClientFireTesla , 1 ) ;
return 1 ;
case 5 :
if ( ! ( pPlayer - > input . actions & SB_FIRE ) )
{
pPlayer - > weaponState = 2 ;
if ( checkAmmo2 ( pPlayer , 7 , 10 ) & & powerupCheck ( pPlayer , kPwUpTwoGuns ) )
StartQAV ( pPlayer , kQAV2SGUNPST ) ;
else
StartQAV ( pPlayer , kQAVSGUNPOST ) ;
return 1 ;
}
break ;
case 7 :
pPlayer - > weaponState = 2 ;
if ( checkAmmo2 ( pPlayer , 7 , 10 ) & & powerupCheck ( pPlayer , kPwUpTwoGuns ) )
StartQAV ( pPlayer , kQAV2SGUNPST ) ;
else
StartQAV ( pPlayer , kQAVSGUNPOST ) ;
return 1 ;
}
return 0 ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void WeaponProcess ( PLAYER * pPlayer ) {
pPlayer - > flashEffect = ClipLow ( pPlayer - > flashEffect - 1 , 0 ) ;
# ifdef NOONE_EXTENSIONS
if ( gPlayerCtrl [ pPlayer - > nPlayer ] . qavScene . initiator ! = nullptr & & pPlayer - > actor - > xspr . health > 0 ) {
playerQavSceneProcess ( pPlayer , & gPlayerCtrl [ pPlayer - > nPlayer ] . qavScene ) ;
UpdateAimVector ( pPlayer ) ;
return ;
}
# endif
2023-03-22 07:16:32 +00:00
int newweap = pPlayer - > input . getNewWeapon ( ) ;
if ( newweap > 0 & & newweap < = WeaponSel_MaxBlood ) pPlayer - > newWeapon = newweap ;
2021-12-29 21:56:21 +00:00
if ( pPlayer - > actor - > xspr . health = = 0 )
{
pPlayer - > qavLoop = 0 ;
sfxKill3DSound ( pPlayer - > actor , 1 , - 1 ) ;
}
if ( pPlayer - > isUnderwater & & BannedUnderwater ( pPlayer - > curWeapon ) )
{
2022-05-05 23:16:10 +00:00
if ( checkLitSprayOrTNT ( pPlayer ) )
2021-12-29 21:56:21 +00:00
{
if ( pPlayer - > curWeapon = = kWeapSpraycan )
{
pPlayer - > fuseTime = pPlayer - > weaponTimer ;
DropCan ( 1 , pPlayer ) ;
pPlayer - > weaponState = 3 ;
}
else if ( pPlayer - > curWeapon = = kWeapDynamite )
{
pPlayer - > fuseTime = pPlayer - > weaponTimer ;
DropBundle ( 1 , pPlayer ) ;
2023-03-16 04:50:52 +00:00
pPlayer - > weaponState = 3 ;
2021-12-29 21:56:21 +00:00
}
}
WeaponLower ( pPlayer ) ;
pPlayer - > throwPower = 0 ;
}
WeaponPlay ( pPlayer ) ;
UpdateAimVector ( pPlayer ) ;
pPlayer - > weaponTimer - = 4 ;
bool bShoot = pPlayer - > input . actions & SB_FIRE ;
bool bShoot2 = pPlayer - > input . actions & SB_ALTFIRE ;
const int prevNewWeaponVal = pPlayer - > input . getNewWeapon ( ) ; // used to fix scroll issue for banned weapons
if ( ( bShoot | | bShoot2 | | prevNewWeaponVal ) & & pPlayer - > weaponQav = = qavGetCorrectID ( kQAVVDIDLE2 ) ) pPlayer - > weaponTimer = 0 ;
if ( pPlayer - > qavLoop & & pPlayer - > actor - > xspr . health > 0 )
{
if ( bShoot & & CheckAmmo ( pPlayer , pPlayer - > weaponAmmo , 1 ) )
{
auto pQAV = getQAV ( pPlayer - > weaponQav ) ;
while ( pPlayer - > weaponTimer < = 0 )
{
pPlayer - > weaponTimer + = pQAV - > duration ;
pPlayer - > qavTimer + = pQAV - > duration ;
}
}
else
{
pPlayer - > weaponTimer = 0 ;
pPlayer - > qavTimer = 0 ;
pPlayer - > qavLoop = 0 ;
}
return ;
}
pPlayer - > weaponTimer = ClipLow ( pPlayer - > weaponTimer , 0 ) ;
switch ( pPlayer - > curWeapon )
{
case kWeapSpraycan :
if ( processSprayCan ( pPlayer ) )
return ;
break ;
case kWeapDynamite :
if ( processTNT ( pPlayer ) )
return ;
break ;
case kWeapProximity :
if ( processProxy ( pPlayer ) )
return ;
break ;
case kWeapRemote :
if ( processRemote ( pPlayer ) )
return ;
break ;
}
if ( pPlayer - > weaponTimer > 0 )
return ;
if ( pPlayer - > actor - > xspr . health = = 0 | | pPlayer - > curWeapon = = kWeapNone )
pPlayer - > weaponQav = kQAVNone ;
switch ( pPlayer - > curWeapon )
{
case kWeapLifeLeech :
if ( processLeech ( pPlayer ) )
return ;
break ;
case kWeapTeslaCannon :
if ( processTesla ( pPlayer ) )
return ;
break ;
}
if ( VanillaMode ( ) )
{
if ( pPlayer - > nextWeapon )
{
sfxKill3DSound ( pPlayer - > actor , - 1 , 441 ) ;
pPlayer - > weaponState = 0 ;
pPlayer - > newWeapon = pPlayer - > nextWeapon ;
pPlayer - > nextWeapon = kWeapNone ;
}
}
if ( pPlayer - > input . getNewWeapon ( ) = = WeaponSel_Next )
{
pPlayer - > input . setNewWeapon ( kWeapNone ) ;
if ( VanillaMode ( ) )
{
pPlayer - > weaponState = 0 ;
}
pPlayer - > nextWeapon = kWeapNone ;
int t ;
int weapon = WeaponFindNext ( pPlayer , & t , 1 ) ;
pPlayer - > weaponMode [ weapon ] = t ;
if ( VanillaMode ( ) )
{
if ( pPlayer - > curWeapon )
{
WeaponLower ( pPlayer ) ;
pPlayer - > nextWeapon = weapon ;
return ;
}
}
pPlayer - > newWeapon = weapon ;
}
else if ( pPlayer - > input . getNewWeapon ( ) = = WeaponSel_Prev )
{
pPlayer - > input . setNewWeapon ( kWeapNone ) ;
if ( VanillaMode ( ) )
{
pPlayer - > weaponState = 0 ;
}
pPlayer - > nextWeapon = kWeapNone ;
int t ;
int weapon = WeaponFindNext ( pPlayer , & t , 0 ) ;
pPlayer - > weaponMode [ weapon ] = t ;
if ( VanillaMode ( ) )
{
if ( pPlayer - > curWeapon )
{
WeaponLower ( pPlayer ) ;
pPlayer - > nextWeapon = weapon ;
return ;
}
}
pPlayer - > newWeapon = weapon ;
}
else if ( pPlayer - > input . getNewWeapon ( ) = = WeaponSel_Alt )
{
int weapon ;
switch ( pPlayer - > curWeapon )
{
case kWeapDynamite :
weapon = kWeapProximity ;
break ;
case kWeapProximity :
weapon = kWeapRemote ;
break ;
case kWeapRemote :
weapon = kWeapDynamite ;
break ;
default :
return ;
}
pPlayer - > input . setNewWeapon ( kWeapNone ) ;
pPlayer - > weaponState = 0 ;
pPlayer - > nextWeapon = kWeapNone ;
int t = 0 ;
pPlayer - > weaponMode [ weapon ] = t ;
if ( pPlayer - > curWeapon )
{
WeaponLower ( pPlayer ) ;
pPlayer - > nextWeapon = weapon ;
return ;
}
pPlayer - > newWeapon = weapon ;
}
if ( ! VanillaMode ( ) )
{
if ( pPlayer - > nextWeapon )
{
sfxKill3DSound ( pPlayer - > actor , - 1 , 441 ) ;
pPlayer - > newWeapon = pPlayer - > nextWeapon ;
pPlayer - > nextWeapon = kWeapNone ;
}
}
if ( pPlayer - > weaponState = = - 1 )
{
pPlayer - > weaponState = 0 ;
int t ;
int weapon = WeaponFindLoaded ( pPlayer , & t ) ;
pPlayer - > weaponMode [ weapon ] = t ;
if ( pPlayer - > curWeapon )
{
WeaponLower ( pPlayer ) ;
pPlayer - > nextWeapon = weapon ;
return ;
}
pPlayer - > newWeapon = weapon ;
}
if ( pPlayer - > newWeapon )
{
2022-05-05 23:16:10 +00:00
if ( pPlayer - > isUnderwater & & BannedUnderwater ( pPlayer - > newWeapon ) & & ! checkLitSprayOrTNT ( pPlayer ) & & ! VanillaMode ( ) ) // skip banned weapons when underwater and using next/prev weapon key inputs
2021-12-29 21:56:21 +00:00
{
if ( prevNewWeaponVal = = WeaponSel_Next | | prevNewWeaponVal = = WeaponSel_Prev ) // if player switched weapons
{
int saveweapon = pPlayer - > curWeapon ;
pPlayer - > curWeapon = pPlayer - > newWeapon ; // set current banned weapon to curweapon so WeaponFindNext() can find the next weapon
for ( int i = 0 ; i < 3 ; i + + ) // attempt twice to find a new weapon
{
pPlayer - > curWeapon = WeaponFindNext ( pPlayer , NULL , ( char ) ( prevNewWeaponVal = = WeaponSel_Next ) ) ;
if ( ! BannedUnderwater ( pPlayer - > curWeapon ) ) // if new weapon is not a banned weapon, set to new current weapon
{
pPlayer - > newWeapon = pPlayer - > curWeapon ;
pPlayer - > weaponMode [ pPlayer - > newWeapon ] = 0 ;
break ;
}
}
pPlayer - > curWeapon = saveweapon ;
}
}
if ( pPlayer - > newWeapon = = kWeapDynamite )
{
if ( pPlayer - > curWeapon = = kWeapDynamite )
{
if ( checkAmmo2 ( pPlayer , 10 , 1 ) )
pPlayer - > newWeapon = kWeapProximity ;
else if ( checkAmmo2 ( pPlayer , 11 , 1 ) )
pPlayer - > newWeapon = kWeapRemote ;
}
else if ( pPlayer - > curWeapon = = kWeapProximity )
{
if ( checkAmmo2 ( pPlayer , 11 , 1 ) )
pPlayer - > newWeapon = kWeapRemote ;
else if ( checkAmmo2 ( pPlayer , 5 , 1 ) & & pPlayer - > isUnderwater = = 0 )
pPlayer - > newWeapon = kWeapDynamite ;
}
else if ( pPlayer - > curWeapon = = kWeapRemote )
{
if ( checkAmmo2 ( pPlayer , 5 , 1 ) & & pPlayer - > isUnderwater = = 0 )
pPlayer - > newWeapon = kWeapDynamite ;
else if ( checkAmmo2 ( pPlayer , 10 , 1 ) )
pPlayer - > newWeapon = kWeapProximity ;
}
else
{
if ( checkAmmo2 ( pPlayer , 5 , 1 ) & & pPlayer - > isUnderwater = = 0 )
pPlayer - > newWeapon = kWeapDynamite ;
else if ( checkAmmo2 ( pPlayer , 10 , 1 ) )
pPlayer - > newWeapon = kWeapProximity ;
else if ( checkAmmo2 ( pPlayer , 11 , 1 ) )
pPlayer - > newWeapon = kWeapRemote ;
}
}
else if ( ( pPlayer - > newWeapon = = kWeapSpraycan ) & & ! VanillaMode ( ) )
{
if ( ( pPlayer - > curWeapon = = kWeapSpraycan ) & & ( pPlayer - > weaponState = = 2 ) ) // fix spray can state glitch when switching from spray to tnt and back quickly
{
pPlayer - > weaponState = 1 ;
pPlayer - > newWeapon = kWeapNone ;
return ;
}
}
if ( pPlayer - > actor - > xspr . health = = 0 | | pPlayer - > hasWeapon [ pPlayer - > newWeapon ] = = 0 )
{
pPlayer - > newWeapon = kWeapNone ;
return ;
}
2022-05-05 23:16:10 +00:00
if ( pPlayer - > isUnderwater & & BannedUnderwater ( pPlayer - > newWeapon ) & & ! checkLitSprayOrTNT ( pPlayer ) )
2021-12-29 21:56:21 +00:00
{
pPlayer - > newWeapon = kWeapNone ;
return ;
}
int nWeapon = pPlayer - > newWeapon ;
int v4c = weaponModes [ nWeapon ] . update ;
if ( ! pPlayer - > curWeapon )
{
int nAmmoType = weaponModes [ nWeapon ] . ammoType ;
if ( v4c > 1 )
{
if ( CheckAmmo ( pPlayer , nAmmoType , 1 ) | | nAmmoType = = 11 )
WeaponRaise ( pPlayer ) ;
pPlayer - > newWeapon = kWeapNone ;
}
else
{
if ( CheckWeaponAmmo ( pPlayer , nWeapon , nAmmoType , 1 ) )
WeaponRaise ( pPlayer ) ;
else
{
pPlayer - > weaponState = 0 ;
int t ;
int weapon = WeaponFindLoaded ( pPlayer , & t ) ;
pPlayer - > weaponMode [ weapon ] = t ;
if ( pPlayer - > curWeapon )
{
WeaponLower ( pPlayer ) ;
pPlayer - > nextWeapon = weapon ;
return ;
}
pPlayer - > newWeapon = weapon ;
}
}
return ;
}
if ( nWeapon = = pPlayer - > curWeapon & & v4c < = 1 )
{
pPlayer - > newWeapon = kWeapNone ;
return ;
}
int i = 0 ;
if ( nWeapon = = pPlayer - > curWeapon )
i = 1 ;
for ( ; i < = v4c ; i + + )
{
int v6c = ( pPlayer - > weaponMode [ nWeapon ] + i ) % v4c ;
if ( CheckWeaponAmmo ( pPlayer , nWeapon , weaponModes [ nWeapon ] . ammoType , 1 ) )
{
WeaponLower ( pPlayer ) ;
pPlayer - > weaponMode [ nWeapon ] = v6c ;
return ;
}
}
pPlayer - > newWeapon = kWeapNone ;
return ;
}
if ( pPlayer - > curWeapon & & ! CheckAmmo ( pPlayer , pPlayer - > weaponAmmo , 1 ) & & pPlayer - > weaponAmmo ! = 11 )
{
pPlayer - > weaponState = - 1 ;
return ;
}
if ( bShoot )
{
switch ( pPlayer - > curWeapon )
{
case kWeapPitchFork :
StartQAV ( pPlayer , kQAVPFORK , nClientFirePitchfork ) ;
return ;
case kWeapSpraycan :
switch ( pPlayer - > weaponState )
{
case 3 :
pPlayer - > weaponState = 4 ;
StartQAV ( pPlayer , kQAVCANFIRE , nClientFireSpray , 1 ) ;
return ;
}
break ;
case kWeapDynamite :
switch ( pPlayer - > weaponState )
{
case 3 :
pPlayer - > weaponState = 6 ;
pPlayer - > fuseTime = - 1 ;
pPlayer - > throwTime = PlayClock ;
StartQAV ( pPlayer , kQAVBUNFUSE , nClientExplodeBundle ) ;
return ;
}
break ;
case kWeapProximity :
switch ( pPlayer - > weaponState )
{
case 7 :
SetQAV ( pPlayer , kQAVPROXIDLE ) ;
pPlayer - > weaponState = 9 ;
pPlayer - > throwTime = PlayClock ;
return ;
}
break ;
case kWeapRemote :
switch ( pPlayer - > weaponState )
{
case 10 :
SetQAV ( pPlayer , kQAVREMIDLE1 ) ;
pPlayer - > weaponState = 13 ;
pPlayer - > throwTime = PlayClock ;
return ;
case 11 :
pPlayer - > weaponState = 12 ;
StartQAV ( pPlayer , kQAVREMFIRE , nClientFireRemote ) ;
return ;
}
break ;
case kWeapShotgun :
switch ( pPlayer - > weaponState )
{
case 7 :
pPlayer - > weaponState = 6 ;
StartQAV ( pPlayer , kQAV2SHOTF2 , nClientFireShotgun ) ;
return ;
case 3 :
pPlayer - > weaponState = 2 ;
StartQAV ( pPlayer , kQAVSHOTF1 , nClientFireShotgun ) ;
return ;
case 2 :
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVSHOTF2 , nClientFireShotgun ) ;
return ;
}
break ;
case kWeapTommyGun :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & checkAmmo2 ( pPlayer , 3 , 2 ) )
StartQAV ( pPlayer , kQAV2TOMFIRE , nClientFireTommy , 1 ) ;
else
StartQAV ( pPlayer , kQAVTOMFIRE , nClientFireTommy , 1 ) ;
return ;
case kWeapFlareGun :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & checkAmmo2 ( pPlayer , 1 , 2 ) )
StartQAV ( pPlayer , kQAVFLAR2FIR , nClientFireFlare ) ;
else
StartQAV ( pPlayer , kQAVFLARFIR2 , nClientFireFlare ) ;
return ;
case kWeapVoodooDoll :
{
static int nChance [ ] = { 0xa000 , 0xc000 , 0xe000 , 0x10000 } ;
int nRand = wrand ( ) * 2 ;
int i ;
for ( i = 0 ; nChance [ i ] < nRand ; i + + )
{
}
pPlayer - > voodooTarget = pPlayer - > aimTarget ;
if ( pPlayer - > voodooTarget = = nullptr | | pPlayer - > voodooTarget - > spr . statnum ! = kStatDude )
i = 4 ;
StartQAV ( pPlayer , kQAVVDFIRE1 + i , nClientFireVoodoo ) ;
return ;
}
case kWeapTeslaCannon :
switch ( pPlayer - > weaponState )
{
case 2 :
pPlayer - > weaponState = 4 ;
if ( checkAmmo2 ( pPlayer , 7 , 10 ) & & powerupCheck ( pPlayer , kPwUpTwoGuns ) )
StartQAV ( pPlayer , kQAV2SGUNFIR , nClientFireTesla ) ;
else
StartQAV ( pPlayer , kQAVSGUNFIR1 , nClientFireTesla ) ;
return ;
case 5 :
if ( checkAmmo2 ( pPlayer , 7 , 10 ) & & powerupCheck ( pPlayer , kPwUpTwoGuns ) )
StartQAV ( pPlayer , kQAV2SGUNFIR , nClientFireTesla ) ;
else
StartQAV ( pPlayer , kQAVSGUNFIR1 , nClientFireTesla ) ;
return ;
}
break ;
case kWeapNapalm :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) )
StartQAV ( pPlayer , kQAV2NAPFIRE , nClientFireNapalm ) ;
else
StartQAV ( pPlayer , kQAVNAPFIRE , nClientFireNapalm ) ;
return ;
case kWeapLifeLeech :
sfxPlay3DSound ( pPlayer - > actor , 494 , 2 , 0 ) ;
StartQAV ( pPlayer , kQAVSTAFIRE4 , nClientFireLifeLeech ) ;
return ;
case kWeapBeast :
StartQAV ( pPlayer , kQAVBSTATAK1 + Random ( 4 ) , nClientFireBeast ) ;
return ;
}
}
if ( bShoot2 )
{
switch ( pPlayer - > curWeapon )
{
case kWeapPitchFork :
StartQAV ( pPlayer , kQAVPFORK , nClientFirePitchfork ) ;
return ;
case kWeapSpraycan :
switch ( pPlayer - > weaponState )
{
case 3 :
pPlayer - > weaponState = 5 ;
StartQAV ( pPlayer , kQAVCANFIRE2 , nClientExplodeCan ) ;
return ;
}
break ;
case kWeapDynamite :
switch ( pPlayer - > weaponState )
{
case 3 :
pPlayer - > weaponState = 4 ;
StartQAV ( pPlayer , kQAVBUNFUSE , nClientExplodeBundle ) ;
return ;
case 7 :
pPlayer - > weaponState = 8 ;
StartQAV ( pPlayer , kQAVPROXDROP , nClientDropProx ) ;
return ;
case 10 :
pPlayer - > weaponState = 11 ;
StartQAV ( pPlayer , kQAVREMDROP , nClientDropRemote ) ;
return ;
case 11 :
if ( pPlayer - > ammoCount [ 11 ] > 0 )
{
pPlayer - > weaponState = 10 ;
StartQAV ( pPlayer , kQAVREMUP1 ) ;
}
return ;
}
break ;
case kWeapProximity :
switch ( pPlayer - > weaponState )
{
case 7 :
pPlayer - > weaponState = 8 ;
StartQAV ( pPlayer , kQAVPROXDROP , nClientDropProx ) ;
return ;
}
break ;
case kWeapRemote :
switch ( pPlayer - > weaponState )
{
case 10 :
pPlayer - > weaponState = 11 ;
StartQAV ( pPlayer , kQAVREMDROP , nClientDropRemote ) ;
return ;
case 11 :
if ( pPlayer - > ammoCount [ 11 ] > 0 )
{
pPlayer - > weaponState = 10 ;
StartQAV ( pPlayer , kQAVREMUP1 ) ;
}
return ;
}
break ;
case kWeapShotgun :
switch ( pPlayer - > weaponState )
{
case 7 :
pPlayer - > weaponState = 6 ;
StartQAV ( pPlayer , kQAV2SHOTFIR , nClientFireShotgun ) ;
return ;
case 3 :
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVSHOTF3 , nClientFireShotgun ) ;
return ;
case 2 :
pPlayer - > weaponState = 1 ;
StartQAV ( pPlayer , kQAVSHOTF2 , nClientFireShotgun ) ;
return ;
}
break ;
case kWeapTommyGun :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & checkAmmo2 ( pPlayer , 3 , 2 ) )
StartQAV ( pPlayer , kQAV2TOMALT , nClientAltFireSpread2 ) ;
else
StartQAV ( pPlayer , kQAVTOMSPRED , nClientAltFireSpread2 ) ;
return ;
case kWeapVoodooDoll :
sfxPlay3DSound ( pPlayer - > actor , 461 , 2 , 0 ) ;
StartQAV ( pPlayer , kQAVVDSPEL1 , nClientAltFireVoodoo ) ;
return ;
2019-09-19 22:42:45 +00:00
#if 0
2021-12-29 21:56:21 +00:00
case kWeapFlareGun :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & checkAmmo2 ( pPlayer , 1 , 2 ) )
StartQAV ( pPlayer , kQAVFLAR2FIR , nClientFireFlare , 0 ) ;
else
StartQAV ( pPlayer , kQAVFLARFIR2 , nClientFireFlare , 0 ) ;
return ;
2019-09-19 22:42:45 +00:00
# endif
2021-12-29 21:56:21 +00:00
case kWeapTeslaCannon :
if ( checkAmmo2 ( pPlayer , 7 , 35 ) )
{
if ( checkAmmo2 ( pPlayer , 7 , 70 ) & & powerupCheck ( pPlayer , kPwUpTwoGuns ) )
StartQAV ( pPlayer , kQAV2SGUNALT , nClientFireTesla ) ;
else
StartQAV ( pPlayer , kQAVSGUNFIR4 , nClientFireTesla ) ;
}
else
{
if ( checkAmmo2 ( pPlayer , 7 , 10 ) & & powerupCheck ( pPlayer , kPwUpTwoGuns ) )
StartQAV ( pPlayer , kQAV2SGUNFIR , nClientFireTesla ) ;
else
StartQAV ( pPlayer , kQAVSGUNFIR1 , nClientFireTesla ) ;
}
return ;
case kWeapNapalm :
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) )
// by NoOne: allow napalm launcher alt fire act like in v1.0x versions
if ( gGameOptions . weaponsV10x & & ! VanillaMode ( ) ) StartQAV ( pPlayer , kQAV2NAPFIR2 , nClientFireNapalm2 ) ;
else StartQAV ( pPlayer , kQAV2NAPFIRE , nClientAltFireNapalm ) ;
else
StartQAV ( pPlayer , kQAVNAPFIRE , ( gGameOptions . weaponsV10x & & ! VanillaMode ( ) ) ? nClientFireNapalm : nClientAltFireNapalm ) ;
return ;
case kWeapFlareGun :
if ( CheckAmmo ( pPlayer , 1 , 8 ) )
{
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & checkAmmo2 ( pPlayer , 1 , 16 ) )
StartQAV ( pPlayer , kQAVFLAR2FIR , nClientAltFireFlare ) ;
else
StartQAV ( pPlayer , kQAVFLARFIR2 , nClientAltFireFlare ) ;
}
else
{
if ( powerupCheck ( pPlayer , kPwUpTwoGuns ) & & checkAmmo2 ( pPlayer , 1 , 2 ) )
StartQAV ( pPlayer , kQAVFLAR2FIR , nClientFireFlare ) ;
else
StartQAV ( pPlayer , kQAVFLARFIR2 , nClientFireFlare ) ;
}
return ;
case kWeapLifeLeech :
if ( gGameOptions . nGameType < = 1 & & ! checkAmmo2 ( pPlayer , 8 , 1 ) & & pPlayer - > actor - > xspr . health < ( 25 < < 4 ) )
{
sfxPlay3DSound ( pPlayer - > actor , 494 , 2 , 0 ) ;
StartQAV ( pPlayer , kQAVSTAFIRE4 , nClientFireLifeLeech ) ;
}
else
{
StartQAV ( pPlayer , kQAVSTAFDOWN ) ;
AltFireLifeLeech ( 1 , pPlayer ) ;
pPlayer - > weaponState = - 1 ;
}
return ;
}
}
WeaponUpdateState ( pPlayer ) ;
2019-09-19 22:42:45 +00:00
}
2021-12-29 21:56:21 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void teslaHit ( DBloodActor * missileactor , int a2 )
{
2022-08-22 16:20:16 +00:00
auto mpos = missileactor - > spr . pos ;
2021-12-29 21:56:21 +00:00
int nDist = 300 ;
2021-12-30 15:51:56 +00:00
auto pSector = missileactor - > sector ( ) ;
2021-12-29 21:56:21 +00:00
auto owneractor = missileactor - > GetOwner ( ) ;
const bool newSectCheckMethod = ! cl_bloodvanillaexplosions & & ! VanillaMode ( ) ; // use new sector checking logic
2022-08-22 16:20:16 +00:00
auto sectorMap = GetClosestSpriteSectors ( pSector , mpos . XY ( ) , nDist , nullptr , newSectCheckMethod ) ;
2021-12-29 21:56:21 +00:00
bool v4 = true ;
DBloodActor * actor = nullptr ;
actHitcodeToData ( a2 , & gHitInfo , & actor ) ;
if ( a2 = = 3 & & actor & & actor - > spr . statnum = = kStatDude )
v4 = false ;
BloodStatIterator it ( kStatDude ) ;
while ( auto hitactor = it . Next ( ) )
{
if ( hitactor ! = owneractor | | v4 )
{
if ( hitactor - > spr . flags & 32 )
continue ;
2022-08-22 16:23:36 +00:00
if ( CheckSector ( sectorMap , hitactor ) & & CheckProximity ( hitactor , mpos , pSector , nDist ) )
2021-12-29 21:56:21 +00:00
{
2022-09-28 15:31:32 +00:00
int length = int ( ( missileactor - > spr . pos . XY ( ) - hitactor - > spr . pos . XY ( ) ) . Length ( ) ) ;
int nDamage = ClipLow ( ( nDist - length + 20 ) > > 1 , 10 ) ;
2021-12-29 21:56:21 +00:00
if ( hitactor = = owneractor )
nDamage / = 2 ;
actDamageSprite ( owneractor , hitactor , kDamageTesla , nDamage < < 4 ) ;
}
}
}
it . Reset ( kStatThing ) ;
while ( auto hitactor = it . Next ( ) )
{
if ( hitactor - > spr . flags & 32 )
continue ;
2022-08-22 16:23:36 +00:00
if ( CheckSector ( sectorMap , hitactor ) & & CheckProximity ( hitactor , mpos , pSector , nDist ) )
2021-12-29 21:56:21 +00:00
{
if ( ! hitactor - > xspr . locked )
{
2022-09-28 15:31:32 +00:00
int length = int ( ( missileactor - > spr . pos . XY ( ) - hitactor - > spr . pos . XY ( ) ) . Length ( ) ) ;
int nDamage = ClipLow ( nDist - length + 20 , 20 ) ;
2021-12-29 21:56:21 +00:00
actDamageSprite ( owneractor , hitactor , kDamageTesla , nDamage < < 4 ) ;
}
}
}
2019-09-19 22:42:45 +00:00
}
2019-09-22 06:39:22 +00:00
END_BLD_NS