-
-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f9e2c94
commit 46752d2
Showing
15 changed files
with
577 additions
and
396 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#pragma once | ||
|
||
#define ITEM_FLAG_SELECTONEMPTY 1 | ||
#define ITEM_FLAG_NOAUTORELOAD 2 | ||
#define ITEM_FLAG_NOAUTOSWITCHEMPTY 4 | ||
#define ITEM_FLAG_LIMITINWORLD 8 | ||
#define ITEM_FLAG_EXHAUSTIBLE 16 // A player can totally exhaust their ammo supply and lose this weapon | ||
|
||
typedef struct | ||
{ | ||
int iSlot; | ||
int iPosition; | ||
const char *pszAmmo1; // ammo 1 type | ||
int iMaxAmmo1; // max ammo 1 | ||
const char *pszAmmo2; // ammo 2 type | ||
int iMaxAmmo2; // max ammo 2 | ||
const char *pszName; | ||
int iMaxClip; | ||
int iId; | ||
int iFlags; | ||
int iWeight;// this value used to determine this weapon's importance in autoselection. | ||
} ItemInfo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,249 @@ | ||
#include "weapon_logic.h" | ||
#include "extdll.h" | ||
#include "util.h" | ||
#include "cbase.h" | ||
#include "player.h" | ||
#include "monsters.h" | ||
#include "weapons.h" | ||
#include "nodes.h" | ||
#include "soundent.h" | ||
#include "decals.h" | ||
#include "gamerules.h" | ||
|
||
BOOL CanAttack( float attack_time, float curtime, BOOL isPredicted ) | ||
{ | ||
return ( attack_time <= curtime ) ? TRUE : FALSE; | ||
} | ||
|
||
CBaseWeaponLogic::CBaseWeaponLogic(IWeaponLogicFuncs *funcs) : | ||
m_pFuncs(funcs), | ||
m_pPlayer(nullptr) | ||
{ | ||
} | ||
|
||
CBaseWeaponLogic::~CBaseWeaponLogic() | ||
{ | ||
if (m_pFuncs) { | ||
delete m_pFuncs; | ||
} | ||
} | ||
|
||
void CBaseWeaponLogic::ItemPostFrame() | ||
{ | ||
if ((m_fInReload) && ( m_pPlayer->m_flNextAttack <= gpGlobals->time )) | ||
{ | ||
// complete the reload. | ||
int j = Q_min( iMaxClip() - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]); | ||
|
||
// Add them to the clip | ||
m_iClip += j; | ||
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= j; | ||
|
||
m_fInReload = FALSE; | ||
} | ||
|
||
if ((m_pPlayer->pev->button & IN_ATTACK2) && CanAttack( m_flNextSecondaryAttack, gpGlobals->time, UseDecrement() ) ) | ||
{ | ||
if ( pszAmmo2() && !m_pPlayer->m_rgAmmo[SecondaryAmmoIndex()] ) | ||
{ | ||
m_fFireOnEmpty = TRUE; | ||
} | ||
|
||
SecondaryAttack(); | ||
m_pPlayer->pev->button &= ~IN_ATTACK2; | ||
} | ||
else if ((m_pPlayer->pev->button & IN_ATTACK) && CanAttack( m_flNextPrimaryAttack, gpGlobals->time, UseDecrement() ) ) | ||
{ | ||
if ( (m_iClip == 0 && pszAmmo1()) || (iMaxClip() == -1 && !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] ) ) | ||
{ | ||
m_fFireOnEmpty = TRUE; | ||
} | ||
|
||
PrimaryAttack(); | ||
} | ||
else if ( m_pPlayer->pev->button & IN_RELOAD && iMaxClip() != WEAPON_NOCLIP && !m_fInReload ) | ||
{ | ||
// reload when reload is pressed, or if no buttons are down and weapon is empty. | ||
Reload(); | ||
} | ||
else if ( !(m_pPlayer->pev->button & (IN_ATTACK|IN_ATTACK2) ) ) | ||
{ | ||
// no fire buttons down | ||
|
||
m_fFireOnEmpty = FALSE; | ||
|
||
if ( !IsUseable() && m_flNextPrimaryAttack < ( UseDecrement() ? 0.0 : gpGlobals->time ) ) | ||
{ | ||
// weapon isn't useable, switch. | ||
if ( !(iFlags() & ITEM_FLAG_NOAUTOSWITCHEMPTY) && m_pFuncs->GetNextBestWeapon() ) | ||
{ | ||
m_flNextPrimaryAttack = ( UseDecrement() ? 0.0 : gpGlobals->time ) + 0.3; | ||
return; | ||
} | ||
} | ||
else | ||
{ | ||
// weapon is useable. Reload if empty and weapon has waited as long as it has to after firing | ||
if ( m_iClip == 0 && !(iFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < ( UseDecrement() ? 0.0 : gpGlobals->time ) ) | ||
{ | ||
Reload(); | ||
return; | ||
} | ||
} | ||
|
||
WeaponIdle( ); | ||
return; | ||
} | ||
|
||
// catch all | ||
if ( ShouldWeaponIdle() ) | ||
{ | ||
WeaponIdle(); | ||
} | ||
} | ||
|
||
void CBaseWeaponLogic::Holster( void ) | ||
{ | ||
m_fInReload = FALSE; // cancel any reload in progress. | ||
m_pPlayer->pev->viewmodel = 0; | ||
m_pPlayer->pev->weaponmodel = 0; | ||
} | ||
|
||
//========================================================= | ||
// IsUseable - this function determines whether or not a | ||
// weapon is useable by the player in its current state. | ||
// (does it have ammo loaded? do I have any ammo for the | ||
// weapon?, etc) | ||
//========================================================= | ||
BOOL CBaseWeaponLogic :: IsUseable( void ) | ||
{ | ||
if ( m_iClip <= 0 ) | ||
{ | ||
if ( m_pPlayer->m_rgAmmo[ PrimaryAmmoIndex() ] <= 0 && iMaxAmmo1() != -1 ) | ||
{ | ||
// clip is empty (or nonexistant) and the player has no more ammo of this type. | ||
return FALSE; | ||
} | ||
} | ||
|
||
return TRUE; | ||
} | ||
|
||
BOOL CBaseWeaponLogic :: CanDeploy( void ) | ||
{ | ||
BOOL bHasAmmo = 0; | ||
|
||
if ( !pszAmmo1() ) | ||
{ | ||
// this weapon doesn't use ammo, can always deploy. | ||
return TRUE; | ||
} | ||
|
||
if ( pszAmmo1() ) | ||
{ | ||
bHasAmmo |= (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] != 0); | ||
} | ||
if ( pszAmmo2() ) | ||
{ | ||
bHasAmmo |= (m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] != 0); | ||
} | ||
if (m_iClip > 0) | ||
{ | ||
bHasAmmo |= 1; | ||
} | ||
if (!bHasAmmo) | ||
{ | ||
return FALSE; | ||
} | ||
|
||
return TRUE; | ||
} | ||
|
||
BOOL CBaseWeaponLogic :: DefaultDeploy( char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal /* = 0 */, int body ) | ||
{ | ||
if (!CanDeploy( )) | ||
return FALSE; | ||
|
||
m_pPlayer->pev->viewmodel = MAKE_STRING(szViewModel); | ||
m_pPlayer->pev->weaponmodel = MAKE_STRING(szWeaponModel); | ||
strcpy( m_pPlayer->m_szAnimExtention, szAnimExt ); | ||
SendWeaponAnim( iAnim, skiplocal, body ); | ||
|
||
m_pPlayer->m_flNextAttack = gpGlobals->time + 0.5; | ||
m_flTimeWeaponIdle = gpGlobals->time + 1.0; | ||
|
||
return TRUE; | ||
} | ||
|
||
BOOL CBaseWeaponLogic :: DefaultReload( int iClipSize, int iAnim, float fDelay, int body ) | ||
{ | ||
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) | ||
return FALSE; | ||
|
||
int j = Q_min(iClipSize - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]); | ||
|
||
if (j == 0) | ||
return FALSE; | ||
|
||
m_pPlayer->m_flNextAttack = gpGlobals->time + fDelay; | ||
|
||
//!!UNDONE -- reload sound goes here !!! | ||
SendWeaponAnim( iAnim, UseDecrement() ? 1 : 0 ); | ||
|
||
m_fInReload = TRUE; | ||
|
||
m_flTimeWeaponIdle = gpGlobals->time + 3; | ||
return TRUE; | ||
} | ||
|
||
void CBaseWeaponLogic::SendWeaponAnim( int iAnim, int skiplocal, int body ) | ||
{ | ||
if ( UseDecrement() ) | ||
skiplocal = 1; | ||
else | ||
skiplocal = 0; | ||
|
||
m_pPlayer->pev->weaponanim = iAnim; | ||
|
||
MESSAGE_BEGIN( MSG_ONE, SVC_WEAPONANIM, NULL, m_pPlayer->pev ); | ||
WRITE_BYTE( iAnim ); // sequence number | ||
WRITE_BYTE( m_pFuncs->GetWeaponBodygroup() ); // weaponmodel bodygroup. | ||
MESSAGE_END(); | ||
} | ||
|
||
BOOL CBaseWeaponLogic :: PlayEmptySound( void ) | ||
{ | ||
if (m_iPlayEmptySound) | ||
{ | ||
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/357_cock1.wav", 0.8, ATTN_NORM); | ||
m_iPlayEmptySound = 0; | ||
return 0; | ||
} | ||
return 0; | ||
} | ||
|
||
void CBaseWeaponLogic :: ResetEmptySound( void ) | ||
{ | ||
m_iPlayEmptySound = 1; | ||
} | ||
|
||
int CBaseWeaponLogic::PrimaryAmmoIndex( void ) | ||
{ | ||
return m_iPrimaryAmmoType; | ||
} | ||
|
||
int CBaseWeaponLogic::SecondaryAmmoIndex( void ) | ||
{ | ||
return -1; | ||
} | ||
|
||
int CBaseWeaponLogic::iItemSlot(void) { return 0; } // return 0 to MAX_ITEMS_SLOTS, used in hud | ||
int CBaseWeaponLogic::iItemPosition( void ) { return CBasePlayerItem::ItemInfoArray[ m_iId ].iPosition; } | ||
const char *CBaseWeaponLogic::pszAmmo1( void ) { return CBasePlayerItem::ItemInfoArray[ m_iId ].pszAmmo1; } | ||
int CBaseWeaponLogic::iMaxAmmo1( void ) { return CBasePlayerItem::ItemInfoArray[ m_iId ].iMaxAmmo1; } | ||
const char *CBaseWeaponLogic::pszAmmo2( void ) { return CBasePlayerItem::ItemInfoArray[ m_iId ].pszAmmo2; } | ||
int CBaseWeaponLogic::iMaxAmmo2( void ) { return CBasePlayerItem::ItemInfoArray[ m_iId ].iMaxAmmo2; } | ||
const char *CBaseWeaponLogic::pszName( void ) { return CBasePlayerItem::ItemInfoArray[ m_iId ].pszName; } | ||
int CBaseWeaponLogic::iMaxClip( void ) { return CBasePlayerItem::ItemInfoArray[ m_iId ].iMaxClip; } | ||
int CBaseWeaponLogic::iWeight( void ) { return CBasePlayerItem::ItemInfoArray[ m_iId ].iWeight; } | ||
int CBaseWeaponLogic::iFlags( void ) { return CBasePlayerItem::ItemInfoArray[ m_iId ].iFlags; } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#pragma once | ||
#include "weapon_logic_funcs.h" | ||
#include "vector.h" | ||
#include "item_info.h" | ||
|
||
class CBasePlayer; | ||
|
||
class CBaseWeaponLogic | ||
{ | ||
public: | ||
CBaseWeaponLogic(IWeaponLogicFuncs *funcs); | ||
virtual ~CBaseWeaponLogic(); | ||
void ItemPostFrame(); | ||
|
||
// called by CBasePlayerWeapons ItemPostFrame() | ||
virtual void PrimaryAttack( void ) { return; } // do "+ATTACK" | ||
virtual void SecondaryAttack( void ) { return; } // do "+ATTACK2" | ||
virtual void Reload( void ) { return; } // do "+RELOAD" | ||
virtual void WeaponIdle( void ) { return; } // called when no buttons pressed | ||
|
||
virtual BOOL ShouldWeaponIdle( void ) {return FALSE; }; | ||
virtual BOOL CanDeploy( void ); | ||
virtual BOOL Deploy( ) { return TRUE; }; // returns is deploy was successful | ||
virtual BOOL CanHolster( void ) { return TRUE; }; // can this weapon be put away right nxow? | ||
virtual void Holster(void); | ||
virtual BOOL IsUseable( void ); | ||
virtual BOOL UseDecrement( void ) { return FALSE; }; | ||
|
||
virtual int GetItemInfo(ItemInfo *p) { return 0; }; // returns 0 if struct not filled out | ||
virtual int PrimaryAmmoIndex(); | ||
virtual int SecondaryAmmoIndex(); | ||
|
||
virtual int iItemSlot(void); | ||
virtual int iItemPosition(void); | ||
virtual const char *pszAmmo1(void); | ||
virtual int iMaxAmmo1(void); | ||
virtual const char *pszAmmo2(void); | ||
virtual int iMaxAmmo2(void); | ||
virtual const char *pszName(void); | ||
virtual int iMaxClip(void); | ||
virtual int iWeight(void); | ||
virtual int iFlags(void); | ||
|
||
BOOL DefaultDeploy( char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal = 0, int body = 0 ); | ||
int DefaultReload( int iClipSize, int iAnim, float fDelay, int body = 0 ); | ||
void SendWeaponAnim( int iAnim, int skiplocal = 1, int body = 0 ); // skiplocal is 1 if client is predicting weapon animations | ||
BOOL PlayEmptySound( void ); | ||
void ResetEmptySound( void ); | ||
|
||
int m_iId; // WEAPON_??? | ||
int m_iPlayEmptySound; | ||
int m_fFireOnEmpty; // True when the gun is empty and the player is still holding down the attack key(s) | ||
float m_flPumpTime; | ||
int m_fInSpecialReload; // Are we in the middle of a reload for the shotguns | ||
float m_flNextPrimaryAttack; // soonest time ItemPostFrame will call PrimaryAttack | ||
float m_flNextSecondaryAttack; // soonest time ItemPostFrame will call SecondaryAttack | ||
float m_flTimeWeaponIdle; // soonest time ItemPostFrame will call WeaponIdle | ||
int m_iPrimaryAmmoType; // "primary" ammo index into players m_rgAmmo[] | ||
int m_iSecondaryAmmoType; // "secondary" ammo index into players m_rgAmmo[] | ||
int m_iClip; // number of shots left in the primary weapon clip, -1 it not used | ||
int m_iClientClip; // the last version of m_iClip sent to hud dll | ||
int m_iClientWeaponState; // the last version of the weapon state sent to hud dll (is current weapon, is on target) | ||
int m_fInReload; // Are we in the middle of a reload; | ||
int m_iDefaultAmmo;// how much ammo you get when you pick up this weapon as placed by a level designer. | ||
CBasePlayer *m_pPlayer; | ||
IWeaponLogicFuncs *m_pFuncs; | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#pragma once | ||
|
||
class IWeaponLogicFuncs | ||
{ | ||
public: | ||
virtual ~IWeaponLogicFuncs() {}; | ||
virtual const char *GetWeaponClassname() = 0; | ||
virtual int GetWeaponBodygroup() = 0; | ||
virtual bool GetNextBestWeapon() = 0; | ||
}; |
Oops, something went wrong.