/*** * * Copyright (c) 1996-2002, Valve LLC. All rights reserved. * * This product contains software technology licensed from Id * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * * Use, distribution, and modification of this source code and/or resulting * object code is restricted to non-commercial enhancements to products from * Valve LLC. All other use, distribution, or modification is prohibited * without written permission from Valve LLC. * ****/ #ifndef WEAPONS_H #define WEAPONS_H #include #include "effects.h" #include "player.h" class CBasePlayer; class CBasePlayerItem; extern int gmsgWeapPickup; // Contact Grenade / Timed grenade class CGrenade : public CBaseMonster { public: void Spawn( void ); static CGrenade *ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time, float damage = 100.0f ); static CGrenade *ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity ); static CGrenade *ShootGeneric( CBaseEntity *pOwner, Vector vecStart, Vector vecVelocity, string_t classname ); void Explode( Vector vecSrc, Vector vecAim ); void Explode( TraceResult *pTrace, int bitsDamageType ); void EXPORT Smoke( void ); void EXPORT BounceTouch( CBaseEntity *pOther ); void EXPORT SlideTouch( CBaseEntity *pOther ); void EXPORT ExplodeTouch( CBaseEntity *pOther ); void EXPORT DangerSoundThink( void ); void EXPORT PreDetonate( void ); void EXPORT Detonate( void ); void EXPORT DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); void EXPORT TumbleThink( void ); virtual void BounceSound( void ); virtual int BloodColor( void ) { return DONT_BLEED; } virtual void Killed( entvars_t *pevAttacker, int iGib ); BOOL m_fRegisteredSound;// whether or not this grenade has issued its DANGER sound to the world sound list yet. }; class CRpgRocket : public CGrenade { public: int Save( CSave &save ); int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; void Spawn( void ); void Precache( void ); void EXPORT FollowThink( void ); void EXPORT IgniteThink( void ); void EXPORT RocketTouch( CBaseEntity *pOther ); static CRpgRocket *CreateRpgRocket( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CBasePlayerItem *pLauncher ); int m_iFireTrail; // Wargon: переменная для огненного следа у ракет. int m_iTrail; float m_flIgniteTime; CBasePlayerItem *m_pLauncher;// pointer back to the launcher that fired me. }; class CLaserSpot : public CBaseEntity { void Spawn( void ); void Precache( void ); int ObjectCaps( void ) { return FCAP_DONT_SAVE; } public: void Update( CBasePlayer *m_pPlayer ); void Suspend( float flSuspendTime ); void EXPORT Revive( void ); static CLaserSpot *CreateSpot( void ); static CLaserSpot *CreateSpot( const char* spritename ); }; // hardcoded ID's #define WEAPON_NONE 0 #define WEAPON_PAINKILLER 31 #define WEAPON_CUSTOM_COUNT WEAPON_PAINKILLER #define WEAPON_ALLWEAPONS (~BIT( WEAPON_PAINKILLER )) #define MAX_WEAPONS 32 // a 32-bit integer limit #define MAX_AMMO_DESC 256 // various combinations of entities that contain ammo #define MAX_SHOOTSOUNDS 8 // max of four random shoot sounds #define MAX_NORMAL_BATTERY 100 // suit definitions #define BAREHAND_SUIT 0 // just in case #define MILITARY_SUIT 1 // gordon suit #define NUM_HANDS 2 // number of hands: barney and gordon #define PLAYER_HAS_SUIT ( FBitSet( m_pPlayer->m_iHideHUD, ITEM_SUIT )) #define PLAYER_DRAW_SUIT ( FBitSet( pev->body, MILITARY_SUIT )) // the maximum amount of ammo each weapon's clip can hold #define WEAPON_NOCLIP -1 // reload code #define NOT_IN_RELOAD 0 #define START_RELOAD 1 #define CONTINUE_RELOAD 2 // for shotgun #define EMPTY_RELOAD 3 #define NORMAL_RELOAD 4 // zoom code #define NOT_IN_ZOOM 0 // zoom not used #define NORMAL_ZOOM 1 // default zooming (button one shot) #define UPDATE_ZOOM 2 // increase zoom (button holding down) #define RESET_ZOOM 3 // disable zoom #define ZOOM_MAXIMUM 20 #define ZOOM_DEFAULT 50 // ammo code #define AMMO_UNKNOWN 0 #define AMMO_PRIMARY 1 #define AMMO_SECONDARY 2 #define ITEM_FLAG_SELECTONEMPTY BIT( 0 ) // can select while ammo is out #define ITEM_FLAG_NOAUTORELOAD BIT( 1 ) // manual reload only #define ITEM_FLAG_NOAUTOSWITCHEMPTY BIT( 2 ) // don't switch to another gun while ammo is out #define ITEM_FLAG_LIMITINWORLD BIT( 3 ) // limit count in world (e.g. explodables) #define ITEM_FLAG_EXHAUSTIBLE BIT( 4 ) // A player can totally exhaust their ammo supply and lose this weapon #define ITEM_FLAG_NODUPLICATE BIT( 5 ) // player can't give this weapon again (e.g. knife, crowbar) #define ITEM_FLAG_USEAUTOAIM BIT( 6 ) // weapon uses autoaim #define ITEM_FLAG_ALLOW_FIREMODE BIT( 7 ) // allow to change firemode #define ITEM_FLAG_SHOOT_UNDERWATER BIT( 8 ) // weapon can be shoot underwater (e.g. glock) #define ITEM_FLAG_IRONSIGHT BIT( 9 ) // enable client effects: DOF, breathing etc #define ITEM_FLAG_AUTOFIRE BIT( 10 ) // hold attack for auto-fire #define ITEM_FLAG_SCOPE BIT( 11 ) // using scope instead of IronSight #define ITEM_FLAG_NODROP BIT( 12 ) // don't drop this weapon #define WEAPON_IS_ONTARGET 0x40 typedef enum { ATTACK_NONE = 0, // no action ATTACK_AMMO1, // fire primary ammo ATTACK_AMMO2, // fire secondary ammo ATTACK_LASER_DOT, // enable laser dot ATTACK_ZOOM, // enable zoom ATTACK_FLASHLIGHT, // enable flashlight ATTACK_SWITCHMODE, // play two beetwen anims and change body ATTACK_SWING, // knife swing ATTACK_IRONSIGHT, // iron sight on and off ATTACK_SCOPE // iron sight & scope } e_attack; enum { SPREAD_LINEAR = 0, // изменение разброса линейно во времени SPREAD_QUAD, // по параболе (вначале узкий, потом резко расширяется) SPREAD_CUBE, // кубическая парабола SPREAD_SQRT, // наоборот (быстро расширяется и плавно переходит в максимальный) }; typedef struct { RandomRange range; // min spread .. max spread int type; // spread equalize float expand; // spread expand } spread_t; typedef struct { float maxSpeed; // clamp at maximum float jumpHeight; // clamp at maximum } player_settings_t; // client feedback typedef struct { RandomRange punchangle[3]; // range of x,y,z RandomRange recoil; } feedback_t; typedef struct { int iSlot; // hud slot int iPosition; // hud position string_t iViewModel; // path to viewmodel string_t iHandModel; // path to optional hands model string_t iWorldModel; // path to worldmodel char szAnimExt[16]; // player anim postfix const char *pszAmmo1; // ammo 1 type int iMaxAmmo1; // max ammo 1 const char *pszAmmo2; // ammo 2 type int iMaxAmmo2; // max ammo 2 RandomRange iDefaultAmmo1; // default primary ammo RandomRange iDefaultAmmo2; // default secondary ammo const char *pszName; // unique weapon name int iMaxClip; // clip size int iId; // unique weapon ID int iFlags; // misc flags int iWeight; // this value used to determine this weapon's importance in autoselection. int attack1; // attack1 type int attack2; // attack2 type float fNextAttack1; // nextattack float fNextAttack2; // next secondary attack Vector vecThrowOffset; // throw view offset for melee grenades string_t shootsound1[MAX_SHOOTSOUNDS]; // primary attack sounds string_t shootsound2[MAX_SHOOTSOUNDS]; // secondary attack sounds string_t emptysounds[MAX_SHOOTSOUNDS]; // empty sound int sndcount1; // primary attack sound count int sndcount2; // secondary attack sound count int emptysndcount; // empty sounds count string_t smashDecals[2]; // decal groups for swing weapon (crowbar, knife) spread_t spread1[2]; // customizable spread from Paranoia spread_t spread2[2]; // same but for secondary attack feedback_t feedback1[2]; // client feedback for primary attack (recoil, punch, speed etc) feedback_t feedback2[2]; // same but for secondary attack player_settings_t plr_settings[2]; // player speed and player jumpheight float spreadtime; // time to return to normal spread int iVolume; // weapon volume int iFlash; // weapon flash RandomRange recoil1; // recoil 1 attack RandomRange recoil2; // recoil 2 attack } ItemInfo; typedef struct { const char *pszName; int iMaxCarry; int iShellIndex; // precached shell model index int iNumShots; // > 1 is fraction string_t iMissileClassName; // it's a projectile ammo (grenades etc) float flDistance; // typically 2048 for fractions float flPlayerDamage; float flMonsterDamage; int iId; } AmmoInfo; // ammo_entity description typedef struct { string_t classname; // to link with real entity string_t ammomodel; // model to show string_t clipsound; // sound when touch entity AmmoInfo *type; // pointer to ammo specification RandomRange count; } AmmoDesc; // Items that the player has in their inventory that they can use class CBasePlayerItem : public CBaseAnimating { public: // buz: get advance spread vec to send it to client // gun dont use advanced spread by default virtual Vector GetSpreadVec( void ); // buz: gun jumping actions virtual void PlayerJump( void ); virtual void PlayerWalk( void ); virtual void PlayerRun( void ); // buz: get current weapon mode (for toggleable weapons) virtual int GetMode( void ) { if( FBitSet( iFlags(), ITEM_FLAG_SCOPE|ITEM_FLAG_IRONSIGHT ) && !m_fInReload ) { if( FBitSet( iFlags(), ITEM_FLAG_SCOPE )) return (m_iIronSight) ? 3 : 1; return (m_iIronSight + 1); } return 0; // 0 means gun dont use mode } virtual void WeaponToggleMode( void ); virtual void SetObjectCollisionBox( void ); virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; virtual int AddToPlayer( CBasePlayer *pPlayer ); // return TRUE if the item you want the item added to the player inventory virtual int AddDuplicate( CBasePlayerItem *pItem ); // return TRUE if you want your duplicate removed from world void EXPORT DestroyItem( void ); void EXPORT DefaultTouch( CBaseEntity *pOther ); // default weapon touch void EXPORT KnifeDecal1( void ); void EXPORT KnifeDecal2( void ); void Precache( void ); void Spawn( void ); // Wargon: Переменные для юзабельности оружий. void EXPORT DefaultUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { DefaultTouch( pActivator ); } virtual int ObjectCaps( void ) { return m_iItemCaps | FCAP_ACROSS_TRANSITION | FCAP_USE_ONLY; } // generic "shared" ammo handlers BOOL AddPrimaryAmmo( int iCount, const char *szName, int iMaxClip, int iMaxCarry, BOOL duplicate ); BOOL AddSecondaryAmmo( int iCount, const char *szName, int iMaxCarry ); void EXPORT FallThink ( void );// when an item is first spawned, this think is run to determine when the object has hit the ground. void EXPORT Materialize( void );// make a weapon visible and tangible void EXPORT AttemptToMaterialize( void ); // the weapon desires to become visible and tangible, if the game rules allow for it CBaseEntity* Respawn ( void );// copy a weapon void FallInit( void ); void CheckRespawn( void ); virtual int GetItemInfo( ItemInfo *p ); virtual BOOL CanDeploy( void ); virtual BOOL CanHolster( void ); // can this weapon be put away right now? virtual BOOL IsUseable( void ); virtual BOOL HasAmmo( void ); virtual BOOL WaitForHolster( void ) { return m_fWaitForHolster; } virtual BOOL AllowToDrop( void ) { return !FBitSet( iFlags(), ITEM_FLAG_NODROP ); } virtual void ItemPreFrame( void ) { return; } // called each frame by the player PreThink virtual void ItemPostFrame( void ); // called each frame by the player PostThink virtual int ExtractAmmo( CBasePlayerItem *pWeapon, BOOL duplicate ); // Return TRUE if you can add ammo to yourself when picked up virtual int ExtractClipAmmo( CBasePlayerItem *pWeapon ); // Return TRUE if you can add ammo to yourself when picked up virtual int AddWeapon( void ) { ExtractAmmo( this, FALSE ); return TRUE; }; // Return TRUE if you want to add yourself to the player virtual void PlayClientFire( const Vector &vecDir, float spread, int iAnim, int shellidx, string_t shootsnd, int cShots = 1 ); virtual void SendWeaponAnim( int iAnim, float framerate = 1.0f ); virtual void Drop( void ); virtual void Kill( void ); virtual void AttachToPlayer ( CBasePlayer *pPlayer ); virtual int PrimaryAmmoIndex( void ); virtual int SecondaryAmmoIndex( void ); virtual int UpdateClientData( CBasePlayer *pPlayer ); virtual void UpdateItemInfo( void ) {}; // updates HUD state Vector GetConeVectorForDegree( int degree ); Vector CalcSpreadVec( const spread_t *info, float &spread ); void DoEqualizeSpread( int type, float &spread ); float ExpandSpread( float expandPower ); float CalcSpread( void ); void SetDefaultParams( ItemInfo *II ); int ParseWeaponFile( ItemInfo *II, const char *filename ); // parse weapon_*.txt int ParseWeaponData( ItemInfo *II, char *file ); // parse WeaponData {} int ParsePrimaryAttack( ItemInfo *II, char *pfile ); // parse PrimaryAttack {} int ParseSecondaryAttack( ItemInfo *II, char *pfile ); // parse SeconadryAttack {} int ParseSoundData( ItemInfo *II, char *pfile ); // parse SoundData {} char *ParseViewPunch( char *pfile, feedback_t *pFeed ); int ParseItemFlags( char *pfile ); // HudData will be parsed on the client side virtual void GenerateID( void ); // generate unique ID number for each weapon virtual bool FindWeaponID( void ); int GetAnimation( Activity activity ); int SetAnimation( Activity activity, float fps = 1.0f ); int SetAnimation( char *name, float fps = 1.0f ); Activity GetIronSightActivity( Activity act ); int UseAmmo( const char *ammo, int count ); int GetAmmoType( const char *ammo ); // incredible stupid way... inline int IsEmptyReload( void ) { return m_iStepReload == EMPTY_RELOAD ? TRUE : FALSE; } int ShootGeneric( const char *ammo, int primary, int cShots = 1 ); int ThrowGeneric( const char *ammo, int primary, int cShots = 1 ); int GetCurrentAttack( const char *ammo, int primary ); int PlayCurrentAttack( int action, int primary ); void PlayAttackSound( int primary ); void ApplyPlayerSettings( bool bReset ); void SetPlayerEffects( void ); float AutoAimDelta( int primary ); float SetNextAttack( float delay ) { return m_pPlayer->m_flNextAttack = gpGlobals->time + delay; } float SetNextIdle( float delay ) { return m_flTimeWeaponIdle = gpGlobals->time + delay; } float SequenceDuration( void ) { return CBaseAnimating :: SequenceDuration( m_pPlayer->pev->weaponanim ); } static ItemInfo ItemInfoArray[MAX_WEAPONS]; static int m_iGlobalID; // unique ID for each weapon // weapon routines void ZoomUpdate( void ); void ZoomReset( void ); CBasePlayer *m_pPlayer; CBasePlayerItem *m_pNext; CLaserSpot *m_pSpot; // LTD spot (don't save this, becase spot have FCAP_DONT_SAVE flag) int m_iId; // WEAPON_??? int m_iItemCaps; TraceResult m_trHit; // for knife BOOL m_fWaitForHolster; // weapon waiting for holster string_t m_iHandModel; // in case it present // virtual methods for ItemInfo acess int iItemPosition( void ) { return ItemInfoArray[m_iId].iPosition; } int iItemSlot( void ) { return ItemInfoArray[m_iId].iSlot + 1; } int iViewModel( void ) { return ItemInfoArray[m_iId].iViewModel; } int iHandModel( void ) { return ItemInfoArray[m_iId].iHandModel; } int iWorldModel( void ) { return ItemInfoArray[m_iId].iWorldModel; } int iDefaultAmmo1( void ) { return (int)ItemInfoArray[m_iId].iDefaultAmmo1.Random(); } int iDefaultAmmo2( void ) { return (int)ItemInfoArray[m_iId].iDefaultAmmo2.Random(); } int iMaxAmmo1( void ) { return ItemInfoArray[m_iId].iMaxAmmo1; } int iMaxAmmo2( void ) { return ItemInfoArray[m_iId].iMaxAmmo2; } int iMaxClip( void ) { return ItemInfoArray[m_iId].iMaxClip; } int iWeight( void ) { return ItemInfoArray[m_iId].iWeight; } int iFlags( void ) { return ItemInfoArray[m_iId].iFlags; } int iAttack1( void ) { return ItemInfoArray[m_iId].attack1; } int sndcnt1( void ) { return ItemInfoArray[m_iId].sndcount1; } int sndcnt2( void ) { return ItemInfoArray[m_iId].sndcount2; } int emptycnt( void ) { return ItemInfoArray[m_iId].emptysndcount; } string_t ShootSnd1( void ) { return ItemInfoArray[m_iId].shootsound1[RANDOM_LONG( 0, sndcnt1( ) - 1)]; } string_t ShootSnd2( void ) { return ItemInfoArray[m_iId].shootsound2[RANDOM_LONG( 0, sndcnt2( ) - 1)]; } string_t EmptySnd( void ) { return ItemInfoArray[m_iId].emptysounds[RANDOM_LONG( 0, emptycnt() - 1)]; } int iAttack2( void ) { return ItemInfoArray[m_iId].attack2; } char *szAnimExt( void ) { return ItemInfoArray[m_iId].szAnimExt; } float fNextAttack1( void ) { return ItemInfoArray[m_iId].fNextAttack1; } float fNextAttack2( void ) { return ItemInfoArray[m_iId].fNextAttack2; } float fRecoil1( void ) { return ItemInfoArray[m_iId].recoil1.Random(); } float fRecoil2( void ) { return ItemInfoArray[m_iId].recoil2.Random(); } const char *pszAmmo1( void ) { return ItemInfoArray[m_iId].pszAmmo1; } const char *pszName( void ) { return ItemInfoArray[m_iId].pszName; } const char *pszAmmo2( void ) { return ItemInfoArray[m_iId].pszAmmo2; } const spread_t *pSpread1( void ) { return &ItemInfoArray[m_iId].spread1[m_iIronSight]; } const spread_t *pSpread2( void ) { return &ItemInfoArray[m_iId].spread2[m_iIronSight]; } const feedback_t *pFeedback1( void ) { return &ItemInfoArray[m_iId].feedback1[m_iIronSight]; } const feedback_t *pFeedback2( void ) { return &ItemInfoArray[m_iId].feedback2[m_iIronSight]; } const char *pszDecalName( int type ) { return STRING( ItemInfoArray[m_iId].smashDecals[type] ); } float ClientMaxSpeed( void ) { return ItemInfoArray[m_iId].plr_settings[m_iIronSight].maxSpeed; } float ClientJumpHeight( void ) { return ItemInfoArray[m_iId].plr_settings[m_iIronSight].jumpHeight; } Vector vecThrowOffset( void ) { return ItemInfoArray[m_iId].vecThrowOffset; } float fSpreadTime( void ) { return ItemInfoArray[m_iId].spreadtime; } int iVolume( void ) { return ItemInfoArray[m_iId].iVolume; } int iFlash( void ) { return ItemInfoArray[m_iId].iFlash; } int m_iWeaponAutoFire; // 0 - semi-auto, 1 - full auto int m_iDefaultAmmo1; // how much ammo you get when you pick up this weapon as placed by a level designer. int m_iDefaultAmmo2; // how much ammo you get when you pick up this weapon as placed by a level designer. 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_fFireOnEmpty; // True when the gun is empty and the player is still holding down the attack key(s) float m_flTimeUpdate; // special time for additional effects int m_iStepReload; // reload state (e.g. for shotgun) int m_iIronSight; // iron sight is enabled float m_flSpreadTime; // time to return from full spread float m_flLastShotTime; // time from last shot float m_flLastSpreadPower; // [0..1] range value int m_cActiveRockets; // stuff for rpg with LTD int m_iClip; // number of shots left in the primary weapon clip, -1 it not used int m_iSpot; // enable laser dot int m_iZoom; // zoom current level int m_iBody; // viewmodel body int m_iSkin; // viewmodel skin int m_fInReload; // Are we in the middle of a reload; int m_iPlayEmptySound; // trigger to playing empty sound once int m_iClientAnim; // used to resend anim on save\restore 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_iClientSkin; // the last version of m_iSkin sent to hud dll int m_iClientBody; // the last version of m_iBody sent to hud dll float m_flHoldTime; // button holdtime // this methods can be overloaded virtual void RetireWeapon( void ); virtual BOOL ShouldWeaponIdle( void ) { return FALSE; }; virtual BOOL PlayEmptySound( void ); virtual void ResetEmptySound( void ); // default methods BOOL DefaultDeploy( Activity sequence ); BOOL DefaultHolster( Activity sequence, bool force = false ); BOOL DefaultReload( Activity sequence ); BOOL DefaultSwing( int primary ); void DefaultIdle( void ); virtual void PrimaryAttack( void ) // do "+ATTACK" { if( !m_iWeaponAutoFire && !FBitSet( m_pPlayer->m_afButtonPressed, IN_ATTACK )) return; // no effect for hold button int iResult = PlayCurrentAttack( iAttack1(), true ); if( iResult == 1 ) { const feedback_t *pFB = pFeedback1(); m_pPlayer->ViewPunch( pFB->punchangle[0].Random(), pFB->punchangle[1].Random(), pFB->punchangle[2].Random() ); m_pPlayer->pev->velocity = m_pPlayer->pev->velocity - gpGlobals->v_forward * fRecoil1(); PrimaryPostAttack(); // run post effects float flNextAttack = fNextAttack1(); if( flNextAttack == -1.0f ) flNextAttack = SequenceDuration(); if( m_flNextPrimaryAttack < UTIL_WeaponTimeBase( )) m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + flNextAttack + 0.02f; m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + flNextAttack; if( HasAmmo( )) m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT( 10.0f, 15.0f ); } else if( iResult == 0 ) { float flNextAttack = 0.1f; if( GetAnimation( ACT_VM_SHOOT_EMPTY ) != -1 ) { SetAnimation( ACT_VM_SHOOT_EMPTY ); flNextAttack = SequenceDuration(); } m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + flNextAttack; PlayEmptySound(); } m_iStepReload = NOT_IN_RELOAD; // reset reload } virtual void SecondaryAttack( void ) // do "+ATTACK2" { if( !FBitSet( m_pPlayer->m_afButtonPressed, IN_ATTACK2 )) return; // no effect for hold button int iResult = PlayCurrentAttack( iAttack2(), false ); if( iResult == 1 ) { const feedback_t *pFB = pFeedback2(); m_pPlayer->ViewPunch( pFB->punchangle[0].Random(), pFB->punchangle[1].Random(), pFB->punchangle[2].Random() ); m_pPlayer->pev->velocity = m_pPlayer->pev->velocity - gpGlobals->v_forward * fRecoil2(); SecondaryPostAttack(); // run post effects float flNextAttack = fNextAttack2(); if( flNextAttack == -1.0f ) flNextAttack = SequenceDuration(); if( m_flNextSecondaryAttack < UTIL_WeaponTimeBase() ) m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + flNextAttack + 0.02f; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + flNextAttack; if( HasAmmo( )) m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT( 10.0f, 15.0f ); } else if( iResult == 0 ) { float flNextAttack = 0.1f; if( GetAnimation( ACT_VM_SHOOT_EMPTY ) != -1 ) { SetAnimation( ACT_VM_SHOOT_EMPTY ); flNextAttack = SequenceDuration(); } m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + flNextAttack; PlayEmptySound(); } m_iStepReload = NOT_IN_RELOAD; // reset reload } virtual void Reload( void ){ DefaultReload( ACT_VM_RELOAD ); } // do "+RELOAD" virtual void PrimaryPostAttack( void ) {} virtual void SecondaryPostAttack( void ) {} virtual void PostReload( void ) {} virtual void PostIdle( void ) {} // calling every frame virtual void WeaponIdle( void ){ DefaultIdle(); } // called when no buttons pressed virtual void Deploy( void ); // deploy function virtual void Holster( bool force = false ); // holster function }; class CBasePlayerAmmo : public CBaseEntity { public: void Precache( void ); void Spawn( void ); // Wargon: Переменные для юзабельности патронов. virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; void EXPORT DefaultUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { DefaultTouch( pActivator ); } virtual int ObjectCaps( void ) { return m_iAmmoCaps | FCAP_ACROSS_TRANSITION | FCAP_USE_ONLY; } virtual BOOL IsGenericAmmo( void ) { return ( FStrEq( STRING( pev->classname ), "ammo_generic" ) && pev->netname != iStringNull ); } void KeyValue( KeyValueData *pkvd ); BOOL InitGenericAmmo( void ); RandomRange m_rAmmoCount; BOOL m_bCustomAmmo; // it's a virtual entity string_t m_iAmmoType; // just store name of ammo so we can find them again int m_iAmmoCaps; static AmmoInfo AmmoInfoArray[MAX_AMMO_SLOTS]; static AmmoDesc AmmoDescArray[MAX_AMMO_DESC]; void EXPORT DefaultTouch( CBaseEntity *pOther ); // default weapon touch virtual BOOL AddAmmo( CBaseEntity *pOther ); CBaseEntity* Respawn( void ); void EXPORT Materialize( void ); }; extern DLL_GLOBAL short g_sModelIndexLaser;// holds the index for the laser beam extern DLL_GLOBAL const char *g_pModelNameLaser; extern DLL_GLOBAL short g_sModelIndexLaserDot;// holds the index for the laser beam dot extern DLL_GLOBAL short g_sModelIndexFireball;// holds the index for the fireball extern DLL_GLOBAL short g_sModelIndexSmoke;// holds the index for the smoke cloud extern DLL_GLOBAL short g_sModelIndexWExplosion;// holds the index for the underwater explosion extern DLL_GLOBAL short g_sModelIndexBubbles;// holds the index for the bubbles model extern DLL_GLOBAL short g_sModelIndexBloodDrop;// holds the sprite index for blood drops extern DLL_GLOBAL short g_sModelIndexBloodSpray;// holds the sprite index for blood spray (bigger) extern DLL_GLOBAL short g_sModelIndexWaterSplash; extern DLL_GLOBAL short g_sModelIndexSmokeTrail; extern DLL_GLOBAL short g_sModelIndexNull; extern void ClearMultiDamage( void ); extern void ApplyMultiDamage( entvars_t* pevInflictor, entvars_t* pevAttacker ); extern void AddMultiDamage( entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType ); extern void DecalGunshot( TraceResult *pTrace, int iBulletType, const Vector &vecSrc, bool fromPlayer = false ); extern void SpawnBlood(Vector vecSpot, int bloodColor, float flDamage); extern const char *DamageDecal( CBaseEntity *pEntity, int bitsDamageType ); extern void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType ); extern void UTIL_InitAmmoDescription( const char *filename ); extern void UTIL_InitWeaponDescription( const char *pattern ); extern void AddAmmoNameToAmmoRegistry( const char *szAmmoname ); extern AmmoInfo *UTIL_FindAmmoType( const char *szAmmoname ); typedef struct { CBaseEntity *pEntity; float amount; int type; } MULTIDAMAGE; extern MULTIDAMAGE gMultiDamage; #define LOUD_GUN_VOLUME 1000 #define NORMAL_GUN_VOLUME 600 #define QUIET_GUN_VOLUME 200 #define NO_GUN_VOLUME 0 #define BRIGHT_GUN_FLASH 512 #define NORMAL_GUN_FLASH 256 #define DIM_GUN_FLASH 128 #define NO_GUN_FLASH 0 #define KNIFE_BODYHIT_VOLUME 128 #define KNIFE_WALLHIT_VOLUME 512 #define BIG_EXPLOSION_VOLUME 2048 #define NORMAL_EXPLOSION_VOLUME 1024 #define SMALL_EXPLOSION_VOLUME 512 #define WEAPON_ACTIVITY_VOLUME 64 #define VECTOR_CONE_1DEGREES Vector( 0.00873, 0.00873, 0.00873 ) #define VECTOR_CONE_2DEGREES Vector( 0.01745, 0.01745, 0.01745 ) #define VECTOR_CONE_3DEGREES Vector( 0.02618, 0.02618, 0.02618 ) #define VECTOR_CONE_4DEGREES Vector( 0.03490, 0.03490, 0.03490 ) #define VECTOR_CONE_5DEGREES Vector( 0.04362, 0.04362, 0.04362 ) #define VECTOR_CONE_6DEGREES Vector( 0.05234, 0.05234, 0.05234 ) #define VECTOR_CONE_7DEGREES Vector( 0.06105, 0.06105, 0.06105 ) #define VECTOR_CONE_8DEGREES Vector( 0.06976, 0.06976, 0.06976 ) #define VECTOR_CONE_9DEGREES Vector( 0.07846, 0.07846, 0.07846 ) #define VECTOR_CONE_10DEGREES Vector( 0.08716, 0.08716, 0.08716 ) #define VECTOR_CONE_15DEGREES Vector( 0.13053, 0.13053, 0.13053 ) #define VECTOR_CONE_20DEGREES Vector( 0.17365, 0.17365, 0.17365 ) //========================================================= // CWeaponBox - a single entity that can store weapons // and ammo. //========================================================= class CWeaponBox : public CBaseAnimating { void Precache( void ); void Spawn( void ); void Touch( CBaseEntity *pOther ); void KeyValue( KeyValueData *pkvd ); BOOL IsEmpty( void ); int GiveAmmo( int iCount, const char *szName ); int MaxAmmoCarry( int iszName ); void SetObjectCollisionBox( void ); public: void EXPORT Kill( void ); int Save( CSave &save ); int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; BOOL HasWeapon( CBasePlayerItem *pCheckItem ); BOOL PackWeapon( CBasePlayerItem *pWeapon ); BOOL PackAmmo( int iszName, int iCount ); CBasePlayerItem *m_rgpPlayerItems[MAX_ITEM_TYPES];// one slot for each int m_rgiszAmmo[MAX_AMMO_SLOTS];// ammo names int m_rgAmmo[MAX_AMMO_SLOTS];// ammo quantities int m_cAmmoTypes;// how many ammo types packed into this box (if packed by a level designer) }; #endif // WEAPONS_H