Adding weapons: Difference between revisions
(→Open:) |
|||
| Line 114: | Line 114: | ||
== | ==Create C++ files== | ||
Pick one of the following templates from http://www.hl2coding.com/forums/viewtopic.php?t=1659 | |||
==Weapon Class w/ Zoom== | |||
// STREAMLINED WEAPON CLASS BY PENDRA | |||
#include "cbase.h" | |||
#include "npcevent.h" | |||
#include "in_buttons.h" | |||
#ifdef CLIENT_DLL | |||
#include "c_hl2mp_player.h" | |||
#else | |||
#include "hl2mp_player.h" | |||
#endif | |||
#include "weapon_hl2mpbasehlmpcombatweapon.h" | |||
//modify this to alter the rate of fire | |||
#define ROF 0.075f //800 rounds/min to calculate this do 60/Rounds per minute = ROF | |||
//modify this to alter the length of the burst. Set it to 1 to make a gun Semi-Auto. Set it to some really big number, like 1000 to make it full auto. | |||
#define BURST 3; | |||
#ifdef CLIENT_DLL | |||
#define CWeaponXCAR C_WeaponXCAR | |||
#endif | |||
//----------------------------------------------------------------------------- | |||
// CWeaponXCAR | |||
//----------------------------------------------------------------------------- | |||
class CWeaponXCAR : public CBaseHL2MPCombatWeapon | |||
{ | |||
public: | |||
DECLARE_CLASS( CWeaponXCAR, CBaseHL2MPCombatWeapon ); | |||
CWeaponXCAR(void); | |||
DECLARE_NETWORKCLASS(); | |||
DECLARE_PREDICTABLE(); | |||
void Precache( void ); | |||
void ItemPostFrame( void ); | |||
void ItemPreFrame( void ); | |||
void ItemBusyFrame( void ); | |||
void PrimaryAttack( void ); | |||
void AddViewKick( void ); | |||
void DryFire( void ); | |||
void GetStance( void ); | |||
bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); // Required so that you know to un-zoom when switching weapons | |||
Activity GetPrimaryAttackActivity( void ); | |||
virtual bool Reload( void ); | |||
int GetMinBurst() { return 2; } | |||
int GetMaxBurst() { return 5; } | |||
float GetFireRate( void ) { return ROF; } | |||
//modify this part to control the accuracy | |||
virtual const Vector& GetBulletSpread( void ) | |||
{ | |||
static Vector cone=VECTOR_CONE_10DEGREES; | |||
if (m_bInZoom) | |||
{ | |||
if (m_iStance==E_DUCK) { cone = VECTOR_CONE_1DEGREES;} | |||
if (m_iStance==E_STAND) { cone = VECTOR_CONE_1DEGREES;} | |||
if (m_iStance==E_MOVE) { cone = VECTOR_CONE_1DEGREES;} | |||
if (m_iStance==E_RUN) { cone = VECTOR_CONE_4DEGREES;} | |||
if (m_iStance==E_INJURED) { cone = VECTOR_CONE_5DEGREES;} | |||
if (m_iStance==E_JUMP) { cone = VECTOR_CONE_8DEGREES;} | |||
if (m_iStance==E_DYING) { cone = VECTOR_CONE_10DEGREES;} | |||
} | |||
if (!m_bInZoom) | |||
{ | |||
if (m_iStance==E_DUCK) { cone = VECTOR_CONE_5DEGREES;} | |||
if (m_iStance==E_STAND) { cone = VECTOR_CONE_6DEGREES;} | |||
if (m_iStance==E_MOVE) { cone = VECTOR_CONE_7DEGREES;} | |||
if (m_iStance==E_RUN) { cone = VECTOR_CONE_10DEGREES;} | |||
if (m_iStance==E_INJURED) { cone = VECTOR_CONE_15DEGREES;} | |||
if (m_iStance==E_JUMP) { cone = VECTOR_CONE_15DEGREES;} | |||
if (m_iStance==E_DYING) { cone = VECTOR_CONE_15DEGREES;} | |||
} | |||
int bs=BURST; | |||
if (m_iBurst!=bs) | |||
{ | |||
for (int i=0;i<(bs-m_iBurst);i++) | |||
{cone=cone+VECTOR_CONE_2DEGREES;} | |||
} | |||
return cone; | |||
} | |||
void ToggleZoom( void ); | |||
void CheckZoomToggle( void ); | |||
#ifndef CLIENT_DLL | |||
DECLARE_ACTTABLE(); | |||
#endif | |||
private: | |||
CNetworkVar( int, m_iBurst ); | |||
CNetworkVar( bool, m_bInZoom ); | |||
CNetworkVar( float, m_flAttackEnds ); | |||
CNetworkVar( int, m_iStance); | |||
private: | |||
CWeaponXCAR( const CWeaponXCAR & ); | |||
}; | |||
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponXCAR, DT_WeaponXCAR ) | |||
BEGIN_NETWORK_TABLE( CWeaponXCAR, DT_WeaponXCAR ) | |||
#ifdef CLIENT_DLL | |||
RecvPropInt( RECVINFO( m_iBurst) ), | |||
RecvPropBool( RECVINFO( m_bInZoom ) ), | |||
RecvPropTime( RECVINFO( m_flAttackEnds ) ), | |||
RecvPropInt( RECVINFO( m_iStance ) ), | |||
#else | |||
SendPropInt( SENDINFO( m_iBurst ) ), | |||
SendPropBool( SENDINFO( m_bInZoom ) ), | |||
SendPropTime( SENDINFO( m_flAttackEnds ) ), | |||
SendPropInt( SENDINFO( m_iStance ) ), | |||
#endif | |||
END_NETWORK_TABLE() | |||
BEGIN_PREDICTION_DATA( CWeaponXCAR ) | |||
END_PREDICTION_DATA() | |||
LINK_ENTITY_TO_CLASS( weapon_xcar, CWeaponXCAR ); | |||
PRECACHE_WEAPON_REGISTER( weapon_xcar ); | |||
#ifndef CLIENT_DLL | |||
acttable_t CWeaponXCAR::m_acttable[] = | |||
{ | |||
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_AR2, false }, | |||
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_AR2, false }, | |||
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_AR2, false }, | |||
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_AR2, false }, | |||
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2, false }, | |||
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_AR2, false }, | |||
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_AR2, false }, | |||
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR2, false }, | |||
}; | |||
IMPLEMENT_ACTTABLE( CWeaponXCAR ); | |||
#endif | |||
//----------------------------------------------------------------------------- | |||
// Purpose: Constructor | |||
//----------------------------------------------------------------------------- | |||
CWeaponXCAR::CWeaponXCAR( void ) | |||
{ | |||
m_iBurst=BURST; | |||
m_iStance=10; | |||
m_fMinRange1 = 1; | |||
m_fMaxRange1 = 1500; | |||
m_fMinRange2 = 1; | |||
m_fMaxRange2 = 200; | |||
m_bFiresUnderwater = false; | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::Precache( void ) | |||
{ | |||
BaseClass::Precache(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::DryFire( void ) | |||
{ | |||
WeaponSound( EMPTY ); | |||
SendWeaponAnim( ACT_VM_DRYFIRE ); | |||
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::PrimaryAttack( void ) | |||
{ | |||
if (m_iBurst!=0) | |||
{ | |||
CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); | |||
if( pOwner ) | |||
{ | |||
// Each time the player fires the pistol, reset the view punch. This prevents | |||
// the aim from 'drifting off' when the player fires very quickly. This may | |||
// not be the ideal way to achieve this, but it's cheap and it works, which is | |||
// great for a feature we're evaluating. (sjb) | |||
pOwner->ViewPunchReset(); | |||
} | |||
BaseClass::PrimaryAttack(); | |||
// Add an accuracy penalty which can move past our maximum penalty time if we're really spastic | |||
m_iBurst--; | |||
m_flNextPrimaryAttack =gpGlobals->curtime + ROF; | |||
m_flAttackEnds = gpGlobals->curtime + SequenceDuration(); | |||
} | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::ItemPreFrame( void ) | |||
{ | |||
GetStance(); | |||
BaseClass::ItemPreFrame(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::ItemBusyFrame( void ) | |||
{ | |||
BaseClass::ItemBusyFrame(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: Allows firing as fast as button is pressed | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::ItemPostFrame( void ) | |||
{ | |||
BaseClass::ItemPostFrame(); | |||
if ( m_bInReload ) | |||
return; | |||
CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); | |||
if ( pOwner == NULL ) | |||
return; | |||
if ( pOwner->m_nButtons & IN_ATTACK ) | |||
{ | |||
if (m_flAttackEnds<gpGlobals->curtime) | |||
{ | |||
SendWeaponAnim(ACT_VM_IDLE); | |||
} | |||
} | |||
else | |||
{ | |||
m_iBurst=BURST; | |||
if ( ( pOwner->m_nButtons & IN_ATTACK ) && ( m_flNextPrimaryAttack < gpGlobals->curtime ) && ( m_iClip1 <= 0 ) ) | |||
{ | |||
DryFire(); | |||
} | |||
} | |||
CheckZoomToggle(); | |||
GetStance(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
// Output : int | |||
//----------------------------------------------------------------------------- | |||
Activity CWeaponXCAR::GetPrimaryAttackActivity( void ) | |||
{ | |||
if (m_iBurst!=0) | |||
{ | |||
return ACT_VM_PRIMARYATTACK; | |||
} | |||
else | |||
{ | |||
return ACT_VM_IDLE; | |||
} | |||
} | |||
//----------------------------------------------------------------------------- | |||
//----------------------------------------------------------------------------- | |||
bool CWeaponXCAR::Reload( void ) | |||
{ | |||
bool fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD ); | |||
if ( fRet ) | |||
{ | |||
WeaponSound( RELOAD ); | |||
m_iBurst=BURST; | |||
} | |||
return fRet; | |||
} | |||
bool CWeaponXCAR::Holster(CBaseCombatWeapon *pSwitchingTo /* = NULL */) | |||
{ | |||
if ( m_bInZoom ) | |||
{ | |||
ToggleZoom(); | |||
} | |||
return BaseClass::Holster( pSwitchingTo ); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::AddViewKick( void ) | |||
{ | |||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); | |||
if ( pPlayer == NULL ) | |||
return; | |||
int iSeed = CBaseEntity::GetPredictionRandomSeed() & 255; | |||
RandomSeed( iSeed ); | |||
QAngle viewPunch; | |||
viewPunch.x = random->RandomFloat( 0.25f, 0.5f ); | |||
viewPunch.y = random->RandomFloat( -.6f, .6f ); | |||
viewPunch.z = 0.0f; | |||
//Add it to the view punch | |||
pPlayer->ViewPunch( viewPunch ); | |||
} | |||
void CWeaponXCAR::ToggleZoom( void ) | |||
{ | |||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); | |||
if ( pPlayer == NULL ) | |||
return; | |||
#ifndef CLIENT_DLL | |||
if ( m_bInZoom ) | |||
{ | |||
// Narrowing the Field Of View here is what gives us the zoomed effect | |||
if ( pPlayer->SetFOV( this, 0, 0.2f ) ) | |||
{ | |||
m_bInZoom = false; | |||
// Send a message to hide the scope | |||
/* CSingleUserRecipientFilter filter(pPlayer); | |||
UserMessageBegin(filter, "ShowScope"); | |||
WRITE_BYTE(0); | |||
MessageEnd();*/ | |||
} | |||
} | |||
else | |||
{ | |||
if ( pPlayer->SetFOV( this, 45, 0.1f ) ) | |||
{ | |||
m_bInZoom = true; | |||
// Send a message to Show the scope | |||
/* CSingleUserRecipientFilter filter(pPlayer); | |||
UserMessageBegin(filter, "ShowScope"); | |||
WRITE_BYTE(1); | |||
MessageEnd();*/ | |||
} | |||
} | |||
#endif | |||
} | |||
void CWeaponXCAR::CheckZoomToggle( void ) | |||
{ | |||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); | |||
if ( pPlayer && (pPlayer->m_afButtonPressed & IN_ATTACK2)) | |||
{ | |||
ToggleZoom(); | |||
} | |||
} | |||
void CWeaponXCAR::GetStance( void ) | |||
{ | |||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); | |||
if ( pPlayer == NULL ) | |||
return; | |||
if (pPlayer->m_nButtons & IN_DUCK) { m_iStance= E_DUCK;} else { m_iStance= E_STAND;} | |||
if (pPlayer->m_nButtons & IN_FORWARD) { m_iStance= E_MOVE;} | |||
if (pPlayer->m_nButtons & IN_BACK) { m_iStance= E_MOVE;} | |||
if (pPlayer->m_nButtons & IN_MOVERIGHT) { m_iStance= E_MOVE;} | |||
if (pPlayer->m_nButtons & IN_MOVELEFT) { m_iStance= E_MOVE;} | |||
if (pPlayer->m_nButtons & IN_RUN) { m_iStance= E_RUN;} | |||
if (pPlayer->m_nButtons & IN_SPEED) { m_iStance= E_RUN;} | |||
if (pPlayer->m_nButtons & IN_JUMP) { m_iStance= E_JUMP;} | |||
if ( pPlayer->GetHealth()<25) { m_iStance= E_INJURED;} | |||
if ( pPlayer->GetHealth()<10) { m_iStance= E_DYING;} | |||
} | |||
// CODE ENDS HERE | |||
Now look up the HL2MP at the HL side, right click on Weapon and New/Add existing item. Look up the file you created previously and you are almost done. | |||
I'm pretty sure you don't want to call your gun XCAR, so make a Find and Replace and replace all XCAR with some SHORTWEAPONNAME (like SIG552) Make sure the Match Case is clicked in! Now replace all the xcar with the shortweaponname (like sig552). Remember it is CASE SENSITIVE!!! | |||
Now go to your sourcemod folder and create a weapon_shortweaponname.txt (like weapon_sig552) in the Scripts folder. I usually make a copy of an existing file. | |||
Congratulation your gun should work! | |||
It will have a zoom function with the 2nd fire key, stance and health dependant accuarcy, and burst. If you want to make it trully selective fire, use the code below. It takes away the zoom so you can switch the fire mode with the 2nd fire button. | |||
==Code with single shot or burst (burst not working)== | |||
// STREAMLINED WEAPON CLASS BY PENDRA | |||
#include "cbase.h" | |||
#include "npcevent.h" | |||
#include "in_buttons.h" | |||
#ifdef CLIENT_DLL | |||
#include "c_hl2mp_player.h" | |||
#else | |||
#include "hl2mp_player.h" | |||
#endif | |||
#include "weapon_hl2mpbasehlmpcombatweapon.h" | |||
//mopdify this to alter the rate of fire | |||
#define ROF 0.075f //800 rounds/min | |||
//modify this to alter the length of the burst. Set it to 1 to make a gun Semi-Auto. Set it to some really big number, like 1000 to make it full auto. | |||
#define BURST 3; | |||
#ifdef CLIENT_DLL | |||
#define CWeaponXCAR C_WeaponXCAR | |||
#endif | |||
//----------------------------------------------------------------------------- | |||
// CWeaponXCAR | |||
//----------------------------------------------------------------------------- | |||
class CWeaponXCAR : public CBaseHL2MPCombatWeapon | |||
{ | |||
public: | |||
DECLARE_CLASS( CWeaponXCAR, CBaseHL2MPCombatWeapon ); | |||
CWeaponXCAR(void); | |||
DECLARE_NETWORKCLASS(); | |||
DECLARE_PREDICTABLE(); | |||
void Precache( void ); | |||
void ItemPostFrame( void ); | |||
void ItemPreFrame( void ); | |||
void ItemBusyFrame( void ); | |||
void PrimaryAttack( void ); | |||
void AddViewKick( void ); | |||
void DryFire( void ); | |||
void GetStance( void ); | |||
bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); // Required so that you know to un-zoom when switching weapons | |||
Activity GetPrimaryAttackActivity( void ); | |||
virtual bool Reload( void ); | |||
int GetMinBurst() { return 2; } | |||
int GetMaxBurst() { return 5; } | |||
float GetFireRate( void ) { return ROF; } | |||
//modify this part to control the accuracy | |||
virtual const Vector& GetBulletSpread( void ) | |||
{ | |||
static Vector cone=VECTOR_CONE_10DEGREES; | |||
if (m_iStance==E_DUCK) { cone = VECTOR_CONE_1DEGREES;} | |||
if (m_iStance==E_STAND) { cone = VECTOR_CONE_1DEGREES;} | |||
if (m_iStance==E_MOVE) { cone = VECTOR_CONE_1DEGREES;} | |||
if (m_iStance==E_RUN) { cone = VECTOR_CONE_4DEGREES;} | |||
if (m_iStance==E_INJURED) { cone = VECTOR_CONE_5DEGREES;} | |||
if (m_iStance==E_JUMP) { cone = VECTOR_CONE_8DEGREES;} | |||
if (m_iStance==E_DYING) { cone = VECTOR_CONE_10DEGREES;} | |||
return cone; | |||
} | |||
void ToggleFireMode( void ); | |||
void CheckFireModeToggle( void ); | |||
#ifndef CLIENT_DLL | |||
DECLARE_ACTTABLE(); | |||
#endif | |||
private: | |||
CNetworkVar( bool, m_bFullAuto ); | |||
CNetworkVar( int, m_iBurst ); | |||
CNetworkVar( float, m_flAttackEnds ); | |||
CNetworkVar( int, m_iStance); | |||
private: | |||
CWeaponXCAR( const CWeaponXCAR & ); | |||
}; | |||
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponXCAR, DT_WeaponXCAR ) | |||
BEGIN_NETWORK_TABLE( CWeaponXCAR, DT_WeaponXCAR ) | |||
#ifdef CLIENT_DLL | |||
RecvPropBool( RECVINFO( m_bFullAuto ) ), | |||
RecvPropInt( RECVINFO( m_iBurst) ), | |||
RecvPropTime( RECVINFO( m_flAttackEnds ) ), | |||
RecvPropInt( RECVINFO( m_iStance ) ), | |||
#else | |||
SendPropBool( SENDINFO( m_bFullAuto ) ), | |||
SendPropInt( SENDINFO( m_iBurst ) ), | |||
SendPropTime( SENDINFO( m_flAttackEnds ) ), | |||
SendPropInt( SENDINFO( m_iStance ) ), | |||
#endif | |||
END_NETWORK_TABLE() | |||
BEGIN_PREDICTION_DATA( CWeaponXCAR ) | |||
END_PREDICTION_DATA() | |||
LINK_ENTITY_TO_CLASS( weapon_xcar, CWeaponXCAR ); | |||
PRECACHE_WEAPON_REGISTER( weapon_xcar ); | |||
#ifndef CLIENT_DLL | |||
acttable_t CWeaponXCAR::m_acttable[] = | |||
{ | |||
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_AR2, false }, | |||
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_AR2, false }, | |||
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_AR2, false }, | |||
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_AR2, false }, | |||
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2, false }, | |||
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_AR2, false }, | |||
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_AR2, false }, | |||
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR2, false }, | |||
}; | |||
IMPLEMENT_ACTTABLE( CWeaponXCAR ); | |||
#endif | |||
//----------------------------------------------------------------------------- | |||
// Purpose: Constructor | |||
//----------------------------------------------------------------------------- | |||
CWeaponXCAR::CWeaponXCAR( void ) | |||
{ | |||
m_iBurst=BURST; | |||
m_iStance=10; | |||
m_bInZoom=false; | |||
m_bFullAuto=true; | |||
m_fMinRange1 = 1; | |||
m_fMaxRange1 = 1500; | |||
m_fMinRange2 = 1; | |||
m_fMaxRange2 = 200; | |||
m_bFiresUnderwater = false; | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::Precache( void ) | |||
{ | |||
BaseClass::Precache(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::DryFire( void ) | |||
{ | |||
WeaponSound( EMPTY ); | |||
SendWeaponAnim( ACT_VM_DRYFIRE ); | |||
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::PrimaryAttack( void ) | |||
{ | |||
if (m_iBurst!=0) | |||
{ | |||
CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); | |||
if( pOwner ) | |||
{ | |||
// Each time the player fires the pistol, reset the view punch. This prevents | |||
// the aim from 'drifting off' when the player fires very quickly. This may | |||
// not be the ideal way to achieve this, but it's cheap and it works, which is | |||
// great for a feature we're evaluating. (sjb) | |||
pOwner->ViewPunchReset(); | |||
} | |||
BaseClass::PrimaryAttack(); | |||
// Add an accuracy penalty which can move past our maximum penalty time if we're really spastic | |||
if (!m_bFullAuto) | |||
{m_iBurst--;} | |||
m_flNextPrimaryAttack =gpGlobals->curtime + ROF; | |||
m_flAttackEnds = gpGlobals->curtime + SequenceDuration(); | |||
} | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::ItemPreFrame( void ) | |||
{ | |||
GetStance(); | |||
BaseClass::ItemPreFrame(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::ItemBusyFrame( void ) | |||
{ | |||
BaseClass::ItemBusyFrame(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: Allows firing as fast as button is pressed | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::ItemPostFrame( void ) | |||
{ | |||
BaseClass::ItemPostFrame(); | |||
if ( m_bInReload ) | |||
return; | |||
CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); | |||
if ( pOwner == NULL ) | |||
return; | |||
if ( pOwner->m_nButtons & IN_ATTACK ) | |||
{ | |||
if (m_flAttackEnds<gpGlobals->curtime) | |||
{ | |||
SendWeaponAnim(ACT_VM_IDLE); | |||
} | |||
} | |||
else | |||
{ | |||
m_iBurst=BURST; | |||
if ( ( pOwner->m_nButtons & IN_ATTACK ) && ( m_flNextPrimaryAttack < gpGlobals->curtime ) && ( m_iClip1 <= 0 ) ) | |||
{ | |||
DryFire(); | |||
} | |||
} | |||
CheckFireMode(); | |||
GetStance(); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
// Output : int | |||
//----------------------------------------------------------------------------- | |||
Activity CWeaponXCAR::GetPrimaryAttackActivity( void ) | |||
{ | |||
if (m_iBurst!=0) | |||
{ | |||
return ACT_VM_PRIMARYATTACK; | |||
} | |||
else | |||
{ | |||
return ACT_VM_IDLE; | |||
} | |||
} | |||
//----------------------------------------------------------------------------- | |||
//----------------------------------------------------------------------------- | |||
bool CWeaponXCAR::Reload( void ) | |||
{ | |||
bool fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD ); | |||
if ( fRet ) | |||
{ | |||
WeaponSound( RELOAD ); | |||
m_iBurst=BURST; | |||
} | |||
return fRet; | |||
} | |||
bool CWeaponXCAR::Holster(CBaseCombatWeapon *pSwitchingTo /* = NULL */) | |||
{ | |||
return BaseClass::Holster( pSwitchingTo ); | |||
} | |||
//----------------------------------------------------------------------------- | |||
// Purpose: | |||
//----------------------------------------------------------------------------- | |||
void CWeaponXCAR::AddViewKick( void ) | |||
{ | |||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); | |||
if ( pPlayer == NULL ) | |||
return; | |||
int iSeed = CBaseEntity::GetPredictionRandomSeed() & 255; | |||
RandomSeed( iSeed ); | |||
QAngle viewPunch; | |||
viewPunch.x = random->RandomFloat( 0.25f, 0.5f ); | |||
viewPunch.y = random->RandomFloat( -.6f, .6f ); | |||
viewPunch.z = 0.0f; | |||
//Add it to the view punch | |||
pPlayer->ViewPunch( viewPunch ); | |||
} | |||
void CWeaponXCAR::ToggleFireMode( void ) | |||
{ | |||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); | |||
if ( pPlayer == NULL ) | |||
return; | |||
if ( m_bFullAuto ) | |||
{ | |||
m_bFullAuto=false; | |||
} | |||
else | |||
{ | |||
m_bFullAuto=true; | |||
} | |||
} | |||
void CWeaponXCAR::CheckFireModeToggle( void ) | |||
{ | |||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); | |||
if ( pPlayer && (pPlayer->m_afButtonPressed & IN_ATTACK2)) | |||
{ | |||
ToggleFireMode(); | |||
} | |||
} | |||
void CWeaponXCAR::GetStance( void ) | |||
{ | |||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); | |||
if ( pPlayer == NULL ) | |||
return; | |||
if (pPlayer->m_nButtons & IN_DUCK) { m_iStance= E_DUCK;} else { m_iStance= E_STAND;} | |||
if (pPlayer->m_nButtons & IN_FORWARD) { m_iStance= E_MOVE;} | |||
if (pPlayer->m_nButtons & IN_BACK) { m_iStance= E_MOVE;} | |||
if (pPlayer->m_nButtons & IN_MOVERIGHT) { m_iStance= E_MOVE;} | |||
if (pPlayer->m_nButtons & IN_MOVELEFT) { m_iStance= E_MOVE;} | |||
if (pPlayer->m_nButtons & IN_RUN) { m_iStance= E_RUN;} | |||
if (pPlayer->m_nButtons & IN_SPEED) { m_iStance= E_RUN;} | |||
if (pPlayer->m_nButtons & IN_JUMP) { m_iStance= E_JUMP;} | |||
if ( pPlayer->GetHealth()<25) { m_iStance= E_INJURED;} | |||
if ( pPlayer->GetHealth()<10) { m_iStance= E_DYING;} | |||
} | |||
// CODE ENDS HERE | |||
==Open:== | ==Open:== | ||
Revision as of 19:29, 2 December 2006
Multiplayer
- This guide assumes that you started out with HL2MP and VC++ Express Edition (It's FREE)***
The models Weapons consist of 2 models, each with their own prefix. A model named v_???.mdl is a view model this is the model that is seen from the players perspective, this normally consists of not only the weapon model but also the player hands. Next is the w_???.mdl; this is known as the world model, these models are used for weapons laying on the ground and also for weapons that you can see in other characters/players hands.
You can make your own or use the CSS one's.
Once you have made the relevant models, they go into the folder: /nameofmodfolder/models/weapons/
The Textures The textures/skins for the weapons also need to be placed in the correct folder so once the textures are done, they need to be placed in: /nameofmodfolder/materials/models/weapons/
weapon_???.txt Each weapon has its own script file which can be edited in any .txt program, the weapon script file has many different purposes, which include:- model file names, bucket info, clip size, ammo type, weight, sounds, icons, crosshairs. For pistols start with pistol.txt, and for SMGs MGs, and assault rifle use smg1.txt as a template. This is an example of the weapon_pistol.txt file:
Code: // Pistol
WeaponData {
// Weapon data is loaded by both the Game and Client DLLs. "printname" "#HL2_Pistol" "viewmodel" "models/weapons/v_pistol.mdl" "playermodel" "models/weapons/w_pistol.mdl" "anim_prefix" "pistol" "bucket" "1" "bucket_position" "0"
"clip_size" "18" "primary_ammo" "Pistol" "secondary_ammo" "None"
"weight" "2" "item_flags" "0"
// Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds)
SoundData
{
"reload" "Weapon_Pistol.Reload"
"reload_npc" "Weapon_Pistol.NPC_Reload"
"empty" "Weapon_Pistol.Empty"
"single_shot" "Weapon_Pistol.Single"
"single_shot_npc" "Weapon_Pistol.NPC_Single"
"special1" "Weapon_Pistol.Special1"
"special2" "Weapon_Pistol.Special2"
"burst" "Weapon_Pistol.Burst"
}
// Weapon Sprite data is loaded by the Client DLL.
TextureData
{
"weapon"
{
"font" "WeaponIcons"
"character" "d"
}
"weapon_s"
{
"font" "WeaponIconsSelected"
"character" "d"
}
"ammo"
{
"font" "WeaponIcons"
"character" "p"
}
"crosshair"
{
"font" "Crosshairs"
"character" "Q"
}
"autoaim"
{
"file" "sprites/crosshairs"
"x" "0"
"y" "48"
"width" "24"
"height" "24"
}
}
}
so create your weapon_nameofweapon.txt file in the same format as shown and save it in the following folder:
/nameofmodfolder/scripts/
"printname" "#HL2_Pistol" --Make this whatever you want
Making your weapon show in Hammer -- Not Tested sorry To get your weapon to show in hammer you need to add the entry to your .fgd file, which should be saved in sourcesdk/bin/
Open it up in notepad or similar, and find where the other (HL2) weapons are referenced. Add yours with them, here is an example: @PointClass base(Weapon) studio("models/weapons/w_tazer.mdl") = weapon_tazer : "Tazer" []
Create C++ files
Pick one of the following templates from http://www.hl2coding.com/forums/viewtopic.php?t=1659
Weapon Class w/ Zoom
// STREAMLINED WEAPON CLASS BY PENDRA
- include "cbase.h"
- include "npcevent.h"
- include "in_buttons.h"
- ifdef CLIENT_DLL
- include "c_hl2mp_player.h"
- else
- include "hl2mp_player.h"
- endif
- include "weapon_hl2mpbasehlmpcombatweapon.h"
//modify this to alter the rate of fire
- define ROF 0.075f //800 rounds/min to calculate this do 60/Rounds per minute = ROF
//modify this to alter the length of the burst. Set it to 1 to make a gun Semi-Auto. Set it to some really big number, like 1000 to make it full auto.
- define BURST 3;
- ifdef CLIENT_DLL
- define CWeaponXCAR C_WeaponXCAR
- endif
//----------------------------------------------------------------------------- // CWeaponXCAR //-----------------------------------------------------------------------------
class CWeaponXCAR : public CBaseHL2MPCombatWeapon { public: DECLARE_CLASS( CWeaponXCAR, CBaseHL2MPCombatWeapon );
CWeaponXCAR(void);
DECLARE_NETWORKCLASS(); DECLARE_PREDICTABLE();
void Precache( void ); void ItemPostFrame( void ); void ItemPreFrame( void ); void ItemBusyFrame( void ); void PrimaryAttack( void ); void AddViewKick( void ); void DryFire( void ); void GetStance( void ); bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); // Required so that you know to un-zoom when switching weapons Activity GetPrimaryAttackActivity( void );
virtual bool Reload( void );
int GetMinBurst() { return 2; } int GetMaxBurst() { return 5; } float GetFireRate( void ) { return ROF; }
//modify this part to control the accuracy virtual const Vector& GetBulletSpread( void ) { static Vector cone=VECTOR_CONE_10DEGREES; if (m_bInZoom) { if (m_iStance==E_DUCK) { cone = VECTOR_CONE_1DEGREES;} if (m_iStance==E_STAND) { cone = VECTOR_CONE_1DEGREES;} if (m_iStance==E_MOVE) { cone = VECTOR_CONE_1DEGREES;} if (m_iStance==E_RUN) { cone = VECTOR_CONE_4DEGREES;} if (m_iStance==E_INJURED) { cone = VECTOR_CONE_5DEGREES;} if (m_iStance==E_JUMP) { cone = VECTOR_CONE_8DEGREES;} if (m_iStance==E_DYING) { cone = VECTOR_CONE_10DEGREES;} } if (!m_bInZoom) { if (m_iStance==E_DUCK) { cone = VECTOR_CONE_5DEGREES;} if (m_iStance==E_STAND) { cone = VECTOR_CONE_6DEGREES;} if (m_iStance==E_MOVE) { cone = VECTOR_CONE_7DEGREES;} if (m_iStance==E_RUN) { cone = VECTOR_CONE_10DEGREES;} if (m_iStance==E_INJURED) { cone = VECTOR_CONE_15DEGREES;} if (m_iStance==E_JUMP) { cone = VECTOR_CONE_15DEGREES;} if (m_iStance==E_DYING) { cone = VECTOR_CONE_15DEGREES;} } int bs=BURST; if (m_iBurst!=bs) { for (int i=0;i<(bs-m_iBurst);i++) {cone=cone+VECTOR_CONE_2DEGREES;} }
return cone; } void ToggleZoom( void ); void CheckZoomToggle( void );
- ifndef CLIENT_DLL
DECLARE_ACTTABLE();
- endif
private: CNetworkVar( int, m_iBurst ); CNetworkVar( bool, m_bInZoom ); CNetworkVar( float, m_flAttackEnds ); CNetworkVar( int, m_iStance);
private: CWeaponXCAR( const CWeaponXCAR & ); };
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponXCAR, DT_WeaponXCAR )
BEGIN_NETWORK_TABLE( CWeaponXCAR, DT_WeaponXCAR )
- ifdef CLIENT_DLL
RecvPropInt( RECVINFO( m_iBurst) ), RecvPropBool( RECVINFO( m_bInZoom ) ), RecvPropTime( RECVINFO( m_flAttackEnds ) ), RecvPropInt( RECVINFO( m_iStance ) ),
- else
SendPropInt( SENDINFO( m_iBurst ) ), SendPropBool( SENDINFO( m_bInZoom ) ), SendPropTime( SENDINFO( m_flAttackEnds ) ), SendPropInt( SENDINFO( m_iStance ) ),
- endif
END_NETWORK_TABLE()
BEGIN_PREDICTION_DATA( CWeaponXCAR ) END_PREDICTION_DATA()
LINK_ENTITY_TO_CLASS( weapon_xcar, CWeaponXCAR ); PRECACHE_WEAPON_REGISTER( weapon_xcar );
- ifndef CLIENT_DLL
acttable_t CWeaponXCAR::m_acttable[] = { { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_AR2, false }, { ACT_HL2MP_RUN, ACT_HL2MP_RUN_AR2, false }, { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_AR2, false }, { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_AR2, false }, { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2, false }, { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_AR2, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_AR2, false }, { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR2, false },
};
IMPLEMENT_ACTTABLE( CWeaponXCAR );
- endif
//----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- CWeaponXCAR::CWeaponXCAR( void ) {
m_iBurst=BURST; m_iStance=10;
m_fMinRange1 = 1; m_fMaxRange1 = 1500; m_fMinRange2 = 1; m_fMaxRange2 = 200;
m_bFiresUnderwater = false;
}
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponXCAR::Precache( void ) { BaseClass::Precache(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponXCAR::DryFire( void )
{
WeaponSound( EMPTY );
SendWeaponAnim( ACT_VM_DRYFIRE );
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponXCAR::PrimaryAttack( void ) { if (m_iBurst!=0) { CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if( pOwner ) { // Each time the player fires the pistol, reset the view punch. This prevents // the aim from 'drifting off' when the player fires very quickly. This may // not be the ideal way to achieve this, but it's cheap and it works, which is // great for a feature we're evaluating. (sjb) pOwner->ViewPunchReset(); }
BaseClass::PrimaryAttack();
// Add an accuracy penalty which can move past our maximum penalty time if we're really spastic m_iBurst--;
m_flNextPrimaryAttack =gpGlobals->curtime + ROF; m_flAttackEnds = gpGlobals->curtime + SequenceDuration();
} }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponXCAR::ItemPreFrame( void )
{
GetStance(); BaseClass::ItemPreFrame(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponXCAR::ItemBusyFrame( void ) {
BaseClass::ItemBusyFrame(); }
//----------------------------------------------------------------------------- // Purpose: Allows firing as fast as button is pressed //----------------------------------------------------------------------------- void CWeaponXCAR::ItemPostFrame( void ) { BaseClass::ItemPostFrame();
if ( m_bInReload ) return;
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if ( pOwner == NULL ) return; if ( pOwner->m_nButtons & IN_ATTACK ) { if (m_flAttackEnds<gpGlobals->curtime) { SendWeaponAnim(ACT_VM_IDLE); } } else { m_iBurst=BURST; if ( ( pOwner->m_nButtons & IN_ATTACK ) && ( m_flNextPrimaryAttack < gpGlobals->curtime ) && ( m_iClip1 <= 0 ) ) { DryFire(); } } CheckZoomToggle(); GetStance();
}
//----------------------------------------------------------------------------- // Purpose: // Output : int //----------------------------------------------------------------------------- Activity CWeaponXCAR::GetPrimaryAttackActivity( void ) { if (m_iBurst!=0) { return ACT_VM_PRIMARYATTACK; } else { return ACT_VM_IDLE; } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- bool CWeaponXCAR::Reload( void ) { bool fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD ); if ( fRet ) { WeaponSound( RELOAD ); m_iBurst=BURST; } return fRet; }
bool CWeaponXCAR::Holster(CBaseCombatWeapon *pSwitchingTo /* = NULL */) { if ( m_bInZoom ) { ToggleZoom(); }
return BaseClass::Holster( pSwitchingTo ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponXCAR::AddViewKick( void ) { CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( pPlayer == NULL ) return;
int iSeed = CBaseEntity::GetPredictionRandomSeed() & 255; RandomSeed( iSeed );
QAngle viewPunch;
viewPunch.x = random->RandomFloat( 0.25f, 0.5f ); viewPunch.y = random->RandomFloat( -.6f, .6f ); viewPunch.z = 0.0f;
//Add it to the view punch pPlayer->ViewPunch( viewPunch ); }
void CWeaponXCAR::ToggleZoom( void ) { CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( pPlayer == NULL ) return;
- ifndef CLIENT_DLL
if ( m_bInZoom ) { // Narrowing the Field Of View here is what gives us the zoomed effect if ( pPlayer->SetFOV( this, 0, 0.2f ) ) { m_bInZoom = false;
// Send a message to hide the scope /* CSingleUserRecipientFilter filter(pPlayer); UserMessageBegin(filter, "ShowScope"); WRITE_BYTE(0); MessageEnd();*/ } } else { if ( pPlayer->SetFOV( this, 45, 0.1f ) ) { m_bInZoom = true;
// Send a message to Show the scope /* CSingleUserRecipientFilter filter(pPlayer); UserMessageBegin(filter, "ShowScope"); WRITE_BYTE(1); MessageEnd();*/ } }
- endif
}
void CWeaponXCAR::CheckZoomToggle( void ) { CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( pPlayer && (pPlayer->m_afButtonPressed & IN_ATTACK2)) { ToggleZoom(); } }
void CWeaponXCAR::GetStance( void ) {
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); if ( pPlayer == NULL ) return;
if (pPlayer->m_nButtons & IN_DUCK) { m_iStance= E_DUCK;} else { m_iStance= E_STAND;} if (pPlayer->m_nButtons & IN_FORWARD) { m_iStance= E_MOVE;} if (pPlayer->m_nButtons & IN_BACK) { m_iStance= E_MOVE;} if (pPlayer->m_nButtons & IN_MOVERIGHT) { m_iStance= E_MOVE;} if (pPlayer->m_nButtons & IN_MOVELEFT) { m_iStance= E_MOVE;} if (pPlayer->m_nButtons & IN_RUN) { m_iStance= E_RUN;} if (pPlayer->m_nButtons & IN_SPEED) { m_iStance= E_RUN;} if (pPlayer->m_nButtons & IN_JUMP) { m_iStance= E_JUMP;} if ( pPlayer->GetHealth()<25) { m_iStance= E_INJURED;} if ( pPlayer->GetHealth()<10) { m_iStance= E_DYING;}
}
// CODE ENDS HERE
Now look up the HL2MP at the HL side, right click on Weapon and New/Add existing item. Look up the file you created previously and you are almost done.
I'm pretty sure you don't want to call your gun XCAR, so make a Find and Replace and replace all XCAR with some SHORTWEAPONNAME (like SIG552) Make sure the Match Case is clicked in! Now replace all the xcar with the shortweaponname (like sig552). Remember it is CASE SENSITIVE!!! Now go to your sourcemod folder and create a weapon_shortweaponname.txt (like weapon_sig552) in the Scripts folder. I usually make a copy of an existing file. Congratulation your gun should work!
It will have a zoom function with the 2nd fire key, stance and health dependant accuarcy, and burst. If you want to make it trully selective fire, use the code below. It takes away the zoom so you can switch the fire mode with the 2nd fire button.
Code with single shot or burst (burst not working)
// STREAMLINED WEAPON CLASS BY PENDRA
- include "cbase.h"
- include "npcevent.h"
- include "in_buttons.h"
- ifdef CLIENT_DLL
- include "c_hl2mp_player.h"
- else
- include "hl2mp_player.h"
- endif
- include "weapon_hl2mpbasehlmpcombatweapon.h"
//mopdify this to alter the rate of fire
- define ROF 0.075f //800 rounds/min
//modify this to alter the length of the burst. Set it to 1 to make a gun Semi-Auto. Set it to some really big number, like 1000 to make it full auto.
- define BURST 3;
- ifdef CLIENT_DLL
- define CWeaponXCAR C_WeaponXCAR
- endif
//----------------------------------------------------------------------------- // CWeaponXCAR //-----------------------------------------------------------------------------
class CWeaponXCAR : public CBaseHL2MPCombatWeapon { public: DECLARE_CLASS( CWeaponXCAR, CBaseHL2MPCombatWeapon );
CWeaponXCAR(void);
DECLARE_NETWORKCLASS(); DECLARE_PREDICTABLE();
void Precache( void ); void ItemPostFrame( void ); void ItemPreFrame( void ); void ItemBusyFrame( void ); void PrimaryAttack( void ); void AddViewKick( void ); void DryFire( void ); void GetStance( void ); bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); // Required so that you know to un-zoom when switching weapons Activity GetPrimaryAttackActivity( void );
virtual bool Reload( void );
int GetMinBurst() { return 2; } int GetMaxBurst() { return 5; } float GetFireRate( void ) { return ROF; }
//modify this part to control the accuracy virtual const Vector& GetBulletSpread( void ) { static Vector cone=VECTOR_CONE_10DEGREES; if (m_iStance==E_DUCK) { cone = VECTOR_CONE_1DEGREES;} if (m_iStance==E_STAND) { cone = VECTOR_CONE_1DEGREES;} if (m_iStance==E_MOVE) { cone = VECTOR_CONE_1DEGREES;} if (m_iStance==E_RUN) { cone = VECTOR_CONE_4DEGREES;} if (m_iStance==E_INJURED) { cone = VECTOR_CONE_5DEGREES;} if (m_iStance==E_JUMP) { cone = VECTOR_CONE_8DEGREES;} if (m_iStance==E_DYING) { cone = VECTOR_CONE_10DEGREES;}
return cone; } void ToggleFireMode( void ); void CheckFireModeToggle( void );
- ifndef CLIENT_DLL
DECLARE_ACTTABLE();
- endif
private: CNetworkVar( bool, m_bFullAuto ); CNetworkVar( int, m_iBurst ); CNetworkVar( float, m_flAttackEnds ); CNetworkVar( int, m_iStance);
private: CWeaponXCAR( const CWeaponXCAR & ); };
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponXCAR, DT_WeaponXCAR )
BEGIN_NETWORK_TABLE( CWeaponXCAR, DT_WeaponXCAR )
- ifdef CLIENT_DLL
RecvPropBool( RECVINFO( m_bFullAuto ) ), RecvPropInt( RECVINFO( m_iBurst) ), RecvPropTime( RECVINFO( m_flAttackEnds ) ), RecvPropInt( RECVINFO( m_iStance ) ),
- else
SendPropBool( SENDINFO( m_bFullAuto ) ), SendPropInt( SENDINFO( m_iBurst ) ), SendPropTime( SENDINFO( m_flAttackEnds ) ), SendPropInt( SENDINFO( m_iStance ) ),
- endif
END_NETWORK_TABLE()
BEGIN_PREDICTION_DATA( CWeaponXCAR ) END_PREDICTION_DATA()
LINK_ENTITY_TO_CLASS( weapon_xcar, CWeaponXCAR ); PRECACHE_WEAPON_REGISTER( weapon_xcar );
- ifndef CLIENT_DLL
acttable_t CWeaponXCAR::m_acttable[] = { { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_AR2, false }, { ACT_HL2MP_RUN, ACT_HL2MP_RUN_AR2, false }, { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_AR2, false }, { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_AR2, false }, { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2, false }, { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_AR2, false }, { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_AR2, false }, { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR2, false },
};
IMPLEMENT_ACTTABLE( CWeaponXCAR );
- endif
//----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- CWeaponXCAR::CWeaponXCAR( void ) {
m_iBurst=BURST; m_iStance=10; m_bInZoom=false; m_bFullAuto=true;
m_fMinRange1 = 1;
m_fMaxRange1 = 1500;
m_fMinRange2 = 1;
m_fMaxRange2 = 200;
m_bFiresUnderwater = false;
}
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponXCAR::Precache( void ) { BaseClass::Precache(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponXCAR::DryFire( void )
{
WeaponSound( EMPTY );
SendWeaponAnim( ACT_VM_DRYFIRE );
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponXCAR::PrimaryAttack( void ) { if (m_iBurst!=0) { CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if( pOwner ) { // Each time the player fires the pistol, reset the view punch. This prevents // the aim from 'drifting off' when the player fires very quickly. This may // not be the ideal way to achieve this, but it's cheap and it works, which is // great for a feature we're evaluating. (sjb) pOwner->ViewPunchReset(); }
BaseClass::PrimaryAttack();
// Add an accuracy penalty which can move past our maximum penalty time if we're really spastic if (!m_bFullAuto) {m_iBurst--;}
m_flNextPrimaryAttack =gpGlobals->curtime + ROF; m_flAttackEnds = gpGlobals->curtime + SequenceDuration();
} }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponXCAR::ItemPreFrame( void )
{
GetStance(); BaseClass::ItemPreFrame(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponXCAR::ItemBusyFrame( void ) {
BaseClass::ItemBusyFrame(); }
//----------------------------------------------------------------------------- // Purpose: Allows firing as fast as button is pressed //----------------------------------------------------------------------------- void CWeaponXCAR::ItemPostFrame( void ) { BaseClass::ItemPostFrame();
if ( m_bInReload ) return;
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if ( pOwner == NULL ) return; if ( pOwner->m_nButtons & IN_ATTACK ) { if (m_flAttackEnds<gpGlobals->curtime) { SendWeaponAnim(ACT_VM_IDLE); } } else { m_iBurst=BURST; if ( ( pOwner->m_nButtons & IN_ATTACK ) && ( m_flNextPrimaryAttack < gpGlobals->curtime ) && ( m_iClip1 <= 0 ) ) { DryFire(); } } CheckFireMode(); GetStance();
}
//----------------------------------------------------------------------------- // Purpose: // Output : int //----------------------------------------------------------------------------- Activity CWeaponXCAR::GetPrimaryAttackActivity( void ) { if (m_iBurst!=0) { return ACT_VM_PRIMARYATTACK; } else { return ACT_VM_IDLE; } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- bool CWeaponXCAR::Reload( void ) { bool fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD ); if ( fRet ) { WeaponSound( RELOAD ); m_iBurst=BURST; } return fRet; }
bool CWeaponXCAR::Holster(CBaseCombatWeapon *pSwitchingTo /* = NULL */) {
return BaseClass::Holster( pSwitchingTo ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponXCAR::AddViewKick( void ) { CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( pPlayer == NULL ) return;
int iSeed = CBaseEntity::GetPredictionRandomSeed() & 255; RandomSeed( iSeed );
QAngle viewPunch;
viewPunch.x = random->RandomFloat( 0.25f, 0.5f ); viewPunch.y = random->RandomFloat( -.6f, .6f ); viewPunch.z = 0.0f;
//Add it to the view punch pPlayer->ViewPunch( viewPunch ); }
void CWeaponXCAR::ToggleFireMode( void ) { CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( pPlayer == NULL ) return;
if ( m_bFullAuto ) { m_bFullAuto=false; } else { m_bFullAuto=true;
} }
void CWeaponXCAR::CheckFireModeToggle( void ) { CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( pPlayer && (pPlayer->m_afButtonPressed & IN_ATTACK2)) { ToggleFireMode(); } }
void CWeaponXCAR::GetStance( void ) {
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); if ( pPlayer == NULL ) return;
if (pPlayer->m_nButtons & IN_DUCK) { m_iStance= E_DUCK;} else { m_iStance= E_STAND;} if (pPlayer->m_nButtons & IN_FORWARD) { m_iStance= E_MOVE;} if (pPlayer->m_nButtons & IN_BACK) { m_iStance= E_MOVE;} if (pPlayer->m_nButtons & IN_MOVERIGHT) { m_iStance= E_MOVE;} if (pPlayer->m_nButtons & IN_MOVELEFT) { m_iStance= E_MOVE;} if (pPlayer->m_nButtons & IN_RUN) { m_iStance= E_RUN;} if (pPlayer->m_nButtons & IN_SPEED) { m_iStance= E_RUN;} if (pPlayer->m_nButtons & IN_JUMP) { m_iStance= E_JUMP;} if ( pPlayer->GetHealth()<25) { m_iStance= E_INJURED;} if ( pPlayer->GetHealth()<10) { m_iStance= E_DYING;}
}
// CODE ENDS HERE
Open:
C:\yourmod\src\cl_dll\hl2_hud\c_weapon__stubs_hl2.cpp
add your gun under #ifndef HL2MP (line 27)
just copy and paste one of the lines renaming the relevant information
Example:
STUB_WEAPON_CLASS( weapon_ar2, WeaponAR2, C_HLMachineGun );
changed to
STUB_WEAPON_CLASS( weapon_m249, WeaponM4A1, C_HLMachineGun );
Open:
C:\yourmod\src\game_shared\hl2mp\hl2mp_gamerules.cpp
Find CAmmoDef *GetAmmoDef() (Line 910)
Copy and paste the line that is closest to your weapon type, I chose
def.AddAmmoType("MP5NAVY",DMG_BULLET,TRACER_LINE_AND_WHIZ,0,0,225,BULLET_IMPULSE(200,1225),0 );
Replace MP5NAVY with the ammo name in your script file (weapon_???.txt)
Make the code files where ever you want, I would recommend your C:/modname/src folder. When you complete the code expand under Server -> Sources Files -> HL2MP -> Weapons, right-click on Weapons then Add -> Existing Item and find your .cpp file
Do the same for Client -> Sources Files -> HL2MP -> Weapons
also, if you want your weapon to be given with the impulse 101 cheat, add it in this file:
/dlls/player.cpp
NOTE: some of the directory structures may be different, following SDK updates etc. this was written after the large August 2006 update
There you have it; you should now have an understanding of how to get a new weapon in-game. Be aware that there is a lot of work to be done that I have not mentioned in detail, such as the code or explaining the weapon_???,txt file fully. Most people should be able to figure out the rest.
Good luck and I hope to see some new weapons being made soon.
I noticed that there were no decent up-to-date guides hence this wiki -Iliketofrolic666
this is a work in progress