diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index ba5e4e162..ac4aba783 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -48,6 +48,8 @@ list(APPEND SVDLL_SOURCES "user_messages.cpp" "util.cpp" "weapons.cpp" + "weapon_logic.cpp" + "weapon_logic_funcs_impl.cpp" "world.cpp" ) diff --git a/server/item_info.h b/server/item_info.h new file mode 100644 index 000000000..18a542b07 --- /dev/null +++ b/server/item_info.h @@ -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; diff --git a/server/player.cpp b/server/player.cpp index 579f48702..26b9b9347 100644 --- a/server/player.cpp +++ b/server/player.cpp @@ -4915,7 +4915,7 @@ void CBasePlayer::DropPlayerItem ( char *pszItemName ) UTIL_MakeVectors ( GetAbsAngles() ); - RemoveWeapon( pWeapon->m_iId ); // take item off hud + RemoveWeapon( pWeapon->iWeaponID() ); // take item off hud CWeaponBox *pWeaponBox = (CWeaponBox *)CBaseEntity::Create( "weaponbox", GetAbsOrigin() + gpGlobals->v_forward * 10, GetAbsAngles(), edict() ); Vector vecAngles = pWeaponBox->GetAbsAngles(); diff --git a/server/stats.cpp b/server/stats.cpp index 5650336d3..f79f1e5af 100644 --- a/server/stats.cpp +++ b/server/stats.cpp @@ -109,7 +109,7 @@ void UpdateStats( CBasePlayer *pPlayer ) int index = pPlayer->GetAmmoIndex(II.pszAmmo1); if ( index >= 0 ) - ammoCount[ index ] += ((CBasePlayerWeapon *)p)->m_iClip; + ammoCount[ index ] += ((CBasePlayerWeapon *)p)->m_pWeaponLogic->m_iClip; p = p->m_pNext; } diff --git a/server/weapon_logic.cpp b/server/weapon_logic.cpp new file mode 100644 index 000000000..c5f9a5da4 --- /dev/null +++ b/server/weapon_logic.cpp @@ -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) && g_pGameRules->GetNextBestWeapon( m_pPlayer, this ) ) + { + 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; } diff --git a/server/weapon_logic.h b/server/weapon_logic.h new file mode 100644 index 000000000..b8431e6d2 --- /dev/null +++ b/server/weapon_logic.h @@ -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; +}; + diff --git a/server/weapon_logic_funcs.h b/server/weapon_logic_funcs.h new file mode 100644 index 000000000..b7c47f3d1 --- /dev/null +++ b/server/weapon_logic_funcs.h @@ -0,0 +1,9 @@ +#pragma once + +class IWeaponLogicFuncs +{ +public: + virtual ~IWeaponLogicFuncs() {}; + virtual const char *GetWeaponClassname() = 0; + virtual int GetWeaponBodygroup() = 0; +}; diff --git a/server/weapon_logic_funcs_impl.cpp b/server/weapon_logic_funcs_impl.cpp new file mode 100644 index 000000000..223819a9f --- /dev/null +++ b/server/weapon_logic_funcs_impl.cpp @@ -0,0 +1,16 @@ +#include "weapon_logic_funcs_impl.h" + +CWeaponLogicFuncsImpl::CWeaponLogicFuncsImpl(CBasePlayerWeapon *weaponEntity) : + m_pWeapon(weaponEntity) +{ +} + +const char *CWeaponLogicFuncsImpl::GetWeaponClassname() +{ + return STRING(m_pWeapon->pev->classname); +} + +int CWeaponLogicFuncsImpl::GetWeaponBodygroup() +{ + return m_pWeapon->pev->body; +} diff --git a/server/weapon_logic_funcs_impl.h b/server/weapon_logic_funcs_impl.h new file mode 100644 index 000000000..eb78953ff --- /dev/null +++ b/server/weapon_logic_funcs_impl.h @@ -0,0 +1,20 @@ +#pragma once +#include "weapon_logic_funcs.h" +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "player.h" +#include "monsters.h" +#include "weapons.h" + +class CWeaponLogicFuncsImpl : public IWeaponLogicFuncs +{ +public: + CWeaponLogicFuncsImpl(CBasePlayerWeapon *weaponEntity); + + const char *GetWeaponClassname() override; + int GetWeaponBodygroup() override; + +private: + CBasePlayerWeapon *m_pWeapon; +}; diff --git a/server/weapons.cpp b/server/weapons.cpp index 54ec7477d..c9c56898c 100644 --- a/server/weapons.cpp +++ b/server/weapons.cpp @@ -398,7 +398,6 @@ void W_Precache(void) BEGIN_DATADESC( CBasePlayerItem ) DEFINE_FIELD( m_pPlayer, FIELD_CLASSPTR ), DEFINE_FIELD( m_pNext, FIELD_CLASSPTR ), - DEFINE_FIELD( m_iId, FIELD_INTEGER ), DEFINE_FUNCTION( DestroyItem ), DEFINE_FUNCTION( DefaultTouch ), DEFINE_FUNCTION( FallThink ), @@ -407,13 +406,14 @@ BEGIN_DATADESC( CBasePlayerItem ) END_DATADESC() BEGIN_DATADESC( CBasePlayerWeapon ) - DEFINE_FIELD( m_flNextPrimaryAttack, FIELD_TIME ), - DEFINE_FIELD( m_flNextSecondaryAttack, FIELD_TIME ), - DEFINE_FIELD( m_flTimeWeaponIdle, FIELD_TIME ), - DEFINE_FIELD( m_iPrimaryAmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_iSecondaryAmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_iClip, FIELD_INTEGER ), - DEFINE_FIELD( m_iDefaultAmmo, FIELD_INTEGER ), + //DEFINE_FIELD( m_flNextPrimaryAttack, FIELD_TIME ), + //DEFINE_FIELD( m_flNextSecondaryAttack, FIELD_TIME ), + //DEFINE_FIELD( m_flTimeWeaponIdle, FIELD_TIME ), + //DEFINE_FIELD( m_iPrimaryAmmoType, FIELD_INTEGER ), + //DEFINE_FIELD( m_iSecondaryAmmoType, FIELD_INTEGER ), + //DEFINE_FIELD( m_iClip, FIELD_INTEGER ), + //DEFINE_FIELD( m_iDefaultAmmo, FIELD_INTEGER ), + //DEFINE_FIELD( m_iId, FIELD_INTEGER ), END_DATADESC() void CBasePlayerItem :: SetObjectCollisionBox( void ) @@ -584,84 +584,7 @@ void CBasePlayerItem::DefaultTouch( CBaseEntity *pOther ) SUB_UseTargets( pOther, USE_TOGGLE, 0 ); // UNDONE: when should this happen? } -BOOL CanAttack( float attack_time, float curtime, BOOL isPredicted ) -{ - return ( attack_time <= curtime ) ? TRUE : FALSE; -} - -void CBasePlayerWeapon::ItemPostFrame( void ) -{ - 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) && g_pGameRules->GetNextBestWeapon( m_pPlayer, this ) ) - { - 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 CBasePlayerItem::DestroyItem( void ) { @@ -720,7 +643,7 @@ void CBasePlayerItem::AttachToPlayer ( CBasePlayer *pPlayer ) // CALLED THROUGH the newly-touched weapon's instance. The existing player weapon is pOriginal int CBasePlayerWeapon::AddDuplicate( CBasePlayerItem *pOriginal ) { - if ( m_iDefaultAmmo ) + if ( m_pWeaponLogic->m_iDefaultAmmo ) { return ExtractAmmo( (CBasePlayerWeapon *)pOriginal ); } @@ -731,17 +654,28 @@ int CBasePlayerWeapon::AddDuplicate( CBasePlayerItem *pOriginal ) } } +CBasePlayerWeapon::CBasePlayerWeapon() : + m_pWeaponLogic(nullptr) +{ +} + +CBasePlayerWeapon::~CBasePlayerWeapon() +{ + if (m_pWeaponLogic) { + delete m_pWeaponLogic; + } +} int CBasePlayerWeapon::AddToPlayer( CBasePlayer *pPlayer ) { int bResult = CBasePlayerItem::AddToPlayer( pPlayer ); - pPlayer->AddWeapon( m_iId ); + pPlayer->AddWeapon( m_pWeaponLogic->m_iId ); - if ( !m_iPrimaryAmmoType ) + if ( !m_pWeaponLogic->m_iPrimaryAmmoType ) { - m_iPrimaryAmmoType = pPlayer->GetAmmoIndex( pszAmmo1() ); - m_iSecondaryAmmoType = pPlayer->GetAmmoIndex( pszAmmo2() ); + m_pWeaponLogic->m_iPrimaryAmmoType = pPlayer->GetAmmoIndex( pszAmmo1() ); + m_pWeaponLogic->m_iSecondaryAmmoType = pPlayer->GetAmmoIndex( pszAmmo2() ); } @@ -779,8 +713,8 @@ int CBasePlayerWeapon::UpdateClientData( CBasePlayer *pPlayer ) } // If the ammo, state, or fov has changed, update the weapon - if ( m_iClip != m_iClientClip || - state != m_iClientWeaponState || + if ( m_pWeaponLogic->m_iClip != m_pWeaponLogic->m_iClientClip || + state != m_pWeaponLogic->m_iClientWeaponState || pPlayer->m_iFOV != pPlayer->m_iClientFOV ) { bSend = TRUE; @@ -790,12 +724,12 @@ int CBasePlayerWeapon::UpdateClientData( CBasePlayer *pPlayer ) { MESSAGE_BEGIN( MSG_ONE, gmsgCurWeapon, NULL, pPlayer->pev ); WRITE_BYTE( state ); - WRITE_BYTE( m_iId ); - WRITE_BYTE( m_iClip ); + WRITE_BYTE( m_pWeaponLogic->m_iId ); + WRITE_BYTE( m_pWeaponLogic->m_iClip ); MESSAGE_END(); - m_iClientClip = m_iClip; - m_iClientWeaponState = state; + m_pWeaponLogic->m_iClientClip = m_pWeaponLogic->m_iClip; + m_pWeaponLogic->m_iClientWeaponState = state; pPlayer->m_fWeapon = TRUE; } @@ -805,36 +739,20 @@ int CBasePlayerWeapon::UpdateClientData( CBasePlayer *pPlayer ) return 1; } - -void CBasePlayerWeapon::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( pev->body ); // weaponmodel bodygroup. - MESSAGE_END(); -} - BOOL CBasePlayerWeapon :: AddPrimaryAmmo( int iCount, char *szName, int iMaxClip, int iMaxCarry ) { int iIdAmmo; if (iMaxClip < 1) { - m_iClip = -1; + m_pWeaponLogic->m_iClip = -1; iIdAmmo = m_pPlayer->GiveAmmo( iCount, szName, iMaxCarry ); } - else if (m_iClip == 0) + else if (m_pWeaponLogic->m_iClip == 0) { int i; - i = Q_min( m_iClip + iCount, iMaxClip ) - m_iClip; - m_iClip += i; + i = Q_min( m_pWeaponLogic->m_iClip + iCount, iMaxClip ) - m_pWeaponLogic->m_iClip; + m_pWeaponLogic->m_iClip += i; iIdAmmo = m_pPlayer->GiveAmmo( iCount - i, szName, iMaxCarry ); } else @@ -846,7 +764,7 @@ BOOL CBasePlayerWeapon :: AddPrimaryAmmo( int iCount, char *szName, int iMaxClip if (iIdAmmo > 0) { - m_iPrimaryAmmoType = iIdAmmo; + m_pWeaponLogic->m_iPrimaryAmmoType = iIdAmmo; if (m_pPlayer->HasPlayerItem( this ) ) { // play the "got ammo" sound only if we gave some ammo to a player that already had this gun. @@ -869,137 +787,12 @@ BOOL CBasePlayerWeapon :: AddSecondaryAmmo( int iCount, char *szName, int iMax ) if (iIdAmmo > 0) { - m_iSecondaryAmmoType = iIdAmmo; + m_pWeaponLogic->m_iSecondaryAmmoType = iIdAmmo; EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM); } return iIdAmmo > 0 ? TRUE : FALSE; } -//========================================================= -// 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 CBasePlayerWeapon :: 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 CBasePlayerWeapon :: 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 CBasePlayerWeapon :: 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 CBasePlayerWeapon :: 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; -} - -BOOL CBasePlayerWeapon :: 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 CBasePlayerWeapon :: ResetEmptySound( void ) -{ - m_iPlayEmptySound = 1; -} - -//========================================================= -//========================================================= -int CBasePlayerWeapon::PrimaryAmmoIndex( void ) -{ - return m_iPrimaryAmmoType; -} - -//========================================================= -//========================================================= -int CBasePlayerWeapon::SecondaryAmmoIndex( void ) -{ - return -1; -} - -void CBasePlayerWeapon::Holster( void ) -{ - m_fInReload = FALSE; // cancel any reload in progress. - m_pPlayer->pev->viewmodel = 0; - m_pPlayer->pev->weaponmodel = 0; -} - BEGIN_DATADESC( CBasePlayerAmmo ) DEFINE_FUNCTION( DefaultTouch ), DEFINE_FUNCTION( Materialize ), @@ -1083,8 +876,8 @@ int CBasePlayerWeapon::ExtractAmmo( CBasePlayerWeapon *pWeapon ) { // blindly call with m_iDefaultAmmo. It's either going to be a value or zero. If it is zero, // we only get the ammo in the weapon's clip, which is what we want. - iReturn = pWeapon->AddPrimaryAmmo( m_iDefaultAmmo, (char *)pszAmmo1(), iMaxClip(), iMaxAmmo1() ); - m_iDefaultAmmo = 0; + iReturn = pWeapon->AddPrimaryAmmo( m_pWeaponLogic->m_iDefaultAmmo, (char *)pszAmmo1(), iMaxClip(), iMaxAmmo1() ); + m_pWeaponLogic->m_iDefaultAmmo = 0; } if ( pszAmmo2() != NULL ) @@ -1102,13 +895,13 @@ int CBasePlayerWeapon::ExtractClipAmmo( CBasePlayerWeapon *pWeapon ) { int iAmmo; - if ( m_iClip == WEAPON_NOCLIP ) + if ( m_pWeaponLogic->m_iClip == WEAPON_NOCLIP ) { iAmmo = 0;// guns with no clips always come empty if they are second-hand } else { - iAmmo = m_iClip; + iAmmo = m_pWeaponLogic->m_iClip; } return pWeapon->m_pPlayer->GiveAmmo( iAmmo, (char *)pszAmmo1(), iMaxAmmo1() ); // , &m_iPrimaryAmmoType @@ -1465,17 +1258,17 @@ void CWeaponBox::SetObjectCollisionBox( void ) void CBasePlayerWeapon::PrintState( void ) { - ALERT( at_console, "primary: %f\n", m_flNextPrimaryAttack ); - ALERT( at_console, "idle : %f\n", m_flTimeWeaponIdle ); +// ALERT( at_console, "primary: %f\n", m_flNextPrimaryAttack ); +// ALERT( at_console, "idle : %f\n", m_flTimeWeaponIdle ); // ALERT( at_console, "nextrl : %f\n", m_flNextReload ); // ALERT( at_console, "nextpum: %f\n", m_flPumpTime ); // ALERT( at_console, "m_frt : %f\n", m_fReloadTime ); - ALERT( at_console, "m_finre: %i\n", m_fInReload ); +// ALERT( at_console, "m_finre: %i\n", m_fInReload ); // ALERT( at_console, "m_finsr: %i\n", m_fInSpecialReload ); - ALERT( at_console, "m_iclip: %i\n", m_iClip ); +// ALERT( at_console, "m_iclip: %i\n", m_iClip ); } //========================================================= diff --git a/server/weapons.h b/server/weapons.h index 70379ad89..328874c12 100644 --- a/server/weapons.h +++ b/server/weapons.h @@ -15,7 +15,10 @@ #ifndef WEAPONS_H #define WEAPONS_H +#include "cbase.h" #include "effects.h" +#include "item_info.h" +#include "weapon_logic.h" class CBasePlayer; @@ -145,30 +148,8 @@ typedef enum BULLET_MONSTER_12MM, } Bullet; - -#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 - #define WEAPON_IS_ONTARGET 0x40 -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; - typedef struct { const char *pszName; @@ -198,8 +179,7 @@ class CBasePlayerItem : public CBaseAnimating virtual BOOL CanDeploy( void ) { return TRUE; }; virtual BOOL Deploy( ) { return TRUE; }; // returns is deploy was successful - - virtual BOOL CanHolster( void ) { return TRUE; }; // can this weapon be put away right now? + virtual BOOL CanHolster( void ) { return TRUE; }; // can this weapon be put away right nxow? virtual void Holster( void ); virtual void UpdateItemInfo( void ) { return; }; @@ -222,19 +202,18 @@ class CBasePlayerItem : public CBaseAnimating CBasePlayer *m_pPlayer; CBasePlayerItem *m_pNext; - int m_iId; // WEAPON_??? - - virtual int iItemSlot( void ) { return 0; } // return 0 to MAX_ITEMS_SLOTS, used in hud - - int iItemPosition( void ) { return ItemInfoArray[ m_iId ].iPosition; } - const char *pszAmmo1( void ) { return ItemInfoArray[ m_iId ].pszAmmo1; } - int iMaxAmmo1( void ) { return ItemInfoArray[ m_iId ].iMaxAmmo1; } - const char *pszAmmo2( void ) { return ItemInfoArray[ m_iId ].pszAmmo2; } - int iMaxAmmo2( void ) { return ItemInfoArray[ m_iId ].iMaxAmmo2; } - const char *pszName( void ) { return ItemInfoArray[ m_iId ].pszName; } - int iMaxClip( void ) { return ItemInfoArray[ m_iId ].iMaxClip; } - int iWeight( void ) { return ItemInfoArray[ m_iId ].iWeight; } - int iFlags( void ) { return ItemInfoArray[ m_iId ].iFlags; } + + virtual int iItemSlot() = 0; + virtual int iItemPosition() = 0; + virtual const char *pszAmmo1() = 0; + virtual int iMaxAmmo1() = 0; + virtual const char *pszAmmo2() = 0; + virtual int iMaxAmmo2() = 0; + virtual const char *pszName() = 0; + virtual int iMaxClip() = 0; + virtual int iWeight() = 0; + virtual int iFlags() = 0; + virtual int iWeaponID() = 0; }; // inventory items that @@ -244,67 +223,58 @@ class CBasePlayerWeapon : public CBasePlayerItem public: DECLARE_DATADESC(); - // generic weapon versions of CBasePlayerItem calls - virtual int AddToPlayer( CBasePlayer *pPlayer ); - virtual int AddDuplicate( CBasePlayerItem *pItem ); + CBasePlayerWeapon(); + ~CBasePlayerWeapon(); - virtual int ExtractAmmo( CBasePlayerWeapon *pWeapon ); // Return TRUE if you can add ammo to yourself when picked up - virtual int ExtractClipAmmo( CBasePlayerWeapon *pWeapon ); // Return TRUE if you can add ammo to yourself when picked up - - virtual int AddWeapon( void ) { ExtractAmmo( this ); return TRUE; }; // Return TRUE if you want to add yourself to the player + // generic weapon versions of CBasePlayerItem calls + virtual int AddToPlayer( CBasePlayer *pPlayer ) override; + virtual int AddDuplicate( CBasePlayerItem *pItem ) override; + + int UpdateClientData( CBasePlayer *pPlayer ) override; // sends hud info to client dll, if things have changed + + // declare it here, but in future move to the bottom + CBaseWeaponLogic *m_pWeaponLogic; + + // forward to weapon logic + virtual void ItemPostFrame(void) override { return m_pWeaponLogic->ItemPostFrame(); }; // called each frame by the player PostThink + + int PrimaryAmmoIndex() override { return m_pWeaponLogic->PrimaryAmmoIndex(); }; // forward to weapon logic + int SecondaryAmmoIndex() override { return m_pWeaponLogic->SecondaryAmmoIndex(); }; // forward to weapon logic + + // forward all this to weapon logic + virtual int GetItemInfo(ItemInfo *p) override { return m_pWeaponLogic->GetItemInfo(p); }; // returns 0 if struct not filled out + virtual BOOL CanDeploy( void ) override { return m_pWeaponLogic->CanDeploy(); }; + virtual BOOL Deploy() override { return m_pWeaponLogic->Deploy(); }; // returns is deploy was successful + virtual BOOL CanHolster( void ) override { return m_pWeaponLogic->CanHolster(); }; // can this weapon be put away right nxow? + virtual void Holster(void) override { m_pWeaponLogic->Holster(); }; + + void UpdateItemInfo( void ) override {}; // updates HUD state + CBasePlayerItem *GetWeaponPtr( void ) override { return (CBasePlayerItem *)this; }; + + // forward all of them to weapon logic + int iItemSlot() override { return m_pWeaponLogic->iItemSlot(); } + int iItemPosition() override { return m_pWeaponLogic->iItemPosition(); } + const char *pszAmmo1() override { return m_pWeaponLogic->pszAmmo1(); } + int iMaxAmmo1() override { return m_pWeaponLogic->iMaxAmmo1(); } + const char *pszAmmo2() override { return m_pWeaponLogic->pszAmmo2(); } + int iMaxAmmo2() override { return m_pWeaponLogic->iMaxAmmo2(); } + const char *pszName() override { return m_pWeaponLogic->pszName(); } + int iMaxClip() override { return m_pWeaponLogic->iMaxClip(); } + int iWeight() override { return m_pWeaponLogic->iWeight(); } + int iFlags() override { return m_pWeaponLogic->iFlags(); } + int iWeaponID() override { return m_pWeaponLogic->m_iId; } + +protected: + int ExtractAmmo( CBasePlayerWeapon *pWeapon ); // Return TRUE if you can add ammo to yourself when picked up + int ExtractClipAmmo( CBasePlayerWeapon *pWeapon ); // Return TRUE if you can add ammo to yourself when picked up + + int AddWeapon( void ) { ExtractAmmo( this ); return TRUE; }; // Return TRUE if you want to add yourself to the player + void RetireWeapon( void ); // generic "shared" ammo handlers BOOL AddPrimaryAmmo( int iCount, char *szName, int iMaxClip, int iMaxCarry ); BOOL AddSecondaryAmmo( int iCount, char *szName, int iMaxCarry ); - - virtual void UpdateItemInfo( void ) {}; // updates HUD state - - int m_iPlayEmptySound; - int m_fFireOnEmpty; // True when the gun is empty and the player is still holding down the - // attack key(s) - virtual BOOL PlayEmptySound( void ); - virtual void ResetEmptySound( void ); - - virtual void SendWeaponAnim( int iAnim, int skiplocal = 1, int body = 0 ); // skiplocal is 1 if client is predicting weapon animations - - virtual BOOL CanDeploy( void ); - virtual BOOL IsUseable( 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 ); - - virtual void ItemPostFrame( void ); // called each frame by the player PostThink - // 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 int UpdateClientData( CBasePlayer *pPlayer ); // sends hud info to client dll, if things have changed - virtual void RetireWeapon( void ); - virtual BOOL ShouldWeaponIdle( void ) {return FALSE; }; - virtual void Holster( void ); - virtual BOOL UseDecrement( void ) { return FALSE; }; - - int PrimaryAmmoIndex(); - int SecondaryAmmoIndex(); - void PrintState( void ); - - virtual CBasePlayerItem *GetWeaponPtr( void ) { return (CBasePlayerItem *)this; }; - - 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. - }; class CBasePlayerAmmo : public CBaseEntity diff --git a/server/weapons/glock.cpp b/server/weapons/glock.cpp index bb20271fc..ae5b6e4ec 100644 --- a/server/weapons/glock.cpp +++ b/server/weapons/glock.cpp @@ -14,6 +14,7 @@ ****/ #include "glock.h" +#include "weapon_logic_funcs_impl.h" enum glock_e { @@ -36,12 +37,9 @@ void CGlock::Spawn( ) { pev->classname = MAKE_STRING( "weapon_9mmhandgun" ); // hack to allow for old names Precache( ); - m_iId = WEAPON_GLOCK; SET_MODEL( edict(), "models/w_9mmhandgun.mdl" ); - - m_iDefaultAmmo = GLOCK_DEFAULT_GIVE; - FallInit();// get ready to fall down. + m_pWeaponLogic = new CGlockWeaponLogic(new CWeaponLogicFuncsImpl(this)); } void CGlock::Precache( void ) @@ -49,20 +47,26 @@ void CGlock::Precache( void ) PRECACHE_MODEL("models/v_9mmhandgun.mdl"); PRECACHE_MODEL("models/w_9mmhandgun.mdl"); PRECACHE_MODEL("models/p_9mmhandgun.mdl"); - - m_iShell = PRECACHE_MODEL ("models/shell.mdl");// brass shell + PRECACHE_MODEL("models/shell.mdl"); // brass shell PRECACHE_SOUND("items/9mmclip1.wav"); PRECACHE_SOUND("items/9mmclip2.wav"); - PRECACHE_SOUND ("weapons/pl_gun1.wav");//silenced handgun - PRECACHE_SOUND ("weapons/pl_gun2.wav");//silenced handgun - PRECACHE_SOUND ("weapons/pl_gun3.wav");//handgun + PRECACHE_SOUND("weapons/pl_gun1.wav"); //silenced handgun + PRECACHE_SOUND("weapons/pl_gun2.wav"); //silenced handgun + PRECACHE_SOUND("weapons/pl_gun3.wav"); //handgun +} + +CGlockWeaponLogic::CGlockWeaponLogic(IWeaponLogicFuncs *funcs) : + CBaseWeaponLogic(funcs) +{ + m_iDefaultAmmo = GLOCK_DEFAULT_GIVE; + m_iId = WEAPON_GLOCK; } -int CGlock::GetItemInfo(ItemInfo *p) +int CGlockWeaponLogic::GetItemInfo(ItemInfo *p) { - p->pszName = STRING(pev->classname); + p->pszName = m_pFuncs->GetWeaponClassname();//STRING(pev->classname); p->pszAmmo1 = "9mm"; p->iMaxAmmo1 = _9MM_MAX_CARRY; p->pszAmmo2 = NULL; @@ -77,23 +81,23 @@ int CGlock::GetItemInfo(ItemInfo *p) return 1; } -BOOL CGlock::Deploy( ) +BOOL CGlockWeaponLogic::Deploy( ) { // pev->body = 1; return DefaultDeploy( "models/v_9mmhandgun.mdl", "models/p_9mmhandgun.mdl", GLOCK_DRAW, "onehanded" ); } -void CGlock::SecondaryAttack( void ) +void CGlockWeaponLogic::SecondaryAttack( void ) { GlockFire( 0.1, 0.2, FALSE ); } -void CGlock::PrimaryAttack( void ) +void CGlockWeaponLogic::PrimaryAttack( void ) { GlockFire( 0.01, 0.3, TRUE ); } -void CGlock::GlockFire( float flSpread , float flCycleTime, BOOL fUseAutoAim ) +void CGlockWeaponLogic::GlockFire( float flSpread , float flCycleTime, BOOL fUseAutoAim ) { if (m_iClip <= 0) { @@ -125,10 +129,10 @@ void CGlock::GlockFire( float flSpread , float flCycleTime, BOOL fUseAutoAim ) + gpGlobals->v_up * RANDOM_FLOAT(100,150) + gpGlobals->v_forward * 25; EjectBrass ( m_pPlayer->EyePosition() + gpGlobals->v_up * -12 + gpGlobals->v_forward * 32 + gpGlobals->v_right * 6, - vecShellVelocity, m_pPlayer->GetAbsAngles().y, m_iShell, TE_BOUNCE_SHELL ); + vecShellVelocity, m_pPlayer->GetAbsAngles().y, MODEL_INDEX("models/shell.mdl"), TE_BOUNCE_SHELL); // silenced - if (pev->body == 1) + if (m_pFuncs->GetWeaponBodygroup() == 1) { m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME; m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH; @@ -175,7 +179,7 @@ void CGlock::GlockFire( float flSpread , float flCycleTime, BOOL fUseAutoAim ) m_pPlayer->pev->punchangle.x -= 2; } -void CGlock::Reload( void ) +void CGlockWeaponLogic::Reload( void ) { int iResult; @@ -190,7 +194,7 @@ void CGlock::Reload( void ) } } -void CGlock::WeaponIdle( void ) +void CGlockWeaponLogic::WeaponIdle( void ) { ResetEmptySound( ); diff --git a/server/weapons/glock.h b/server/weapons/glock.h index 4448beac3..aa0f95b03 100644 --- a/server/weapons/glock.h +++ b/server/weapons/glock.h @@ -21,22 +21,29 @@ #include "weapons.h" #include "nodes.h" #include "player.h" +#include "weapon_logic_funcs.h" -class CGlock : public CBasePlayerWeapon +class CGlockWeaponLogic : public CBaseWeaponLogic { - DECLARE_CLASS( CGlock, CBasePlayerWeapon ); public: - void Spawn( void ); - void Precache( void ); + CGlockWeaponLogic() = delete; + CGlockWeaponLogic(IWeaponLogicFuncs *funcs); + int iItemSlot( void ) { return 2; } int GetItemInfo(ItemInfo *p); - void PrimaryAttack( void ); void SecondaryAttack( void ); void GlockFire( float flSpread, float flCycleTime, BOOL fUseAutoAim ); BOOL Deploy( void ); void Reload( void ); void WeaponIdle( void ); -private: - int m_iShell; }; + +class CGlock : public CBasePlayerWeapon +{ + DECLARE_CLASS( CGlock, CBasePlayerWeapon ); +public: + void Spawn( void ); + void Precache( void ); +}; +