AvHBasePlayerWeapon.cpp

 ifdef AVH_CLIENT
include "cl_dll/wrect.h"
include "cl_dll/cl_dll.h"
include "cl_dll/hud.h"
include "cl_dll/cl_util.h"
include "cl_dll/ammo.h"
include "cl_dll/ammohistory.h"
extern int g_runfuncs;
endif
include "../util/nowarnings.h"
include "AvHBasePlayerWeapon.h"
include "AvHAlienWeaponConstants.h"
include "AvHPlayer.h"
include "../common/usercmd.h"
include "../pm_shared/pm_defs.h"
include "AvHMarineEquipmentConstants.h"
include "AvHMarineWeapons.h"
ifdef AVH_SERVER
include "AvHServerUtil.h"
include "AvHGamerules.h"
extern int gWelderConstEventID;
endif
ifdef AVH_CLIENT
include "cl_dll/com_weapons.h"
endif
include "AvHPlayerUpgrade.h"
include "AvHSharedUtil.h"
include "../types.h"
include "../common/vector_util.h"
include "../util/MathUtil.h"
// extern "C" this guy because delcared in pm_shared.c, not pm_shared.cpp
extern playermove_t* pmove;
extern cvar_t weaponstay;
Vector UTIL_GetRandomSpreadDir(unsigned int inSeed, int inShotNumber, const Vector& inBaseDirection, const Vector& inRight, const Vector& inUp, const Vector& inSpread)
{
// Use player's random seed.
// get circular gaussian spread
float x = UTIL_SharedRandomFloat( inSeed + inShotNumber, -0.5, 0.5 ) + UTIL_SharedRandomFloat( inSeed + ( 1 + inShotNumber ) , -0.5, 0.5 );
float y = UTIL_SharedRandomFloat( inSeed + ( 2 + inShotNumber ), -0.5, 0.5 ) + UTIL_SharedRandomFloat( inSeed + ( 3 + inShotNumber ), -0.5, 0.5 );
float z = x * x + y * y;
Vector theRandomDir = inBaseDirection + x * inSpread.x * inRight + y * inSpread.y * inUp; return theRandomDir;
}
// test
Vector UTIL_GetRandomSpreadDirFrom(unsigned int inSeed, int inShotNumber, const Vector& inBaseDirection, const Vector& inRight, const Vector& inUp, const Vector& inSpread, const Vector& inFromSpread)
{
// Use player's random seed.
// get circular gaussian spread
float x = UTIL_SharedRandomFloat( inSeed + inShotNumber, -0.5, 0.5 ) + UTIL_SharedRandomFloat( inSeed + ( 1 + inShotNumber ) , -0.5, 0.5 );
float y = UTIL_SharedRandomFloat( inSeed + ( 2 + inShotNumber ), -0.5, 0.5 ) + UTIL_SharedRandomFloat( inSeed + ( 3 + inShotNumber ), -0.5, 0.5 );
float z = x * x + y * y;
float xdir = x / fabs(x);
float ydir = y / fabs(y);
Vector theRandomDir = inBaseDirection + inFromSpread.x * inRight * xdir + x * inSpread.x * inRight + inFromSpread.y * inUp * ydir + y * inSpread.y * inUp; return theRandomDir;
}
AvHBasePlayerWeapon::AvHBasePlayerWeapon()
{
// reasonable defaults for everything else
this->mEvent = 0;
this->mWeaponAnimationEvent = 0;
this->mStartEvent = 0;
this->mEndEvent = 0;
this->mRange = 8012;
this->mDamage = 10;
this->mAttackButtonDownLastFrame = false;
this->mTimeOfLastResupply = -1;
this->mTimeOfLastPrime = -1;
this->mWeaponPrimeStarted = false;
ifdef AVH_SERVER
this->mInOverwatch = false; this->mIsPersistent = false; this->mLifetime = -1;
endif
}
void AvHBasePlayerWeapon::PrintWeaponToClient(CBaseEntity *theAvHPlayer) {
char msg[1024];
ItemInfo theItemInfo;
this->GetItemInfo(&theItemInfo);
sprintf(msg, "%s iuser3=%d\tenabled = %d\n", theItemInfo.pszName, this->pev->iuser3, this->m_iEnabled);
ClientPrint(theAvHPlayer->pev, HUD_PRINTNOTIFY, msg);
}
int AvHBasePlayerWeapon::AddToPlayer( CBasePlayer *pPlayer )
{
// Can we predict weapon pick-ups? I bet we can.
int theAddedToPlayer = 0;
ifdef AVH_SERVER
AvHPlayer* inPlayer = dynamic_cast<AvHPlayer*>(pPlayer); ASSERT(inPlayer != NULL); if(this->GetAllowedForUser3(inPlayer->GetUser3())) { // Make sure player doesn't have this weapon already if(!pPlayer->HasItem(this)) { // If weapon was placed by mapper if(this->GetIsPersistent()) { // Create a new weapon and give it to the player pPlayer->GiveNamedItem(STRING(this->pev->classname)); this->DestroyItem(); } else { theAddedToPlayer = CBasePlayerWeapon::AddToPlayer(pPlayer); if(theAddedToPlayer) { // Make sure it's not set for expiration SetThink(NULL); } } } }
endif
return theAddedToPlayer;
}
BOOL AvHBasePlayerWeapon::Deploy()
{
// : 0000938
// removed deploy sounds for all weapons, leaving the sounds to the models
// char* theDeploySound = this->GetDeploySound();
// if(theDeploySound)
// {
// EMIT_SOUND(ENT(this->pev), CHAN_WEAPON, this->GetDeploySound(), this->GetDeploySoundVolume(), ATTN_NORM);
//}
// :
char* theAnimExt = this->GetAnimationExtension(); BOOL theSuccess = DefaultDeploy(this->GetActiveViewModel(), this->GetPlayerModel(), this->GetDeployAnimation(), theAnimExt); // Set a player animatiom here? //this->m_pPlayer->SetAnimation(PLAYER_ANIM(iAnim)); // Set deploy time this->m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + this->GetDeployTime(); this->mTimeOfLastPrime = -1; this->mWeaponPrimeStarted = false; return theSuccess;
}
BOOL AvHBasePlayerWeapon::DefaultDeploy( char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal, int body)
{
if (!CanDeploy( ))
return FALSE;
m_pPlayer->TabulateAmmo(); // This was causing a crash from hl_weapons.cpp only when connected to a dedicated server and switching weapons //#ifdef AVH_SERVER //m_pPlayer->pev->viewmodel = MAKE_STRING(szViewModel); //#endif
ifdef AVH_SERVER
m_pPlayer->pev->viewmodel = MAKE_STRING(szViewModel); m_pPlayer->pev->weaponmodel = MAKE_STRING(szWeaponModel);
else
gEngfuncs.CL_LoadModel( szViewModel, &m_pPlayer->pev->viewmodel ); gEngfuncs.CL_LoadModel( szWeaponModel, &m_pPlayer->pev->weaponmodel );
endif
strcpy( m_pPlayer->m_szAnimExtention, szAnimExt ); //SendWeaponAnim( iAnim, skiplocal, body ); this->SendWeaponAnim(iAnim); // Set the player animation as well //this->m_pPlayer->SetAnimation(PLAYER_ANIM(iAnim)); m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + this->GetDeployTime(); m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + this->GetDeployTime() + kDeployIdleInterval; return TRUE;
}
BOOL AvHBasePlayerWeapon::DefaultReload( int iClipSize, int iAnim, float fDelay, int body)
{
// : 0000996
if (m_fInReload == TRUE)
return TRUE;
// :
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) return FALSE; // Don't reload while we're resupplying if(this->mTimeOfLastResupply > 0) { return FALSE; } int j = min(iClipSize - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]); if (j == 0) return FALSE; m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + fDelay; //!!UNDONE -- reload sound goes here !!! //SendWeaponAnim( iAnim, UseDecrement() ? 1 : 0 ); this->SendWeaponAnim(iAnim); // Send reload to all players. Reloads are initiated server-side, so send down to local client as well this->m_pPlayer->pev->weaponanim = iAnim; this->PlaybackEvent(this->mWeaponAnimationEvent, iAnim, FEV_RELIABLE); // Player model reload animation this->m_pPlayer->SetAnimation(PLAYER_RELOAD); m_fInReload = TRUE; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + kDeployIdleInterval; return TRUE;
}
char* AvHBasePlayerWeapon::GetActiveViewModel() const
{
return this->GetViewModel();
}
//BOOL AvHBasePlayerWeapon::Deploy(char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, float inNextAttackTime, int skiplocal)
//{
// BOOL theSuccess = FALSE;
//
// if(CanDeploy())
// {
// this->m_pPlayer->TabulateAmmo();
// this->m_pPlayer->pev->viewmodel = MAKE_STRING(szViewModel);
// this->m_pPlayer->pev->weaponmodel = MAKE_STRING(szWeaponModel);
// strcpy( m_pPlayer->m_szAnimExtention, szAnimExt );
// SendWeaponAnim( iAnim, skiplocal );
//
// this->m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + inNextAttackTime;
// this->m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.0;
//
// theSuccess = TRUE;
// }
//
// return theSuccess;
//}
char* AvHBasePlayerWeapon::GetAnimationExtension() const
{
char* theAnimExt = NULL;
AvHWeaponID theWeaponID = (AvHWeaponID)this->m_iId; switch(theWeaponID) { case AVH_WEAPON_BITE: case AVH_WEAPON_SPIT: case AVH_WEAPON_SPIKE: case AVH_WEAPON_BITE2: case AVH_WEAPON_SWIPE: case AVH_WEAPON_CLAWS: theAnimExt = "ability1"; break; case AVH_WEAPON_PARASITE: case AVH_WEAPON_HEALINGSPRAY: case AVH_WEAPON_SPORES: case AVH_WEAPON_BLINK: case AVH_WEAPON_STOMP: theAnimExt = "ability2"; break; case AVH_ABILITY_LEAP: case AVH_WEAPON_BILEBOMB: case AVH_WEAPON_UMBRA: case AVH_WEAPON_METABOLIZE: case AVH_WEAPON_DEVOUR: theAnimExt = "ability3"; break; case AVH_WEAPON_DIVINEWIND: case AVH_WEAPON_WEBSPINNER: case AVH_WEAPON_PRIMALSCREAM: case AVH_WEAPON_ACIDROCKET: case AVH_ABILITY_CHARGE: theAnimExt = "ability4"; break; case AVH_WEAPON_KNIFE: theAnimExt = "knife"; break; case AVH_WEAPON_PISTOL: theAnimExt = "pistol"; break; case AVH_WEAPON_MG: theAnimExt = "lmg"; break; case AVH_WEAPON_SONIC: theAnimExt = "shotgun"; break; case AVH_WEAPON_HMG: theAnimExt = "hmg"; break; case AVH_WEAPON_WELDER: theAnimExt = "welder"; break; case AVH_WEAPON_MINE: theAnimExt = "tripmine"; break; case AVH_WEAPON_GRENADE_GUN: theAnimExt = "grenadegun"; break; case AVH_WEAPON_GRENADE: theAnimExt = "handgrenade"; break; default: ASSERT(false); break; } return theAnimExt;
}
int AvHBasePlayerWeapon::GetClipSize() const
{
ItemInfo theItemInfo;
this->GetItemInfo(&theItemInfo);
int theClipSize = theItemInfo.iMaxClip;
return theClipSize;
}
int AvHBasePlayerWeapon::GetPrimaryAmmoAmount() const
{
int theAmmo = 0;
if(this->m_pPlayer && (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > 0)) { theAmmo = this->m_pPlayer->m_rgAmmo[this->m_iPrimaryAmmoType]; } return theAmmo;
}
int AvHBasePlayerWeapon::GetDamageType() const
{
return NS_DMG_NORMAL;
}
char* AvHBasePlayerWeapon::GetDeploySound() const
{
return NULL;
}
float AvHBasePlayerWeapon::GetDeploySoundVolume() const
{
return 1.0f;
}
int AvHBasePlayerWeapon::GetEmptyShootAnimation() const
{
return kShootEmptyAnimation;
}
void AvHBasePlayerWeapon::GetEventOrigin(Vector& outOrigin) const
{
VectorCopy(this->m_pPlayer->pev->origin, outOrigin);
}
void AvHBasePlayerWeapon::GetEventAngles(Vector& outAngles) const
{
outAngles = this->pev->v_angle + this->pev->punchangle;
}
bool AvHBasePlayerWeapon::GetFiresUnderwater() const
{
return false;
}
bool AvHBasePlayerWeapon::GetIsFiring() const
{
return this->mAttackButtonDownLastFrame;
}
bool AvHBasePlayerWeapon::GetHasMuzzleFlash() const
{
return false;
}
bool AvHBasePlayerWeapon::GetIsCapableOfFiring() const
{
return !this->UsesAmmo() || (this->m_iClip > 0);
}
int AvHBasePlayerWeapon::GetDeployAnimation() const
{
return kDeployAnimation;
}
int AvHBasePlayerWeapon::GetIdleAnimation() const
{
int iAnim;
int theRandomNum = UTIL_SharedRandomLong(this->m_pPlayer->random_seed, 0, 1);
switch(theRandomNum) { case 0: iAnim = kIdleAnimationOne; break; default: case 1: iAnim = kIdleAnimationTwo; break; } return iAnim;
}
Vector AvHBasePlayerWeapon::GetProjectileSpread() const
{
return VECTOR_CONE_0DEGREES;
}
float AvHBasePlayerWeapon::ComputeAttackInterval() const
{
return this->GetRateOfFire();
}
float AvHBasePlayerWeapon::GetRateOfFire() const
{
return 1;
}
int AvHBasePlayerWeapon::GetShootAnimation() const
{
return kShootAnimation;
}
int AvHBasePlayerWeapon::GetShotsInClip() const
{
int theShotsInClip = -1;
if(this->UsesAmmo()) { theShotsInClip = this->m_iClip; } return theShotsInClip;
}
bool AvHBasePlayerWeapon::GetIsDroppable() const
{
return true;
}
bool AvHBasePlayerWeapon::GetIsPlayerMoving() const
{
bool thePlayerIsMoving = false;
// float kMovingThresholdVelocity = 100;
// float theCurrentVelocity = 0;
//
// #ifdef AVH_SERVER
// theCurrentVelocity = this->m_pPlayer->pev->velocity.Length();
// #endif
//
// #ifdef AVH_CLIENT
// cl_entity_t* theLocalPlayer = gEngfuncs.GetLocalPlayer();
// if(theLocalPlayer)
// {
// theCurrentVelocity = theLocalPlayer->curstate.velocity.Length();
// }
// #endif
//
// if(theCurrentVelocity > kMovingThresholdVelocity)
// {
// thePlayerIsMoving = true;
// }
return thePlayerIsMoving;
}
int AvHBasePlayerWeapon::GetMaxClipsCouldReceive()
{
int theMaxClips = 0;
ItemInfo theItemInfo; this->GetItemInfo(&theItemInfo); int theClipSize = theItemInfo.iMaxClip; if(theClipSize > 0 && this->UsesAmmo()) { theMaxClips = ((theItemInfo.iMaxAmmo1 - this->m_iClip)/theClipSize) + 1; } return theMaxClips;
}
AvHWeaponID AvHBasePlayerWeapon::GetPreviousWeaponID() const
{
AvHWeaponID theID = AVH_WEAPON_NONE;
// Look at most recently used weapon and see if we can transition from it AvHBasePlayerWeapon* theWeapon = dynamic_cast<AvHBasePlayerWeapon*>(this->m_pPlayer->m_pLastItem); if(theWeapon) { theID = (AvHWeaponID)(theWeapon->m_iId); } return theID;
}
float AvHBasePlayerWeapon::GetRange() const
{
return this->mRange;
}
vec3_t AvHBasePlayerWeapon::GetWorldBarrelPoint() const
{
ASSERT(this->m_pPlayer);
Vector vecAiming = gpGlobals->v_forward; Vector theWorldBarrelPoint = this->m_pPlayer->GetGunPosition() + vecAiming*this->GetBarrelLength(); return theWorldBarrelPoint;
}
char* AvHBasePlayerWeapon::GetPlayerModel() const
{
return kNullModel;
}
char* AvHBasePlayerWeapon::GetPrimeSound() const
{
return NULL;
}
float AvHBasePlayerWeapon::GetPrimeSoundVolume() const
{
return 1.0f;
}
char* AvHBasePlayerWeapon::GetViewModel() const
{
return kNullModel;
}
char* AvHBasePlayerWeapon::GetWorldModel() const
{
return kNullModel;
}
void AvHBasePlayerWeapon::Holster( int skiplocal)
{
CBasePlayerWeapon::Holster(skiplocal);
#ifdef AVH_SERVER this->mInOverwatch = false; #endif
}
float AvHBasePlayerWeapon::GetTimePassedThisTick() const
{
float theClientTimePassedThisTick = (pmove->cmd.msec/1000.0f);
return theClientTimePassedThisTick;
}
void AvHBasePlayerWeapon::ItemPostFrame( void )
{
CBasePlayerWeapon::ItemPostFrame();
float theClientTimePassedThisTick = this->GetTimePassedThisTick(); this->m_flNextPrimaryAttack -= theClientTimePassedThisTick; this->m_flTimeWeaponIdle -= theClientTimePassedThisTick; this->mTimeOfLastResupply -= theClientTimePassedThisTick; this->mTimeOfLastPrime -= theClientTimePassedThisTick;
}
void AvHBasePlayerWeapon::Precache(void)
{
CBasePlayerWeapon::Precache();
char* theDeploySound = this->GetDeploySound(); if(theDeploySound) { PRECACHE_UNMODIFIED_SOUND(theDeploySound); } char* thePrimeSound = this->GetPrimeSound(); if(thePrimeSound) { PRECACHE_UNMODIFIED_SOUND(thePrimeSound); } char* thePlayerModel = this->GetPlayerModel(); if(thePlayerModel) { PRECACHE_UNMODIFIED_MODEL(thePlayerModel); } char* theViewModel = this->GetViewModel(); if(theViewModel) { PRECACHE_UNMODIFIED_MODEL(theViewModel); } char* theWorldModel = this->GetWorldModel(); if(theWorldModel) { PRECACHE_UNMODIFIED_MODEL(theWorldModel); } this->mWeaponAnimationEvent = PRECACHE_EVENT(1, kWeaponAnimationEvent);
}
bool AvHBasePlayerWeapon::ProcessValidAttack(void)
{
bool theAttackIsValid = false;
//#ifdef AVH_CLIENT
// char sz[ 128 ];
// sprintf(sz, "during check valid, clip is %d\n", this->m_iClip);
// gEngfuncs.pfnCenterPrint( sz );
//
// //gEngfuncs.Con_Printf("during idle, clip is %d\n", sz);
//#endif
//#ifdef AVH_CLIENT
// if(gHUD.GetInTopDownMode())
// {
// return false;
// }
//#endif
//
//#ifdef AVH_SERVER
// AvHPlayer* thePlayer = dynamic_cast(this->m_pPlayer);
// if(thePlayer->GetIsInTopDownMode())
// {
// return false;
// }
//#endif
// Only shoot if deployed and enabled (iuser3 is 0 when disabled, 1 when enabled <from m_fireState>) // : 497 call GetEnabledState instead of testing directly int enabledState=this->GetEnabledState(); if(this->m_pPlayer->pev->viewmodel && ( enabledState == 1)) { // don't fire underwater if((this->m_pPlayer->pev->waterlevel == 3) && !this->GetFiresUnderwater()) { this->PlayEmptySound(); //this->m_flNextPrimaryAttack = gpGlobals->time + this->mROF; this->m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + this->ComputeAttackInterval(); } else if(this->UsesAmmo()) { ASSERT(this->m_iPrimaryAmmoType >= 0); if(this->m_iClip > 0) { if(this->m_flNextPrimaryAttack <= 0) { if(!this->GetMustPressTriggerForEachShot() || (!this->mAttackButtonDownLastFrame)) { theAttackIsValid = true; } } } else { // Definitely not firing this pull of the trigger theAttackIsValid = false; BOOL theHasAmmo = 0; if ( pszAmmo1() ) { theHasAmmo |= (this->m_pPlayer->m_rgAmmo[this->m_iPrimaryAmmoType] != 0); } if ( pszAmmo2() ) { theHasAmmo |= (this->m_pPlayer->m_rgAmmo[this->m_iSecondaryAmmoType] != 0); } if (this->m_iClip > 0) { theHasAmmo |= 1; } if(theHasAmmo) { // Trigger reload this->Reload(); } else { this->PlayEmptySound(); this->SendWeaponAnim(this->GetEmptyShootAnimation()); //this->m_pPlayer->SetAnimation(PLAYER_ATTACK1); } } } else { theAttackIsValid = true; } } return theAttackIsValid;
}
bool AvHBasePlayerWeapon::GetIsGunPositionValid() const
{
return true;
}
void AvHBasePlayerWeapon::DeductCostForShot(void)
{
this->m_iClip--;
// On a successful attack, decloak the player if needed #ifdef AVH_SERVER AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(this->m_pPlayer); if(thePlayer) { thePlayer->TriggerUncloak(); } int theResourceCost = this->GetResourceCost(); if(theResourceCost > 0) { float theNewResources = (thePlayer->GetResources(false) - theResourceCost); theNewResources = max(theNewResources, 0.0f); thePlayer->SetResources(theNewResources); } #endif
}
float AvHBasePlayerWeapon::GetReloadTime(void) const
{
// TODO: Allow weapons to have different reload times
return 1.5f;
}
int AvHBasePlayerWeapon::GetReloadAnimation() const
{
return kReloadAnimation;
}
void AvHBasePlayerWeapon::PlaybackEvent(unsigned short inEvent, int inIparam2, int inFlags) const
{
unsigned short theEvent = inEvent;
if(theEvent != 0)
{
// Playback event, sending along enough data so client knows who triggered this event!
int theWeaponIndex = 0;
AvHUser3 theUser3 = AVH_USER3_NONE;
int theUpgrades = 0;
// When predicting weapons, play the event locally, then tell everyone else but us to play it back later int flags = inFlags; edict_t* theEdict; // Pass player random seed to event, so it chooses the right direction for spread int theRandomNumber = this->m_pPlayer->random_seed;
if defined( AVH_CLIENT )
theUser3 = gHUD.GetHUDUser3(); theUpgrades = gHUD.GetHUDUpgrades(); theEdict = NULL;
else
theUser3 = dynamic_cast<AvHPlayer*>(this->m_pPlayer)->GetUser3(); theUpgrades = this->m_pPlayer->pev->iuser4; theEdict = this->m_pPlayer->edict();
endif
// For bullet spread //theRandomNumber = UTIL_SharedRandomLong(this->m_pPlayer->random_seed, 1, kBulletSpreadGranularity*kBulletSpreadGranularity); // When in overwatch, the weapon is fired on the server, so the client firing the weapon won't be firing it locally first
if defined(AVH_SERVER)
if(this->mInOverwatch) { flags = 0; }
endif
// Allow weapon to specify some parameters, so they are available on both client and server Vector theEventOrigin; this->GetEventOrigin(theEventOrigin); Vector theEventAngles; this->GetEventAngles(theEventAngles); float theVolume = AvHPlayerUpgrade::GetSilenceVolumeLevel(theUser3, theUpgrades); //( int flags, const edict_t *pInvoker, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 ); PLAYBACK_EVENT_FULL(flags, this->m_pPlayer->edict(), theEvent, 0, (float *)&theEventOrigin, (float *)&theEventAngles, theVolume, 0.0, theRandomNumber, inIparam2, 0, 0 ); }
}
void AvHBasePlayerWeapon::SetAnimationAndSound(void)
{
this->m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
this->m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
// player "shoot" animation //SendWeaponAnim(this->GetShootAnimation()); this->m_pPlayer->SetAnimation(PLAYER_ATTACK1); if(this->GetHasMuzzleFlash()) { this->m_pPlayer->pev->effects = (int)(this->m_pPlayer->pev->effects) | EF_MUZZLEFLASH; }
}
void AvHBasePlayerWeapon::FireProjectiles(void)
{
Vector vecSrc = this->m_pPlayer->GetGunPosition();
Vector vecAiming = this->m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
// Fire the bullets and apply damage int theRange = this->mRange; float theDamage = this->mDamage; int theTracerFreq; float theDamageMultiplier; AvHPlayerUpgrade::GetWeaponUpgrade(this->m_pPlayer->pev->iuser3, this->m_pPlayer->pev->iuser4, &theDamageMultiplier, &theTracerFreq); theDamage *= theDamageMultiplier; Vector theSpread = this->GetProjectileSpread(); this->m_pPlayer->FireBulletsPlayer(1, vecSrc, vecAiming, theSpread, theRange, BULLET_PLAYER_MP5, theTracerFreq, theDamage, this->m_pPlayer->pev, this->m_pPlayer->random_seed); this->mWeaponPrimeStarted = false;
}
int AvHBasePlayerWeapon::GetPrimeAnimation() const
{
return -1;
}
float AvHBasePlayerWeapon::GetWeaponPrimeTime() const
{
return -1.0f;
}
void AvHBasePlayerWeapon::PrimeWeapon()
{
float thePrimeTime = this->GetWeaponPrimeTime();
if(thePrimeTime > 0.0f)
{
if(!this->GetIsWeaponPriming())
{
char* thePrimeSound = this->GetPrimeSound();
if(thePrimeSound)
{
EMIT_SOUND(ENT(this->pev), CHAN_WEAPON, thePrimeSound, this->GetPrimeSoundVolume(), ATTN_NORM);
}
this->PlaybackEvent(this->mWeaponAnimationEvent, this->GetPrimeAnimation()); this->mTimeOfLastPrime = UTIL_WeaponTimeBase() + thePrimeTime; this->mWeaponPrimeStarted = true; } }
}
BOOL AvHBasePlayerWeapon::GetIsWeaponPrimed() const
{
return ((this->GetWeaponPrimeTime() > 0.0f) && this->mWeaponPrimeStarted && (UTIL_WeaponTimeBase() > this->mTimeOfLastPrime));
}
BOOL AvHBasePlayerWeapon::GetIsWeaponPriming() const
{
return ((this->GetWeaponPrimeTime() > 0.0f) && this->mWeaponPrimeStarted && (UTIL_WeaponTimeBase() < this->mTimeOfLastPrime));
}
void AvHBasePlayerWeapon::SetNextAttack(void)
{
// this->m_flNextPrimaryAttack += this->mROF;
//
// if(this->m_flNextPrimaryAttack < 0) // this->m_flNextPrimaryAttack = this->mROF;
float theRateOfFire = this->ComputeAttackInterval(); this->m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + theRateOfFire; if(this->m_flNextPrimaryAttack < 0) { this->m_flNextPrimaryAttack = theRateOfFire; } this->SetNextIdle();
}
void AvHBasePlayerWeapon::PrimaryAttack(void)
{
if (this->ProcessValidAttack())
{
if (!this->mAttackButtonDownLastFrame) { this->PlaybackEvent(this->mStartEvent); this->mAttackButtonDownLastFrame = true; } this->PlaybackEvent(this->mEvent, this->GetShootAnimation()); this->SetAnimationAndSound(); // If player is too close to a wall, don't actually fire the projectile if(this->GetIsGunPositionValid()) { this->FireProjectiles(); } else { #ifdef DEBUG #ifdef AVH_SERVER char theMessage[256]; sprintf(theMessage, "Gun position is not valid, skipping call to FireProjectiles.\n"); ALERT(at_console, theMessage); #endif #endif } this->DeductCostForShot(); this->SetNextAttack(); }
}
void AvHBasePlayerWeapon::Reload(void)
{
// Move clip sounds out
int theReloadAnimation = this->GetReloadAnimation();
float theReloadTime = this->GetReloadTime();
int theClipSize = this->GetClipSize();
this->DefaultReload(theClipSize, theReloadAnimation, theReloadTime); // Don't idle for a bit this->SetNextIdle();
}
bool AvHBasePlayerWeapon::GetCanBeResupplied() const
{
bool theCanBeResupplied = false;
if(this->UsesAmmo()) { ItemInfo theItemInfo; this->GetItemInfo(&theItemInfo); int theCurrentPrimary = this->m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]; int theMaxPrimary = theItemInfo.iMaxAmmo1; // Add some to primary store if(theCurrentPrimary < theMaxPrimary) { theCanBeResupplied = true; } } return theCanBeResupplied;
}
bool AvHBasePlayerWeapon::Resupply()
{
bool theResupplied = false;
if(this->GetCanBeResupplied()) { ItemInfo theItemInfo; this->GetItemInfo(&theItemInfo); // Get amount to add int theMaxClip = theItemInfo.iMaxClip; // Add half the clip each time, rounding up (roughly 3 seconds per clip () int theAmountToAdd = max((theMaxClip+1)/2, 1); int theCurrentPrimary = this->m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]; int theMaxPrimary = theItemInfo.iMaxAmmo1; // Add ammo this->m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] = min(theCurrentPrimary + theAmountToAdd, theMaxPrimary); const float theDelay = 1.0f; //bugfix - don't let resupply shorten reload time this->m_pPlayer->m_flNextAttack = max(this->m_pPlayer->m_flNextAttack,UTIL_WeaponTimeBase() + theDelay); this->mTimeOfLastResupply = UTIL_WeaponTimeBase() + theDelay; } return theResupplied;
}
void AvHBasePlayerWeapon::SendWeaponAnim(int inAnimation, int skiplocal, int body)
{
if(inAnimation >= 0)
{
this->m_pPlayer->pev->weaponanim = inAnimation;
this->PlaybackEvent(this->mWeaponAnimationEvent, inAnimation); }
}
void AvHBasePlayerWeapon::SecondaryAttack(void)
{
}
void AvHBasePlayerWeapon::Spawn()
{
CBasePlayerWeapon::Spawn();
this->pev->solid = SOLID_BBOX; this->pev->movetype = MOVETYPE_TOSS; UTIL_SetOrigin(this->pev, this->pev->origin); UTIL_SetSize(this->pev, kMarineItemMinSize, kMarineItemMaxSize); this->pev->iuser3 = AVH_USER3_MARINEITEM; #ifdef AVH_SERVER if(!this->GetIsPersistent()) { this->mLifetime = AvHSUGetWeaponStayTime(); } #endif
}
bool AvHBasePlayerWeapon::GetEnabledState() const
{
bool result=false;
ifdef AVH_SERVER
result= (this->m_iEnabled == 1);
else
// : 497 client now uses the enabled state in the appropriate WEAPON ItemInfo theItemInfo; this->GetItemInfo(&theItemInfo); WEAPON *pWeapon = gWR.GetWeapon( theItemInfo.iId ); if ( pWeapon != 0 ) { result=(pWeapon->iEnabled == 1); }
endif
return result;
}
ifdef AVH_SERVER
void AvHBasePlayerWeapon::VirtualMaterialize(void)
{
int theLifetime = this->GetGroundLifetime();
if(theLifetime >= 0) { SetThink(&AvHBasePlayerWeapon::DestroyItem); this->pev->nextthink = gpGlobals->time + theLifetime; }
}
int AvHBasePlayerWeapon::GetGroundLifetime() const
{
return this->mLifetime;
}
// -1 means never expire
void AvHBasePlayerWeapon::SetGroundLifetime(int inGroundLifetime)
{
this->mLifetime = inGroundLifetime;
}
int AvHBasePlayerWeapon::GetResourceCost() const
{
return 0;
}
void AvHBasePlayerWeapon::VirtualDestroyItem(void)
{
if(this->GetIsPersistent())
{
// Make this weapon invisible until map reset
this->pev->effects |= EF_NODRAW;
this->pev->solid = SOLID_NOT;
this->pev->takedamage = DAMAGE_NO;
SetThink(NULL);
}
else
{
CBasePlayerItem::VirtualDestroyItem();
}
}
void AvHBasePlayerWeapon::ResetEntity()
{
CBasePlayerWeapon::ResetEntity();
this->pev->effects = 0; this->pev->solid = SOLID_BBOX; this->pev->movetype = MOVETYPE_TOSS; this->pev->takedamage = DAMAGE_YES; this->VirtualMaterialize();
}
void AvHBasePlayerWeapon::SetOverwatchState(bool inState)
{
this->mInOverwatch = inState;
}
void AvHBasePlayerWeapon::UpdateInventoryEnabledState(int inNumActiveHives)
{
// Process here
int theEnabledState = 1;
ItemInfo theItemInfo; if(this->GetItemInfo(&theItemInfo) != 0) { int theWeaponFlags = theItemInfo.iFlags; AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(this->m_pPlayer); ASSERT(thePlayer); // If we don't have the hives required, or we're ensnared if (/*thePlayer->GetIsTemporarilyInvulnerable() ||*/ !thePlayer->GetIsAbleToAct() || ((inNumActiveHives < 1) && (theWeaponFlags & ONE_HIVE_REQUIRED)) || ((inNumActiveHives < 2) && (theWeaponFlags & TWO_HIVES_REQUIRED)) || ((inNumActiveHives < 3) && (theWeaponFlags & THREE_HIVES_REQUIRED)) || (this->GetResourceCost() > thePlayer->GetResources(false)) ) { // Disable it theEnabledState = 0; } } // : 497 save the state for when we send the CurWeapon message this->m_iEnabled = theEnabledState;
}
void AvHBasePlayerWeapon::KeyValue(KeyValueData* pkvd)
{
// Any entity placed by the mapper is persistent
this->SetPersistent();
if(FStrEq(pkvd->szKeyName, "teamchoice")) { this->pev->team = (AvHTeamNumber)(atoi(pkvd->szValue)); pkvd->fHandled = TRUE; } else if(FStrEq(pkvd->szKeyName, "angles")) { // TODO: Insert code here //pkvd->fHandled = TRUE; } else if(FStrEq(pkvd->szKeyName, "lifetime")) { this->mLifetime = atoi(pkvd->szValue); pkvd->fHandled = TRUE; } else { CBasePlayerWeapon::KeyValue(pkvd); }
}
// 0 means never expire, -1 means no value was set so use default
int AvHBasePlayerWeapon::GetLifetime() const
{
int theLifetime = this->mLifetime;
if(theLifetime < 0) { theLifetime = AvHSUGetWeaponStayTime(); } return theLifetime;
}
bool AvHBasePlayerWeapon::GetIsPersistent() const
{
return this->mIsPersistent;
}
void AvHBasePlayerWeapon::SetPersistent()
{
this->mIsPersistent = true;
}
endif
void AvHBasePlayerWeapon::SetNextIdle(void)
{
float theRandomIdle = UTIL_SharedRandomFloat(this->m_pPlayer->random_seed, 10, 15);
this->m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + theRandomIdle; // Just added these next two lines 8/8/01 (trying to fix prediction wackiness) if(this->m_flTimeWeaponIdle < 0) { this->m_flTimeWeaponIdle = theRandomIdle; }
}
BOOL AvHBasePlayerWeapon::UseDecrement( void )
{
// If we're predicting, return true
return TRUE;
}
void AvHBasePlayerWeapon::WeaponIdle(void)
{
//#ifdef AVH_CLIENT
// char sz[ 128 ];
// sprintf(sz, "during idle, clip is %d\n", this->m_iClip);
// gEngfuncs.pfnCenterPrint( sz );
//
// //gEngfuncs.Con_Printf("during idle, clip is %d\n", sz);
//#endif
if(this->mAttackButtonDownLastFrame) { this->PlaybackEvent(this->mEndEvent); this->mAttackButtonDownLastFrame = false; } ResetEmptySound(); this->m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); if(this->m_flTimeWeaponIdle <= UTIL_WeaponTimeBase()) { this->SendWeaponAnim(this->GetIdleAnimation()); this->m_pPlayer->SetAnimation(PLAYER_IDLE); this->SetNextIdle(); }
}
bool AvHBasePlayerWeapon::UsesAmmo(void) const
{
return true;
}