2018-04-22 15:55:55 +00:00
//
// Copyright (c) 1999, 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.
//
// ===== weapons.cpp ========================================================
//
// functions governing the selection/use of weapons for players
//
// $Workfile: weapons.cpp $
// $Date: 2002/11/22 21:13:52 $
//
//-------------------------------------------------------------------------------
// $Log: weapons.cpp,v $
// Revision 1.49 2002/11/22 21:13:52 Flayra
// - mp_consistency changes
//
// Revision 1.48 2002/11/12 02:19:43 Flayra
// - Fixed problem where friendly bulletfire was doing damage
//
// Revision 1.47 2002/10/24 21:19:11 Flayra
// - Reworked jetpack effects
// - Added a few extra sounds
//
// Revision 1.46 2002/10/16 00:41:15 Flayra
// - Removed unneeds sounds and events
// - Added distress beacon event
// - Added general purpose particle event
//
// Revision 1.45 2002/09/25 20:40:09 Flayra
// - Play different sound for aliens when they get weapons
//
// Revision 1.44 2002/09/23 22:04:00 Flayra
// - Regular update
//
// Revision 1.43 2002/08/31 18:01:18 Flayra
// - Work at VALVe
//
// Revision 1.42 2002/07/26 23:01:05 Flayra
// - Precache numerical feedback event
//
// Revision 1.41 2002/07/23 16:48:37 Flayra
// - Added distress beacon
//
// Revision 1.40 2002/07/08 16:35:17 Flayra
// - Added document header, updates for cheat protection, added constants
//
//===============================================================================
# include "../util/nowarnings.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"
# include "../mod/AvHConstants.h"
# include "../mod/AvHMarineEquipmentConstants.h"
# include "../mod/AvHAlienWeaponConstants.h"
# include "../mod/AvHAlienEquipmentConstants.h"
# include "../mod/AvHPlayer.h"
# include "../mod/AvHGamerules.h"
# include "../mod/AvHNetworkMessages.h"
extern CGraph WorldGraph ;
extern int gEvilImpulse101 ;
int gJetpackEventID ;
int gStartOverwatchEventID ;
int gEndOverwatchEventID ;
int gTeleportEventID ;
int gBlinkEffectSuccessEventID ;
int gPhaseInEventID ;
int gSiegeHitEventID ;
int gSiegeViewHitEventID ;
int gCommanderPointsAwardedEventID ;
int gAlienSightOnEventID ;
int gAlienSightOffEventID ;
//int gParalysisStartEventID;
int gRegenerationEventID ;
int gStartCloakEventID ;
int gEndCloakEventID ;
int gSporeCloudEventID ;
int gUmbraCloudEventID ;
int gStopScreamEventID ;
int gWelderEventID ;
int gWelderConstEventID ;
//int gWallJumpEventID;
//int gFlightEventID;
int gEmptySoundEventID ;
int gNumericalInfoEventID ;
int gInvalidActionEventID ;
int gParticleEventID ;
int gDistressBeaconEventID ;
int gWeaponAnimationEventID ;
int gLevelUpEventID ;
int gMetabolizeSuccessEventID ;
# define NOT_USED 255
DLL_GLOBAL short g_sModelIndexLaser ; // holds the index for the laser beam
DLL_GLOBAL const char * g_pModelNameLaser = " sprites/laserbeam.spr " ;
DLL_GLOBAL short g_sModelIndexLaserDot ; // holds the index for the laser beam dot
DLL_GLOBAL short g_sModelIndexFireball ; // holds the index for the fireball
DLL_GLOBAL short g_sModelIndexSmoke ; // holds the index for the smoke cloud
DLL_GLOBAL short g_sModelIndexWExplosion ; // holds the index for the underwater explosion
DLL_GLOBAL short g_sModelIndexBubbles ; // holds the index for the bubbles model
DLL_GLOBAL short g_sModelIndexBloodDrop ; // holds the sprite index for the initial blood
DLL_GLOBAL short g_sModelIndexBloodSpray ; // holds the sprite index for splattered blood
ItemInfo CBasePlayerItem : : ItemInfoArray [ MAX_WEAPONS ] ;
AmmoInfo CBasePlayerItem : : AmmoInfoArray [ MAX_AMMO_SLOTS ] ;
MULTIDAMAGE gMultiDamage ;
# define TRACER_FREQ 4 // Tracers fire every fourth bullet
extern bool gCanMove [ ] ;
//=========================================================
// MaxAmmoCarry - pass in a name and this function will tell
// you the maximum amount of that type of ammunition that a
// player can carry.
//=========================================================
int MaxAmmoCarry ( int iszName )
{
for ( int i = 0 ; i < MAX_WEAPONS ; i + + )
{
if ( CBasePlayerItem : : ItemInfoArray [ i ] . pszAmmo1 & & ! strcmp ( STRING ( iszName ) , CBasePlayerItem : : ItemInfoArray [ i ] . pszAmmo1 ) )
return CBasePlayerItem : : ItemInfoArray [ i ] . iMaxAmmo1 ;
if ( CBasePlayerItem : : ItemInfoArray [ i ] . pszAmmo2 & & ! strcmp ( STRING ( iszName ) , CBasePlayerItem : : ItemInfoArray [ i ] . pszAmmo2 ) )
return CBasePlayerItem : : ItemInfoArray [ i ] . iMaxAmmo2 ;
}
ALERT ( at_console , " MaxAmmoCarry() doesn't recognize '%s'! \n " , STRING ( iszName ) ) ;
return - 1 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
MULTI - DAMAGE
Collects multiple small damages into a single damage
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
//
// ClearMultiDamage - resets the global multi damage accumulator
//
void ClearMultiDamage ( void )
{
gMultiDamage . pEntity = NULL ;
gMultiDamage . amount = 0 ;
gMultiDamage . type = 0 ;
}
//
// ApplyMultiDamage - inflicts contents of global multi damage register on gMultiDamage.pEntity
//
// GLOBALS USED:
// gMultiDamage
void ApplyMultiDamage ( entvars_t * pevInflictor , entvars_t * pevAttacker )
{
Vector vecSpot1 ; //where blood comes from
Vector vecDir ; //direction blood should go
TraceResult tr ;
if ( ! gMultiDamage . pEntity )
return ;
float theDamage = gMultiDamage . amount ;
gMultiDamage . pEntity - > TakeDamage ( pevInflictor , pevAttacker , theDamage , gMultiDamage . type ) ;
}
// GLOBALS USED:
// gMultiDamage
void AddMultiDamage ( entvars_t * pevInflictor , CBaseEntity * pEntity , float flDamage , int bitsDamageType )
{
if ( ! pEntity )
return ;
gMultiDamage . type | = bitsDamageType ;
if ( pEntity ! = gMultiDamage . pEntity )
{
ApplyMultiDamage ( pevInflictor , pevInflictor ) ; // UNDONE: wrong attacker!
gMultiDamage . pEntity = pEntity ;
gMultiDamage . amount = 0 ;
}
gMultiDamage . amount + = flDamage ;
}
/*
= = = = = = = = = = = = = = = =
SpawnBlood
= = = = = = = = = = = = = = = =
*/
void SpawnBlood ( Vector vecSpot , int bloodColor , float flDamage )
{
if ( flDamage > = 0.0f )
{
if ( bloodColor = = DONT_BLEED )
{
UTIL_Sparks ( vecSpot ) ;
}
else
{
UTIL_BloodDrips ( vecSpot , g_vecAttackDir , bloodColor , ( int ) flDamage ) ;
}
}
}
int DamageDecal ( CBaseEntity * pEntity , int bitsDamageType )
{
if ( ! pEntity )
return ( DECAL_GUNSHOT1 + RANDOM_LONG ( 0 , 4 ) ) ;
return pEntity - > DamageDecal ( bitsDamageType ) ;
}
void DecalGunshot ( TraceResult * pTrace , int iBulletType )
{
// Is the entity valid
if ( ! UTIL_IsValidEntity ( pTrace - > pHit ) )
return ;
if ( VARS ( pTrace - > pHit ) - > solid = = SOLID_BSP | | VARS ( pTrace - > pHit ) - > movetype = = MOVETYPE_PUSHSTEP )
{
CBaseEntity * pEntity = NULL ;
// Decal the wall with a gunshot
if ( ! FNullEnt ( pTrace - > pHit ) )
pEntity = CBaseEntity : : Instance ( pTrace - > pHit ) ;
// switch( iBulletType )
// {
// case BULLET_PLAYER_9MM:
// case BULLET_MONSTER_9MM:
// case BULLET_PLAYER_MP5:
// case BULLET_MONSTER_MP5:
// case BULLET_PLAYER_BUCKSHOT:
// case BULLET_PLAYER_357:
// default:
// smoke and decal
UTIL_GunshotDecalTrace ( pTrace , DamageDecal ( pEntity , DMG_BULLET ) ) ;
// break;
// case BULLET_MONSTER_12MM:
// // smoke and decal
// UTIL_GunshotDecalTrace( pTrace, DamageDecal( pEntity, DMG_BULLET ) );
// break;
// case BULLET_PLAYER_CROWBAR:
// // wall decal
// UTIL_DecalTrace( pTrace, DamageDecal( pEntity, DMG_CLUB ) );
// break;
// }
}
}
//
// EjectBrass - tosses a brass shell from passed origin at passed velocity
//
void EjectBrass ( const Vector & vecOrigin , const Vector & vecVelocity , float rotation , int model , int soundtype )
{
// FIX: when the player shoots, their gun isn't in the same position as it is on the model other players see.
MESSAGE_BEGIN ( MSG_PVS , SVC_TEMPENTITY , vecOrigin ) ;
WRITE_BYTE ( TE_MODEL ) ;
WRITE_COORD ( vecOrigin . x ) ;
WRITE_COORD ( vecOrigin . y ) ;
WRITE_COORD ( vecOrigin . z ) ;
WRITE_COORD ( vecVelocity . x ) ;
WRITE_COORD ( vecVelocity . y ) ;
WRITE_COORD ( vecVelocity . z ) ;
WRITE_ANGLE ( rotation ) ;
WRITE_SHORT ( model ) ;
WRITE_BYTE ( soundtype ) ;
WRITE_BYTE ( 25 ) ; // 2.5 seconds
MESSAGE_END ( ) ;
}
#if 0
// UNDONE: This is no longer used?
void ExplodeModel ( const Vector & vecOrigin , float speed , int model , int count )
{
MESSAGE_BEGIN ( MSG_PVS , SVC_TEMPENTITY , vecOrigin ) ;
WRITE_BYTE ( TE_EXPLODEMODEL ) ;
WRITE_COORD ( vecOrigin . x ) ;
WRITE_COORD ( vecOrigin . y ) ;
WRITE_COORD ( vecOrigin . z ) ;
WRITE_COORD ( speed ) ;
WRITE_SHORT ( model ) ;
WRITE_SHORT ( count ) ;
WRITE_BYTE ( 15 ) ; // 1.5 seconds
MESSAGE_END ( ) ;
}
# endif
int giAmmoIndex = 0 ;
// Precaches the ammo and queues the ammo info for sending to clients
void AddAmmoNameToAmmoRegistry ( const char * szAmmoname )
{
// make sure it's not already in the registry
for ( int i = 0 ; i < MAX_AMMO_SLOTS ; i + + )
{
if ( ! CBasePlayerItem : : AmmoInfoArray [ i ] . pszName )
continue ;
if ( stricmp ( CBasePlayerItem : : AmmoInfoArray [ i ] . pszName , szAmmoname ) = = 0 )
return ; // ammo already in registry, just quite
}
giAmmoIndex + + ;
ASSERT ( giAmmoIndex < MAX_AMMO_SLOTS ) ;
if ( giAmmoIndex > = MAX_AMMO_SLOTS )
giAmmoIndex = 0 ;
CBasePlayerItem : : AmmoInfoArray [ giAmmoIndex ] . pszName = szAmmoname ;
CBasePlayerItem : : AmmoInfoArray [ giAmmoIndex ] . iId = giAmmoIndex ; // yes, this info is redundant
}
// Precaches the weapon and queues the weapon info for sending to clients
void UTIL_PrecacheOtherWeapon ( const char * szClassname )
{
edict_t * pent ;
pent = CREATE_NAMED_ENTITY ( MAKE_STRING ( szClassname ) ) ;
if ( FNullEnt ( pent ) )
{
ALERT ( at_console , " NULL Ent in UTIL_PrecacheOtherWeapon \n " ) ;
return ;
}
CBaseEntity * pEntity = CBaseEntity : : Instance ( VARS ( pent ) ) ;
if ( pEntity )
{
ItemInfo II ;
pEntity - > Precache ( ) ;
memset ( & II , 0 , sizeof II ) ;
if ( ( ( CBasePlayerItem * ) pEntity ) - > GetItemInfo ( & II ) )
{
CBasePlayerItem : : ItemInfoArray [ II . iId ] = II ;
if ( II . pszAmmo1 & & * II . pszAmmo1 )
{
AddAmmoNameToAmmoRegistry ( II . pszAmmo1 ) ;
}
if ( II . pszAmmo2 & & * II . pszAmmo2 )
{
AddAmmoNameToAmmoRegistry ( II . pszAmmo2 ) ;
}
memset ( & II , 0 , sizeof II ) ;
}
}
REMOVE_ENTITY ( pent ) ;
}
// called by worldspawn
void W_Precache ( void )
{
memset ( CBasePlayerItem : : ItemInfoArray , 0 , sizeof ( CBasePlayerItem : : ItemInfoArray ) ) ;
memset ( CBasePlayerItem : : AmmoInfoArray , 0 , sizeof ( CBasePlayerItem : : AmmoInfoArray ) ) ;
giAmmoIndex = 0 ;
// Marine weapons
//UTIL_PrecacheOtherWeapon("weapon_9mmhandgun");
//UTIL_PrecacheOtherWeapon("weapon_glock");
//UTIL_PrecacheOther("ammo_9mmclip");
// Player assets
PRECACHE_UNMODIFIED_MODEL ( kReadyRoomModel ) ;
PRECACHE_UNMODIFIED_MODEL ( kMarineSoldierModel ) ;
PRECACHE_UNMODIFIED_MODEL ( kHeavySoldierModel ) ;
PRECACHE_UNMODIFIED_MODEL ( kAlienLevelOneModel ) ;
PRECACHE_UNMODIFIED_SOUND ( kDistressBeaconSound ) ;
PRECACHE_UNMODIFIED_SOUND ( kLevelUpMarineSound ) ;
PRECACHE_UNMODIFIED_SOUND ( kLevelUpAlienSound ) ;
PRECACHE_UNMODIFIED_SOUND ( kAlienBuildingSound1 ) ;
PRECACHE_UNMODIFIED_SOUND ( kAlienBuildingSound2 ) ;
PRECACHE_SOUND ( kMyHiveEasterEgg ) ;
//PRECACHE_UNMODIFIED_SOUND(kAlienAbilitiesGrantedSound);
//PRECACHE_UNMODIFIED_SOUND(kAlienAbilitiesLostSound);
PRECACHE_UNMODIFIED_MODEL ( kAlienLevelTwoModel ) ;
PRECACHE_UNMODIFIED_MODEL ( kAlienLevelThreeModel ) ;
PRECACHE_UNMODIFIED_MODEL ( kAlienLevelFourModel ) ;
PRECACHE_UNMODIFIED_MODEL ( kAlienLevelFiveModel ) ;
PRECACHE_UNMODIFIED_MODEL ( kMarineCommanderModel ) ;
PRECACHE_UNMODIFIED_MODEL ( kAlienGestateModel ) ;
// : 1072
// Added some client side consistency checks.
PRECACHE_UNMODIFIED_MODEL ( " sprites/muzzleflash1.spr " ) ;
PRECACHE_UNMODIFIED_MODEL ( " sprites/muzzleflash2.spr " ) ;
PRECACHE_UNMODIFIED_MODEL ( " sprites/muzzleflash3.spr " ) ;
PRECACHE_UNMODIFIED_MODEL ( " sprites/digesting.spr " ) ;
PRECACHE_UNMODIFIED_MODEL ( " sprites/membrane.spr " ) ;
PRECACHE_UNMODIFIED_MODEL ( " sprites/hera_fog.spr " ) ;
PRECACHE_UNMODIFIED_MODEL ( " sprites/spore.spr " ) ;
PRECACHE_UNMODIFIED_MODEL ( " sprites/spore2.spr " ) ;
PRECACHE_UNMODIFIED_MODEL ( " sprites/umbra.spr " ) ;
PRECACHE_UNMODIFIED_MODEL ( " sprites/umbra2.spr " ) ;
PRECACHE_UNMODIFIED_MODEL ( " sprites/webstrand.spr " ) ;
UTIL_PrecacheOtherWeapon ( kwsMine ) ;
UTIL_PrecacheOtherWeapon ( kwsKnife ) ;
UTIL_PrecacheOtherWeapon ( kwsMachineGun ) ;
UTIL_PrecacheOtherWeapon ( kwsPistol ) ;
UTIL_PrecacheOtherWeapon ( kwsShotGun ) ;
UTIL_PrecacheOtherWeapon ( kwsHeavyMachineGun ) ;
UTIL_PrecacheOtherWeapon ( kwsGrenadeGun ) ;
UTIL_PrecacheOtherWeapon ( kwsGrenade ) ;
// Alien weapons
UTIL_PrecacheOtherWeapon ( kwsSpitGun ) ;
UTIL_PrecacheOther ( kwsSpitProjectile ) ;
UTIL_PrecacheOther ( kwsWebProjectile ) ;
UTIL_PrecacheOtherWeapon ( kwsClaws ) ;
UTIL_PrecacheOtherWeapon ( kwsSwipe ) ;
UTIL_PrecacheOtherWeapon ( kwsSporeGun ) ;
UTIL_PrecacheOther ( kwsSporeProjectile ) ;
// UTIL_PrecacheOtherWeapon(kwsParalysisGun);
UTIL_PrecacheOtherWeapon ( kwsSpikeGun ) ;
UTIL_PrecacheOtherWeapon ( kwsBiteGun ) ;
UTIL_PrecacheOtherWeapon ( kwsBite2Gun ) ;
UTIL_PrecacheOtherWeapon ( kwsHealingSpray ) ;
UTIL_PrecacheOtherWeapon ( kwsWebSpinner ) ;
// UTIL_PrecacheOtherWeapon(kwsBabblerGun);
UTIL_PrecacheOtherWeapon ( kwsPrimalScream ) ;
UTIL_PrecacheOtherWeapon ( kwsParasiteGun ) ;
UTIL_PrecacheOtherWeapon ( kwsMetabolize ) ;
UTIL_PrecacheOtherWeapon ( kwsUmbraGun ) ;
UTIL_PrecacheOtherWeapon ( kwsBlinkGun ) ;
UTIL_PrecacheOtherWeapon ( kwsDivineWind ) ;
UTIL_PrecacheOtherWeapon ( kwsBileBombGun ) ;
UTIL_PrecacheOtherWeapon ( kwsAcidRocketGun ) ;
UTIL_PrecacheOtherWeapon ( kwsStomp ) ;
UTIL_PrecacheOtherWeapon ( kwsDevour ) ;
// UTIL_PrecacheOtherWeapon(kwsAmplify);
UTIL_PrecacheOther ( kwsBileBomb ) ;
// Alien abilities
UTIL_PrecacheOtherWeapon ( kwsLeap ) ;
UTIL_PrecacheOtherWeapon ( kwsCharge ) ;
// Alien buildings
UTIL_PrecacheOther ( kwsAlienResourceTower ) ;
UTIL_PrecacheOther ( kwsOffenseChamber ) ;
UTIL_PrecacheOther ( kwsDefenseChamber ) ;
UTIL_PrecacheOther ( kwsSensoryChamber ) ;
UTIL_PrecacheOther ( kwsMovementChamber ) ;
UTIL_PrecacheOther ( kesTeamWebStrand ) ;
// Equipment
//UTIL_PrecacheOtherWeapon("weapon_tripmine");
UTIL_PrecacheOther ( kwsScan ) ;
UTIL_PrecacheOther ( kwsPhaseGate ) ;
//UTIL_PrecacheOther(kwsNuke);
// Marine buildings
UTIL_PrecacheOther ( kwsTeamCommand ) ;
UTIL_PrecacheOther ( kwsResourceTower ) ;
UTIL_PrecacheOther ( kwsInfantryPortal ) ;
UTIL_PrecacheOther ( kwsTurretFactory ) ;
UTIL_PrecacheOther ( kwsArmory ) ;
UTIL_PrecacheOther ( kwsAdvancedArmory ) ;
UTIL_PrecacheOther ( kwsArmsLab ) ;
UTIL_PrecacheOther ( kwsPrototypeLab ) ;
UTIL_PrecacheOther ( kwsObservatory ) ;
//UTIL_PrecacheOther(kwsChemlab);
//UTIL_PrecacheOther(kwsMedlab);
//UTIL_PrecacheOther(kwsNukePlant);
UTIL_PrecacheOther ( kwsDeployedTurret ) ;
UTIL_PrecacheOther ( kwsSiegeTurret ) ;
// container for dropped deathmatch weapons
UTIL_PrecacheOther ( " weaponbox " ) ;
UTIL_PrecacheOtherWeapon ( kwsWelder ) ;
UTIL_PrecacheOther ( kwsDeployedMine ) ;
UTIL_PrecacheOther ( kwsHealth ) ;
UTIL_PrecacheOther ( kwsCatalyst ) ;
UTIL_PrecacheOther ( kwsGenericAmmo ) ;
UTIL_PrecacheOther ( kwsHeavyArmor ) ;
UTIL_PrecacheOther ( kwsJetpack ) ;
UTIL_PrecacheOther ( kwsAmmoPack ) ;
UTIL_PrecacheOther ( kwsDebugEntity ) ;
// Precache other events
gJetpackEventID = PRECACHE_EVENT ( 1 , kJetpackEvent ) ;
//gStartOverwatchEventID = PRECACHE_EVENT(1, kStartOverwatchEvent);
//gEndOverwatchEventID = PRECACHE_EVENT(1, kEndOverwatchEvent);
// Alien upgrade events
gRegenerationEventID = PRECACHE_EVENT ( 1 , kRegenerationEvent ) ;
gStartCloakEventID = PRECACHE_EVENT ( 1 , kStartCloakEvent ) ;
gEndCloakEventID = PRECACHE_EVENT ( 1 , kEndCloakEvent ) ;
// Extra alien weapon events
//gEnsnareHitEventID = PRECACHE_EVENT(1, kEnsnareHitEventName);
gSporeCloudEventID = PRECACHE_EVENT ( 1 , kSporeCloudEventName ) ;
gUmbraCloudEventID = PRECACHE_EVENT ( 1 , kUmbraCloudEventName ) ;
gStopScreamEventID = PRECACHE_EVENT ( 1 , kStopPrimalScreamSoundEvent ) ;
// Extra marine events
gTeleportEventID = PRECACHE_EVENT ( 1 , kTeleportEvent ) ;
gBlinkEffectSuccessEventID = PRECACHE_EVENT ( 1 , kBlinkEffectSuccessEventName ) ;
gPhaseInEventID = PRECACHE_EVENT ( 1 , kPhaseInEvent ) ;
gSiegeHitEventID = PRECACHE_EVENT ( 1 , kSiegeHitEvent ) ;
gSiegeViewHitEventID = PRECACHE_EVENT ( 1 , kSiegeViewHitEvent ) ;
gCommanderPointsAwardedEventID = PRECACHE_EVENT ( 1 , kCommanderPointsAwardedEvent ) ;
gAlienSightOnEventID = PRECACHE_EVENT ( 1 , kAlienSightOnEvent ) ;
gAlienSightOffEventID = PRECACHE_EVENT ( 1 , kAlienSightOffEvent ) ;
// gParalysisStartEventID = PRECACHE_EVENT(1, kParalysisStartEventName);
//gWallJumpEventID = PRECACHE_EVENT(1, kWallJumpEvent);
//gFlightEventID = PRECACHE_EVENT(1, kFlightEvent);
PRECACHE_UNMODIFIED_SOUND ( kConnectSound ) ;
//PRECACHE_UNMODIFIED_SOUND(kDisconnectSound);
PRECACHE_UNMODIFIED_MODEL ( kNullModel ) ;
UTIL_PrecacheOther ( " monster_sentry " ) ;
// Allow welder events in mapper build
gWelderEventID = PRECACHE_EVENT ( 1 , kWelderEventName ) ;
gWelderConstEventID = PRECACHE_EVENT ( 1 , kWelderConstEventName ) ;
PRECACHE_EVENT ( 1 , kWelderStartEventName ) ;
PRECACHE_EVENT ( 1 , kWelderEndEventName ) ;
gEmptySoundEventID = PRECACHE_EVENT ( 1 , kEmptySoundEvent ) ;
gNumericalInfoEventID = PRECACHE_EVENT ( 1 , kNumericalInfoEvent ) ;
gInvalidActionEventID = PRECACHE_EVENT ( 1 , kInvalidActionEvent ) ;
gParticleEventID = PRECACHE_EVENT ( 1 , kParticleEvent ) ;
gDistressBeaconEventID = PRECACHE_EVENT ( 1 , kDistressBeaconEvent ) ;
gWeaponAnimationEventID = PRECACHE_EVENT ( 1 , kWeaponAnimationEvent ) ;
gLevelUpEventID = PRECACHE_EVENT ( 1 , kLevelUpEvent ) ;
gMetabolizeSuccessEventID = PRECACHE_EVENT ( 1 , kMetabolizeSuccessEventName ) ;
PRECACHE_UNMODIFIED_SOUND ( kPhaseInSound ) ;
// Precache reload sound that is hardcoded deep in HL
PRECACHE_UNMODIFIED_SOUND ( kEmptySound ) ;
PRECACHE_UNMODIFIED_SOUND ( kInvalidSound ) ;
// Not sure who's using these, but I keep getting errors that they're not precached. Buttons?
PRECACHE_UNMODIFIED_SOUND ( " buttons/spark1.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " buttons/spark2.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " buttons/spark3.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " buttons/spark4.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " buttons/spark5.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " buttons/spark6.wav " ) ;
// For grunts. Careful, this uses the same weapon id that the grenade gun uses
//UTIL_PrecacheOtherWeapon("weapon_9mmAR");
// common world objects
// UTIL_PrecacheOther( "item_suit" );
// UTIL_PrecacheOther( "item_battery" );
// UTIL_PrecacheOther( "item_antidote" );
// UTIL_PrecacheOther( "item_security" );
// UTIL_PrecacheOther( "item_longjump" );
// shotgun
// UTIL_PrecacheOtherWeapon( "weapon_shotgun" );
// UTIL_PrecacheOther( "ammo_buckshot" );
//
// // crowbar
// UTIL_PrecacheOtherWeapon( "weapon_rowbar" );
//
// // glock
// UTIL_PrecacheOtherWeapon( "weapon_9mmhandgun" );
// UTIL_PrecacheOther( "ammo_9mmclip" );
//
// // mp5
// UTIL_PrecacheOtherWeapon( "weapon_9mmAR" );
// UTIL_PrecacheOther( "ammo_9mmAR" );
// UTIL_PrecacheOther( "ammo_ARgrenades" );
//#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
// // python
// UTIL_PrecacheOtherWeapon( "weapon_357" );
// UTIL_PrecacheOther( "ammo_357" );
//#endif
//
//#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
// // gauss
// UTIL_PrecacheOtherWeapon( "weapon_gauss" );
// UTIL_PrecacheOther( "ammo_gaussclip" );
//#endif
//
//#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
// // rpg
// UTIL_PrecacheOtherWeapon( "weapon_rpg" );
// UTIL_PrecacheOther( "ammo_rpgclip" );
//#endif
//
//#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
// // crossbow
// UTIL_PrecacheOtherWeapon( "weapon_crossbow" );
// UTIL_PrecacheOther( "ammo_crossbow" );
// UTIL_PrecacheOther( "weaponbox" );// container for dropped deathmatch weapons
//#endif
//
//#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
// // egon
// UTIL_PrecacheOtherWeapon( "weapon_egon" );
//#endif
//
//#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
// // satchel charge
// UTIL_PrecacheOtherWeapon( "weapon_satchel" );
//#endif
//
// // hand grenade
// UTIL_PrecacheOtherWeapon("weapon_handgrenade");
//
//
//#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
// // squeak grenade
// UTIL_PrecacheOtherWeapon( "weapon_snark" );
//#endif
//
//#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
// // hornetgun
// UTIL_PrecacheOtherWeapon( "weapon_hornetgun" );
//#endif
//#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
// if ( g_pGameRules->IsDeathmatch() )
// {
// UTIL_PrecacheOther( "weaponbox" );// container for dropped deathmatch weapons
// }
//#endif
g_sModelIndexFireball = PRECACHE_UNMODIFIED_MODEL ( " sprites/zerogxplode.spr " ) ; // fireball
g_sModelIndexWExplosion = PRECACHE_UNMODIFIED_MODEL ( " sprites/WXplo1.spr " ) ; // underwater fireball
g_sModelIndexSmoke = PRECACHE_UNMODIFIED_MODEL ( " sprites/steam1.spr " ) ; // smoke
g_sModelIndexBubbles = PRECACHE_UNMODIFIED_MODEL ( " sprites/bubble2.spr " ) ; //bubbles
g_sModelIndexBloodSpray = PRECACHE_UNMODIFIED_MODEL ( " sprites/bloodspray.spr " ) ; // initial blood
g_sModelIndexBloodDrop = PRECACHE_UNMODIFIED_MODEL ( " sprites/blood.spr " ) ; // splattered blood
g_sModelIndexLaser = PRECACHE_UNMODIFIED_MODEL ( ( char * ) g_pModelNameLaser ) ;
g_sModelIndexLaserDot = PRECACHE_UNMODIFIED_MODEL ( " sprites/laserdot.spr " ) ;
// used by explosions
PRECACHE_UNMODIFIED_MODEL ( " models/grenade.mdl " ) ;
PRECACHE_UNMODIFIED_MODEL ( " sprites/explode1.spr " ) ;
PRECACHE_SOUND ( " weapons/debris1.wav " ) ; // explosion aftermaths
PRECACHE_SOUND ( " weapons/debris2.wav " ) ; // explosion aftermaths
PRECACHE_SOUND ( " weapons/debris3.wav " ) ; // explosion aftermaths
PRECACHE_UNMODIFIED_SOUND ( kGrenadeBounceSound1 ) ;
PRECACHE_UNMODIFIED_SOUND ( kGrenadeBounceSound2 ) ;
PRECACHE_UNMODIFIED_SOUND ( kGrenadeBounceSound3 ) ;
PRECACHE_UNMODIFIED_SOUND ( kGRHitSound ) ;
PRECACHE_UNMODIFIED_SOUND ( " weapons/bullet_hit1.wav " ) ; // hit by bullet
PRECACHE_UNMODIFIED_SOUND ( " weapons/bullet_hit2.wav " ) ; // hit by bullet
PRECACHE_UNMODIFIED_SOUND ( " items/weapondrop1.wav " ) ; // weapon falls to the ground
}
TYPEDESCRIPTION CBasePlayerItem : : m_SaveData [ ] =
{
DEFINE_FIELD ( CBasePlayerItem , m_pPlayer , FIELD_CLASSPTR ) ,
DEFINE_FIELD ( CBasePlayerItem , m_pNext , FIELD_CLASSPTR ) ,
DEFINE_FIELD ( CBasePlayerItem , m_iId , FIELD_INTEGER ) ,
} ;
IMPLEMENT_SAVERESTORE ( CBasePlayerItem , CBaseAnimating ) ;
TYPEDESCRIPTION CBasePlayerWeapon : : m_SaveData [ ] =
{
DEFINE_FIELD ( CBasePlayerWeapon , m_flNextPrimaryAttack , FIELD_TIME ) ,
DEFINE_FIELD ( CBasePlayerWeapon , m_flNextSecondaryAttack , FIELD_TIME ) ,
DEFINE_FIELD ( CBasePlayerWeapon , m_flTimeWeaponIdle , FIELD_TIME ) ,
DEFINE_FIELD ( CBasePlayerWeapon , m_iPrimaryAmmoType , FIELD_INTEGER ) ,
DEFINE_FIELD ( CBasePlayerWeapon , m_iSecondaryAmmoType , FIELD_INTEGER ) ,
DEFINE_FIELD ( CBasePlayerWeapon , m_iClip , FIELD_INTEGER ) ,
DEFINE_FIELD ( CBasePlayerWeapon , m_iDefaultAmmo , FIELD_INTEGER ) ,
} ;
IMPLEMENT_SAVERESTORE ( CBasePlayerWeapon , CBasePlayerItem ) ;
void CBasePlayerItem : : SetObjectCollisionBox ( void )
{
pev - > absmin = pev - > origin + Vector ( - 24 , - 24 , 0 ) ;
pev - > absmax = pev - > origin + Vector ( 24 , 24 , 16 ) ;
}
BOOL
CBasePlayerItem : : CanDeploy ( void )
{
return TRUE ;
}
// can this weapon be put away right now?
BOOL CBasePlayerItem : : CanHolster ( void )
{
return TRUE ;
} ;
// returns is deploy was successful
BOOL CBasePlayerItem : : Deploy ( )
{
return TRUE ;
}
BOOL
CBasePlayerItem : : IsUseable ( void )
{
return TRUE ;
}
//=========================================================
// Sets up movetype, size, solidtype for a new weapon.
//=========================================================
void CBasePlayerItem : : FallInit ( void )
{
pev - > movetype = MOVETYPE_TOSS ;
2021-01-20 20:36:37 +00:00
//SOLID_BBOX caused weapons to get stuck on eachother and float in air
pev - > solid = SOLID_BSP ;
2018-04-22 15:55:55 +00:00
UTIL_SetOrigin ( pev , pev - > origin ) ;
UTIL_SetSize ( pev , Vector ( 0 , 0 , 0 ) , Vector ( 0 , 0 , 0 ) ) ; //pointsize until it lands on the ground.
SetTouch ( & CBasePlayerItem : : DefaultTouch ) ;
SetThink ( & CBasePlayerItem : : FallThink ) ;
pev - > nextthink = gpGlobals - > time + 0.1 ;
}
//=========================================================
// FallThink - Items that have just spawned run this think
// to catch them when they hit the ground. Once we're sure
// that the object is grounded, we change its solid type
// to trigger and set it in a large box that helps the
// player get it.
//=========================================================
void CBasePlayerItem : : FallThink ( void )
{
pev - > nextthink = gpGlobals - > time + 0.1 ;
2021-01-20 20:36:37 +00:00
//timer for weapons stuck floating in air
pev - > fuser4 + = 0.1 ;
2018-04-22 15:55:55 +00:00
if ( pev - > flags & FL_ONGROUND )
{
// clatter if we have an owner (i.e., dropped by someone)
// don't clatter if the gun is waiting to respawn (if it's waiting, it is invisible!)
if ( ! FNullEnt ( pev - > owner ) )
{
int pitch = 95 + RANDOM_LONG ( 0 , 29 ) ;
EMIT_SOUND_DYN ( ENT ( pev ) , CHAN_VOICE , " items/weapondrop1.wav " , 1 , ATTN_NORM , 0 , pitch ) ;
}
// lie flat
pev - > angles . x = 0 ;
pev - > angles . z = 0 ;
2021-01-20 20:36:37 +00:00
Materialize ( ) ;
pev - > fuser4 = 0 ;
}
//weapons in air for too long from collision issues with other entities change to SOLID_TRIGGER to fall to ground
if ( ( pev - > fuser4 > 0.7 ) )
{
pev - > solid = SOLID_TRIGGER ;
pev - > fuser4 = 0 ;
2018-04-22 15:55:55 +00:00
}
}
//=========================================================
// Materialize - make a CBasePlayerItem visible and tangible
//=========================================================
void CBasePlayerItem : : Materialize ( void )
{
if ( pev - > effects & EF_NODRAW )
{
// changing from invisible state to visible.
EMIT_SOUND_DYN ( ENT ( pev ) , CHAN_WEAPON , " items/suitchargeok1.wav " , 1 , ATTN_NORM , 0 , 150 ) ;
pev - > effects & = ~ EF_NODRAW ;
pev - > effects | = EF_MUZZLEFLASH ;
}
pev - > solid = SOLID_TRIGGER ;
UTIL_SetOrigin ( pev , pev - > origin ) ; // link into world.
SetTouch ( & CBasePlayerItem : : DefaultTouch ) ;
SetThink ( NULL ) ;
this - > VirtualMaterialize ( ) ;
}
//=========================================================
// AttemptToMaterialize - the item is trying to rematerialize,
// should it do so now or wait longer?
//=========================================================
void CBasePlayerItem : : AttemptToMaterialize ( void )
{
float time = g_pGameRules - > FlWeaponTryRespawn ( this ) ;
if ( time = = 0 )
{
Materialize ( ) ;
return ;
}
pev - > nextthink = gpGlobals - > time + time ;
}
//=========================================================
// CheckRespawn - a player is taking this weapon, should
// it respawn?
//=========================================================
void CBasePlayerItem : : CheckRespawn ( void )
{
switch ( g_pGameRules - > WeaponShouldRespawn ( this ) )
{
case GR_WEAPON_RESPAWN_YES :
Respawn ( ) ;
break ;
case GR_WEAPON_RESPAWN_NO :
return ;
break ;
}
}
//=========================================================
// Respawn- this item is already in the world, but it is
// invisible and intangible. Make it visible and tangible.
//=========================================================
CBaseEntity * CBasePlayerItem : : Respawn ( void )
{
// make a copy of this weapon that is invisible and inaccessible to players (no touch function). The weapon spawn/respawn code
// will decide when to make the weapon visible and touchable.
CBaseEntity * pNewWeapon = CBaseEntity : : Create ( ( char * ) STRING ( pev - > classname ) , g_pGameRules - > VecWeaponRespawnSpot ( this ) , pev - > angles , pev - > owner ) ;
if ( pNewWeapon )
{
pNewWeapon - > pev - > effects | = EF_NODRAW ; // invisible for now
pNewWeapon - > SetTouch ( NULL ) ; // no touch
pNewWeapon - > SetThink ( & CBasePlayerItem : : AttemptToMaterialize ) ;
DROP_TO_FLOOR ( ENT ( pev ) ) ;
// not a typo! We want to know when the weapon the player just picked up should respawn! This new entity we created is the replacement,
// but when it should respawn is based on conditions belonging to the weapon that was taken.
pNewWeapon - > pev - > nextthink = g_pGameRules - > FlWeaponRespawnTime ( this ) ;
}
else
{
ALERT ( at_console , " Respawn failed to create %s! \n " , STRING ( pev - > classname ) ) ;
}
return pNewWeapon ;
}
void CBasePlayerItem : : DefaultTouch ( CBaseEntity * pOther )
{
// if it's not a player, ignore
if ( ! pOther - > IsPlayer ( ) )
return ;
CBasePlayer * pPlayer = ( CBasePlayer * ) pOther ;
// can I have this?
if ( ! g_pGameRules - > CanHavePlayerItem ( pPlayer , this ) )
{
if ( gEvilImpulse101 )
{
UTIL_Remove ( this ) ;
}
return ;
}
if ( pOther - > AddPlayerItem ( this ) )
{
AttachToPlayer ( pPlayer ) ;
AvHPlayer * thePlayer = dynamic_cast < AvHPlayer * > ( pPlayer ) ;
if ( thePlayer & & thePlayer - > GetIsAlien ( ) )
{
EMIT_SOUND ( ENT ( pPlayer - > pev ) , CHAN_ITEM , " items/gunpickup2-a.wav " , 1 , ATTN_NORM ) ;
}
else
{
EMIT_SOUND ( ENT ( pPlayer - > pev ) , CHAN_ITEM , " items/gunpickup2.wav " , 1 , ATTN_NORM ) ;
}
}
SUB_UseTargets ( pOther , USE_TOGGLE , 0 ) ; // UNDONE: when should this happen?
2021-01-20 20:36:37 +00:00
// Haven't had the crash but adding this in case due to weapons being able to turn to SOLID_TRIGGER before touching the ground with 2021 weapon collision fix.
// https://github.com/ValveSoftware/halflife/pull/1599
// If the item is falling and its Think remains FallItem after the player picks it up,
// then after the item touches the ground its Touch will be set back to DefaultTouch,
// so the player will pick it up again, this time Kill-ing the item (since we already have it in the inventory),
// which will make the pointer bad and crash the game.
if ( m_pfnThink = = & CBasePlayerItem : : FallThink )
SetThink ( NULL ) ;
2018-04-22 15:55:55 +00:00
}
BOOL CanAttack ( float attack_time , float curtime , BOOL isPredicted )
{
if ( ! isPredicted )
{
return ( attack_time < = curtime ) ? TRUE : FALSE ;
}
else
{
return ( attack_time < = 0.0 ) ? TRUE : FALSE ;
}
}
void CBasePlayerWeapon : : ItemPostFrame ( void )
{
bool theAttackPressed = ( m_pPlayer - > pev - > button & IN_ATTACK ) & & ! ( m_pPlayer - > pev - > button & IN_ATTACK2 ) ;
bool theWeaponPrimes = ( this - > GetWeaponPrimeTime ( ) > 0.0f ) ;
bool theWeaponIsPriming = this - > GetIsWeaponPriming ( ) ;
bool theWeaponIsPrimed = this - > GetIsWeaponPrimed ( ) ;
if ( ( m_fInReload ) & & ( m_pPlayer - > m_flNextAttack < = UTIL_WeaponTimeBase ( ) ) )
{
// complete the reload.
int j = 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_pPlayer - > TabulateAmmo ( ) ;
m_fInReload = FALSE ;
}
/* // +movement: Removed case for +attack2 since it's used for movement abilities
if ( ( m_pPlayer - > pev - > button & IN_ATTACK2 ) & & CanAttack ( m_flNextSecondaryAttack , gpGlobals - > time , UseDecrement ( ) ) )
{
if ( m_pPlayer - > GetCanUseWeapon ( ) )
{
if ( pszAmmo2 ( ) & & ! m_pPlayer - > m_rgAmmo [ SecondaryAmmoIndex ( ) ] )
{
m_fFireOnEmpty = TRUE ;
}
m_pPlayer - > TabulateAmmo ( ) ;
SecondaryAttack ( ) ;
m_pPlayer - > pev - > button & = ~ IN_ATTACK2 ;
}
}
else
*/
2021-01-20 20:36:37 +00:00
if ( theAttackPressed & & m_pPlayer - > GetCanUseWeapon ( ) )
2018-04-22 15:55:55 +00:00
{
2021-01-20 20:36:37 +00:00
if ( ( m_fInSpecialReload = = 1 | | m_fInSpecialReload = = 2 ) & & m_iClip ! = 0 & & ( CVAR_GET_FLOAT ( " sv_nsversion " ) > 322.0f ) )
{
m_fInSpecialReload = 3 ;
Reload ( ) ;
}
else if ( CanAttack ( m_flNextPrimaryAttack , gpGlobals - > time , UseDecrement ( ) ) )
2018-04-22 15:55:55 +00:00
{
if ( ( m_iClip = = 0 & & pszAmmo1 ( ) ) | | ( iMaxClip ( ) = = - 1 & & ! m_pPlayer - > m_rgAmmo [ PrimaryAmmoIndex ( ) ] ) )
{
m_fFireOnEmpty = TRUE ;
}
2021-01-20 20:36:37 +00:00
m_pPlayer - > TabulateAmmo ( ) ;
PrimaryAttack ( ) ;
2018-04-22 15:55:55 +00:00
}
}
else if ( m_pPlayer - > pev - > button & IN_RELOAD & & iMaxClip ( ) ! = WEAPON_NOCLIP & & ! m_fInReload )
{
if ( m_pPlayer - > GetCanUseWeapon ( ) )
{
// reload when reload is pressed, or if no buttons are down and weapon is empty.
Reload ( ) ;
}
}
// +movement: Removed case for +attack2
else if ( ! ( m_pPlayer - > pev - > button & ( IN_ATTACK /* |IN_ATTACK2 */ ) ) )
{
if ( m_pPlayer - > GetCanUseWeapon ( ) )
{
// 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 ) )
{
if ( m_pPlayer - > m_rgAmmo [ m_iPrimaryAmmoType ] > 0 )
{
Reload ( ) ;
return ;
}
}
}
WeaponIdle ( ) ;
}
return ;
}
// catch all
if ( ShouldWeaponIdle ( ) )
{
WeaponIdle ( ) ;
}
}
void CBasePlayerItem : : DestroyItem ( void )
{
//KGP: this is a virtual function call for a reason...
// it had been replaced with the contents of
// CBasePlayerItem::VirtualDestroyItem, ignoring
// AvHBasePlayerWeapon::VirtualDestroyItem in 3.01
this - > VirtualDestroyItem ( ) ;
}
void CBasePlayerItem : : VirtualDestroyItem ( void )
{
if ( m_pPlayer )
{
// if attached to a player, remove.
m_pPlayer - > RemovePlayerItem ( this ) ;
}
Kill ( ) ;
}
int CBasePlayerItem : : AddToPlayer ( CBasePlayer * pPlayer )
{
m_pPlayer = pPlayer ;
pPlayer - > m_iHideHUD & = ~ HIDEHUD_WEAPONS ;
return TRUE ;
}
void CBasePlayerItem : : Drop ( void )
{
SetTouch ( NULL ) ;
SetThink ( & CBasePlayerItem : : SUB_Remove ) ;
pev - > nextthink = gpGlobals - > time + .1 ;
}
void CBasePlayerItem : : Kill ( void )
{
SetTouch ( NULL ) ;
SetThink ( & CBasePlayerItem : : SUB_Remove ) ;
pev - > nextthink = gpGlobals - > time + .1 ;
}
void CBasePlayerItem : : Holster ( int skiplocal /* = 0 */ )
{
m_pPlayer - > pev - > viewmodel = 0 ;
m_pPlayer - > pev - > weaponmodel = 0 ;
}
void CBasePlayerItem : : AttachToPlayer ( CBasePlayer * pPlayer )
{
pev - > movetype = MOVETYPE_FOLLOW ;
pev - > solid = SOLID_NOT ;
pev - > aiment = pPlayer - > edict ( ) ;
pev - > effects = EF_NODRAW ; // ??
pev - > modelindex = 0 ; // server won't send down to clients if modelindex == 0
pev - > model = iStringNull ;
pev - > owner = pPlayer - > edict ( ) ;
pev - > nextthink = gpGlobals - > time + .1 ;
SetTouch ( NULL ) ;
}
void CBasePlayerItem : : Spawn ( )
{
CBaseAnimating : : Spawn ( ) ;
}
// CALLED THROUGH the newly-touched weapon's instance. The existing player weapon is pOriginal
int CBasePlayerWeapon : : AddDuplicate ( CBasePlayerItem * pOriginal )
{
if ( m_iDefaultAmmo )
{
return ExtractAmmo ( ( CBasePlayerWeapon * ) pOriginal ) ;
}
else
{
// a dead player dropped this.
return ExtractClipAmmo ( ( CBasePlayerWeapon * ) pOriginal ) ;
}
}
int CBasePlayerWeapon : : AddToPlayer ( CBasePlayer * pPlayer )
{
int bResult = CBasePlayerItem : : AddToPlayer ( pPlayer ) ;
pPlayer - > pev - > weapons | = ( 1 < < m_iId ) ;
if ( ! m_iPrimaryAmmoType )
{
m_iPrimaryAmmoType = pPlayer - > GetAmmoIndex ( pszAmmo1 ( ) ) ;
m_iSecondaryAmmoType = pPlayer - > GetAmmoIndex ( pszAmmo2 ( ) ) ;
}
if ( bResult )
return AddWeapon ( ) ;
return FALSE ;
}
int CBasePlayerWeapon : : UpdateClientData ( CBasePlayer * pPlayer )
{
BOOL bSend = FALSE ;
int state = 0 ;
// KGP: folded m_iEnabled into the state value and converted it to a proper bitfield.
if ( pPlayer - > m_pActiveItem = = this )
{ state | = WEAPON_IS_CURRENT ; }
if ( pPlayer - > m_fOnTarget )
{ state | = WEAPON_ON_TARGET ; }
if ( m_iEnabled )
{ state | = WEAPON_IS_ENABLED ; }
// Forcing send of all data!
if ( ! pPlayer - > m_fWeapon )
{
bSend = TRUE ;
}
// This is the current or last weapon, so the state will need to be updated
if ( this = = pPlayer - > m_pActiveItem | |
this = = pPlayer - > m_pClientActiveItem )
{
if ( pPlayer - > m_pActiveItem ! = pPlayer - > m_pClientActiveItem )
{
bSend = TRUE ;
}
}
// If the ammo, state, or fov has changed, update the weapon
if ( m_iClip ! = m_iClientClip | |
state ! = m_iClientWeaponState | |
pPlayer - > m_iFOV ! = pPlayer - > m_iClientFOV )
{
bSend = TRUE ;
}
if ( m_iId = = 22 | | m_iId = = 11 | | m_iId = = 21 )
gCanMove [ pPlayer - > entindex ( ) - 1 ] = m_iEnabled ;
if ( bSend )
{
NetMsg_CurWeapon ( pPlayer - > pev , state , m_iId , m_iClip ) ;
m_iClientClip = m_iClip ;
m_iClientWeaponState = state ;
pPlayer - > m_fWeapon = TRUE ;
}
if ( m_pNext )
m_pNext - > UpdateClientData ( pPlayer ) ;
return 1 ;
}
void CBasePlayerWeapon : : SendWeaponAnim ( int iAnim , int skiplocal , int body )
{
if ( iAnim > = 0 )
{
if ( UseDecrement ( ) )
skiplocal = 1 ;
else
skiplocal = 0 ;
m_pPlayer - > pev - > weaponanim = iAnim ;
if ( skiplocal & & ENGINE_CANSKIP ( m_pPlayer - > edict ( ) ) )
return ;
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 ;
iIdAmmo = m_pPlayer - > GiveAmmo ( iCount , szName , iMaxCarry ) ;
}
else if ( m_iClip = = 0 )
{
int i ;
i = min ( m_iClip + iCount , iMaxClip ) - m_iClip ;
m_iClip + = i ;
iIdAmmo = m_pPlayer - > GiveAmmo ( iCount - i , szName , iMaxCarry ) ;
}
else
{
iIdAmmo = m_pPlayer - > GiveAmmo ( iCount , szName , iMaxCarry ) ;
}
// m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] = iMaxCarry; // hack for testing
if ( iIdAmmo > 0 )
{
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.
// if the player is just getting this gun for the first time, DefaultTouch will play the "picked up gun" sound for us.
EMIT_SOUND ( ENT ( pev ) , CHAN_ITEM , " items/9mmclip1.wav " , 1 , ATTN_NORM ) ;
}
}
return iIdAmmo > 0 ? TRUE : FALSE ;
}
BOOL CBasePlayerWeapon : : AddSecondaryAmmo ( int iCount , char * szName , int iMax )
{
int iIdAmmo ;
iIdAmmo = m_pPlayer - > GiveAmmo ( iCount , szName , iMax ) ;
//m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] = iMax; // hack for testing
if ( iIdAmmo > 0 )
{
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 )
{
// This looks like a nasty bug Valve didn't notice
ASSERT ( PrimaryAmmoIndex ( ) > = 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 ;
// All weapons can always deploy. Once fire is hit, it checks if it's out of ammo. If so, the weapon switches.
// This is needed so ammo packs function correctly, and it also feels more responsive.
// 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 , int body )
{
if ( ! CanDeploy ( ) )
return FALSE ;
m_pPlayer - > TabulateAmmo ( ) ;
m_pPlayer - > pev - > viewmodel = MAKE_STRING ( szViewModel ) ;
m_pPlayer - > pev - > weaponmodel = MAKE_STRING ( szWeaponModel ) ;
strcpy ( m_pPlayer - > m_szAnimExtention , szAnimExt ) ;
SendWeaponAnim ( iAnim , skiplocal , body ) ;
// Set the player animation as well
//this->m_pPlayer->SetAnimation(PLAYER_ANIM(iAnim));
m_pPlayer - > m_flNextAttack = UTIL_WeaponTimeBase ( ) + this - > GetDeployTime ( ) ;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase ( ) + this - > GetDeployTime ( ) + kDeployIdleInterval ;
return TRUE ;
}
BOOL CBasePlayerWeapon : : DefaultReload ( int iClipSize , int iAnim , float fDelay , int body )
{
if ( m_pPlayer - > m_rgAmmo [ m_iPrimaryAmmoType ] < = 0 )
return FALSE ;
int j = min ( iClipSize - m_iClip , m_pPlayer - > m_rgAmmo [ m_iPrimaryAmmoType ] ) ;
if ( j = = 0 )
return FALSE ;
m_pPlayer - > m_flNextAttack = UTIL_WeaponTimeBase ( ) + fDelay ;
//!!UNDONE -- reload sound goes here !!!
//SendWeaponAnim( iAnim, UseDecrement() ? 1 : 0 );
m_fInReload = TRUE ;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase ( ) + kDeployIdleInterval ;
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);
int flags = FEV_NOTHOST ;
PLAYBACK_EVENT_FULL ( flags , m_pPlayer - > edict ( ) , gEmptySoundEventID , 0.0 , ( float * ) & ( m_pPlayer - > pev - > origin ) , ( float * ) & g_vecZero , 0.0 , 0.0 , 0 , 0 , 0 , 0 ) ;
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 ( int skiplocal /* = 0 */ )
{
m_fInReload = FALSE ; // cancel any reload in progress.
m_pPlayer - > pev - > viewmodel = 0 ;
m_pPlayer - > pev - > weaponmodel = 0 ;
}
void CBasePlayerAmmo : : Spawn ( void )
{
pev - > movetype = MOVETYPE_TOSS ;
pev - > solid = SOLID_TRIGGER ;
UTIL_SetSize ( pev , Vector ( - 16 , - 16 , 0 ) , Vector ( 16 , 16 , 16 ) ) ;
UTIL_SetOrigin ( pev , pev - > origin ) ;
SetTouch ( & CBasePlayerAmmo : : DefaultTouch ) ;
}
CBaseEntity * CBasePlayerAmmo : : Respawn ( void )
{
pev - > effects | = EF_NODRAW ;
SetTouch ( NULL ) ;
UTIL_SetOrigin ( pev , g_pGameRules - > VecAmmoRespawnSpot ( this ) ) ; // move to wherever I'm supposed to repawn.
SetThink ( & CBasePlayerAmmo : : Materialize ) ;
pev - > nextthink = g_pGameRules - > FlAmmoRespawnTime ( this ) ;
return this ;
}
void CBasePlayerAmmo : : Materialize ( void )
{
if ( pev - > effects & EF_NODRAW )
{
// changing from invisible state to visible.
EMIT_SOUND_DYN ( ENT ( pev ) , CHAN_WEAPON , " items/suitchargeok1.wav " , 1 , ATTN_NORM , 0 , 150 ) ;
pev - > effects & = ~ EF_NODRAW ;
pev - > effects | = EF_MUZZLEFLASH ;
}
SetTouch ( & CBasePlayerAmmo : : DefaultTouch ) ;
}
void CBasePlayerAmmo : : DefaultTouch ( CBaseEntity * pOther )
{
if ( ! pOther - > IsPlayer ( ) )
{
return ;
}
if ( AddAmmo ( pOther ) )
{
if ( g_pGameRules - > AmmoShouldRespawn ( this ) = = GR_AMMO_RESPAWN_YES )
{
Respawn ( ) ;
}
else
{
SetTouch ( NULL ) ;
SetThink ( & CBasePlayerAmmo : : SUB_Remove ) ;
pev - > nextthink = gpGlobals - > time + .1 ;
}
}
else if ( gEvilImpulse101 )
{
// evil impulse 101 hack, kill always
SetTouch ( NULL ) ;
SetThink ( & CBasePlayerAmmo : : SUB_Remove ) ;
pev - > nextthink = gpGlobals - > time + .1 ;
}
}
//=========================================================
// called by the new item with the existing item as parameter
//
// if we call ExtractAmmo(), it's because the player is picking up this type of weapon for
// the first time. If it is spawned by the world, m_iDefaultAmmo will have a default ammo amount in it.
// if this is a weapon dropped by a dying player, has 0 m_iDefaultAmmo, which means only the ammo in
// the weapon clip comes along.
//=========================================================
int CBasePlayerWeapon : : ExtractAmmo ( CBasePlayerWeapon * pWeapon )
{
int iReturn ;
if ( pszAmmo1 ( ) ! = NULL )
{
// 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 ;
}
if ( pszAmmo2 ( ) ! = NULL )
{
iReturn = pWeapon - > AddSecondaryAmmo ( 0 , ( char * ) pszAmmo2 ( ) , iMaxAmmo2 ( ) ) ;
}
return iReturn ;
}
//=========================================================
// called by the new item's class with the existing item as parameter
//=========================================================
int CBasePlayerWeapon : : ExtractClipAmmo ( CBasePlayerWeapon * pWeapon )
{
int iAmmo ;
if ( m_iClip = = WEAPON_NOCLIP )
{
iAmmo = 0 ; // guns with no clips always come empty if they are second-hand
}
else
{
iAmmo = m_iClip ;
}
return pWeapon - > m_pPlayer - > GiveAmmo ( iAmmo , ( char * ) pszAmmo1 ( ) , iMaxAmmo1 ( ) ) ; // , &m_iPrimaryAmmoType
}
//=========================================================
// RetireWeapon - no more ammo for this gun, put it away.
//=========================================================
void CBasePlayerWeapon : : RetireWeapon ( void )
{
// first, no viewmodel at all.
m_pPlayer - > pev - > viewmodel = iStringNull ;
m_pPlayer - > pev - > weaponmodel = iStringNull ;
//m_pPlayer->pev->viewmodelindex = NULL;
g_pGameRules - > GetNextBestWeapon ( m_pPlayer , this ) ;
}
//*********************************************************
// weaponbox code:
//*********************************************************
LINK_ENTITY_TO_CLASS ( weaponbox , CWeaponBox ) ;
TYPEDESCRIPTION CWeaponBox : : m_SaveData [ ] =
{
DEFINE_ARRAY ( CWeaponBox , m_rgAmmo , FIELD_INTEGER , MAX_AMMO_SLOTS ) ,
DEFINE_ARRAY ( CWeaponBox , m_rgiszAmmo , FIELD_STRING , MAX_AMMO_SLOTS ) ,
DEFINE_ARRAY ( CWeaponBox , m_rgpPlayerItems , FIELD_CLASSPTR , MAX_ITEM_TYPES ) ,
DEFINE_FIELD ( CWeaponBox , m_cAmmoTypes , FIELD_INTEGER ) ,
} ;
IMPLEMENT_SAVERESTORE ( CWeaponBox , CBaseEntity ) ;
//=========================================================
//
//=========================================================
void CWeaponBox : : Precache ( void )
{
PRECACHE_UNMODIFIED_MODEL ( " models/w_weaponbox.mdl " ) ;
}
//=========================================================
//=========================================================
void CWeaponBox : : KeyValue ( KeyValueData * pkvd )
{
if ( m_cAmmoTypes < MAX_AMMO_SLOTS )
{
PackAmmo ( ALLOC_STRING ( pkvd - > szKeyName ) , atoi ( pkvd - > szValue ) ) ;
m_cAmmoTypes + + ; // count this new ammo type.
pkvd - > fHandled = TRUE ;
}
else
{
ALERT ( at_console , " WeaponBox too full! only %d ammotypes allowed \n " , MAX_AMMO_SLOTS ) ;
}
}
//=========================================================
// CWeaponBox - Spawn
//=========================================================
void CWeaponBox : : Spawn ( void )
{
Precache ( ) ;
pev - > movetype = MOVETYPE_TOSS ;
pev - > solid = SOLID_TRIGGER ;
UTIL_SetSize ( pev , g_vecZero , g_vecZero ) ;
SET_MODEL ( ENT ( pev ) , " models/w_weaponbox.mdl " ) ;
}
//=========================================================
// CWeaponBox - Kill - the think function that removes the
// box from the world.
//=========================================================
void CWeaponBox : : Kill ( void )
{
CBasePlayerItem * pWeapon ;
int i ;
// destroy the weapons
for ( i = 0 ; i < MAX_ITEM_TYPES ; i + + )
{
pWeapon = m_rgpPlayerItems [ i ] ;
while ( pWeapon )
{
pWeapon - > SetThink ( & CWeaponBox : : SUB_Remove ) ;
pWeapon - > pev - > nextthink = gpGlobals - > time + 0.1 ;
pWeapon = pWeapon - > m_pNext ;
}
}
// remove the box
UTIL_Remove ( this ) ;
}
//=========================================================
// CWeaponBox - Touch: try to add my contents to the toucher
// if the toucher is a player.
//=========================================================
void CWeaponBox : : Touch ( CBaseEntity * pOther )
{
if ( ! ( pev - > flags & FL_ONGROUND ) )
{
return ;
}
if ( ! pOther - > IsPlayer ( ) )
{
// only players may touch a weaponbox.
return ;
}
if ( ! pOther - > IsAlive ( ) )
{
// no dead guys.
return ;
}
CBasePlayer * pPlayer = ( CBasePlayer * ) pOther ;
int i ;
// dole out ammo
for ( i = 0 ; i < MAX_AMMO_SLOTS ; i + + )
{
if ( ! FStringNull ( m_rgiszAmmo [ i ] ) )
{
// there's some ammo of this type.
pPlayer - > GiveAmmo ( m_rgAmmo [ i ] , ( char * ) STRING ( m_rgiszAmmo [ i ] ) , MaxAmmoCarry ( m_rgiszAmmo [ i ] ) ) ;
//ALERT ( at_console, "Gave %d rounds of %s\n", m_rgAmmo[i], STRING(m_rgiszAmmo[i]) );
// now empty the ammo from the weaponbox since we just gave it to the player
m_rgiszAmmo [ i ] = iStringNull ;
m_rgAmmo [ i ] = 0 ;
}
}
// go through my weapons and try to give the usable ones to the player.
// it's important the the player be given ammo first, so the weapons code doesn't refuse
// to deploy a better weapon that the player may pick up because he has no ammo for it.
for ( i = 0 ; i < MAX_ITEM_TYPES ; i + + )
{
if ( m_rgpPlayerItems [ i ] )
{
CBasePlayerItem * pItem ;
// have at least one weapon in this slot
while ( m_rgpPlayerItems [ i ] )
{
//ALERT ( at_console, "trying to give %s\n", STRING( m_rgpPlayerItems[ i ]->pev->classname ) );
pItem = m_rgpPlayerItems [ i ] ;
m_rgpPlayerItems [ i ] = m_rgpPlayerItems [ i ] - > m_pNext ; // unlink this weapon from the box
if ( pPlayer - > AddPlayerItem ( pItem ) )
{
pItem - > AttachToPlayer ( pPlayer ) ;
}
}
}
}
EMIT_SOUND ( pOther - > edict ( ) , CHAN_ITEM , " items/gunpickup2.wav " , 1 , ATTN_NORM ) ;
SetTouch ( NULL ) ;
UTIL_Remove ( this ) ;
}
//=========================================================
// CWeaponBox - PackWeapon: Add this weapon to the box
//=========================================================
BOOL CWeaponBox : : PackWeapon ( CBasePlayerItem * pWeapon )
{
// is one of these weapons already packed in this box?
if ( HasWeapon ( pWeapon ) )
{
return FALSE ; // box can only hold one of each weapon type
}
if ( pWeapon - > m_pPlayer )
{
if ( ! pWeapon - > m_pPlayer - > RemovePlayerItem ( pWeapon ) )
{
// failed to unhook the weapon from the player!
return FALSE ;
}
}
int iWeaponSlot = pWeapon - > iItemSlot ( ) ;
if ( m_rgpPlayerItems [ iWeaponSlot ] )
{
// there's already one weapon in this slot, so link this into the slot's column
pWeapon - > m_pNext = m_rgpPlayerItems [ iWeaponSlot ] ;
m_rgpPlayerItems [ iWeaponSlot ] = pWeapon ;
}
else
{
// first weapon we have for this slot
m_rgpPlayerItems [ iWeaponSlot ] = pWeapon ;
pWeapon - > m_pNext = NULL ;
}
pWeapon - > pev - > spawnflags | = SF_NORESPAWN ; // never respawn
pWeapon - > pev - > movetype = MOVETYPE_NONE ;
pWeapon - > pev - > solid = SOLID_NOT ;
pWeapon - > pev - > effects = EF_NODRAW ;
pWeapon - > pev - > modelindex = 0 ;
pWeapon - > pev - > model = iStringNull ;
pWeapon - > pev - > owner = edict ( ) ;
pWeapon - > SetThink ( NULL ) ; // crowbar may be trying to swing again, etc.
pWeapon - > SetTouch ( NULL ) ;
pWeapon - > m_pPlayer = NULL ;
//ALERT ( at_console, "packed %s\n", STRING(pWeapon->pev->classname) );
return TRUE ;
}
//=========================================================
// CWeaponBox - PackAmmo
//=========================================================
BOOL CWeaponBox : : PackAmmo ( int iszName , int iCount )
{
int iMaxCarry ;
if ( FStringNull ( iszName ) )
{
// error here
ALERT ( at_console , " NULL String in PackAmmo! \n " ) ;
return FALSE ;
}
iMaxCarry = MaxAmmoCarry ( iszName ) ;
if ( iMaxCarry ! = - 1 & & iCount > 0 )
{
//ALERT ( at_console, "Packed %d rounds of %s\n", iCount, STRING(iszName) );
GiveAmmo ( iCount , ( char * ) STRING ( iszName ) , iMaxCarry ) ;
return TRUE ;
}
return FALSE ;
}
//=========================================================
// CWeaponBox - GiveAmmo
//=========================================================
int CWeaponBox : : GiveAmmo ( int iCount , char * szName , int iMax , int * pIndex /* = NULL*/ )
{
int i ;
for ( i = 1 ; i < MAX_AMMO_SLOTS & & ! FStringNull ( m_rgiszAmmo [ i ] ) ; i + + )
{
if ( stricmp ( szName , STRING ( m_rgiszAmmo [ i ] ) ) = = 0 )
{
if ( pIndex )
* pIndex = i ;
int iAdd = min ( iCount , iMax - m_rgAmmo [ i ] ) ;
if ( iCount = = 0 | | iAdd > 0 )
{
m_rgAmmo [ i ] + = iAdd ;
return i ;
}
return - 1 ;
}
}
if ( i < MAX_AMMO_SLOTS )
{
if ( pIndex )
* pIndex = i ;
m_rgiszAmmo [ i ] = MAKE_STRING ( szName ) ;
m_rgAmmo [ i ] = iCount ;
return i ;
}
ALERT ( at_console , " out of named ammo slots \n " ) ;
return i ;
}
//=========================================================
// CWeaponBox::HasWeapon - is a weapon of this type already
// packed in this box?
//=========================================================
BOOL CWeaponBox : : HasWeapon ( CBasePlayerItem * pCheckItem )
{
CBasePlayerItem * pItem = m_rgpPlayerItems [ pCheckItem - > iItemSlot ( ) ] ;
while ( pItem )
{
if ( FClassnameIs ( pItem - > pev , STRING ( pCheckItem - > pev - > classname ) ) )
{
return TRUE ;
}
pItem = pItem - > m_pNext ;
}
return FALSE ;
}
//=========================================================
// CWeaponBox::IsEmpty - is there anything in this box?
//=========================================================
BOOL CWeaponBox : : IsEmpty ( void )
{
int i ;
for ( i = 0 ; i < MAX_ITEM_TYPES ; i + + )
{
if ( m_rgpPlayerItems [ i ] )
{
return FALSE ;
}
}
for ( i = 0 ; i < MAX_AMMO_SLOTS ; i + + )
{
if ( ! FStringNull ( m_rgiszAmmo [ i ] ) )
{
// still have a bit of this type of ammo
return FALSE ;
}
}
return TRUE ;
}
//=========================================================
//=========================================================
void CWeaponBox : : SetObjectCollisionBox ( void )
{
pev - > absmin = pev - > origin + Vector ( - 16 , - 16 , 0 ) ;
pev - > absmax = pev - > origin + Vector ( 16 , 16 , 16 ) ;
}
void CBasePlayerWeapon : : PrintState ( void )
{
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_finsr: %i\n", m_fInSpecialReload );
ALERT ( at_console , " m_iclip: %i \n " , m_iClip ) ;
}
TYPEDESCRIPTION CRpg : : m_SaveData [ ] =
{
DEFINE_FIELD ( CRpg , m_fSpotActive , FIELD_INTEGER ) ,
DEFINE_FIELD ( CRpg , m_cActiveRockets , FIELD_INTEGER ) ,
} ;
IMPLEMENT_SAVERESTORE ( CRpg , CBasePlayerWeapon ) ;
TYPEDESCRIPTION CRpgRocket : : m_SaveData [ ] =
{
DEFINE_FIELD ( CRpgRocket , m_flIgniteTime , FIELD_TIME ) ,
DEFINE_FIELD ( CRpgRocket , m_pLauncher , FIELD_CLASSPTR ) ,
} ;
IMPLEMENT_SAVERESTORE ( CRpgRocket , CGrenade ) ;
TYPEDESCRIPTION CShotgun : : m_SaveData [ ] =
{
DEFINE_FIELD ( CShotgun , m_flNextReload , FIELD_TIME ) ,
DEFINE_FIELD ( CShotgun , m_fInSpecialReload , FIELD_INTEGER ) ,
DEFINE_FIELD ( CShotgun , m_flNextReload , FIELD_TIME ) ,
// DEFINE_FIELD( CShotgun, m_iShell, FIELD_INTEGER ),
DEFINE_FIELD ( CShotgun , m_flPumpTime , FIELD_TIME ) ,
} ;
IMPLEMENT_SAVERESTORE ( CShotgun , CBasePlayerWeapon ) ;
TYPEDESCRIPTION CGauss : : m_SaveData [ ] =
{
DEFINE_FIELD ( CGauss , m_fInAttack , FIELD_INTEGER ) ,
// DEFINE_FIELD( CGauss, m_flStartCharge, FIELD_TIME ),
// DEFINE_FIELD( CGauss, m_flPlayAftershock, FIELD_TIME ),
// DEFINE_FIELD( CGauss, m_flNextAmmoBurn, FIELD_TIME ),
DEFINE_FIELD ( CGauss , m_fPrimaryFire , FIELD_BOOLEAN ) ,
} ;
IMPLEMENT_SAVERESTORE ( CGauss , CBasePlayerWeapon ) ;
TYPEDESCRIPTION CEgon : : m_SaveData [ ] =
{
// DEFINE_FIELD( CEgon, m_pBeam, FIELD_CLASSPTR ),
// DEFINE_FIELD( CEgon, m_pNoise, FIELD_CLASSPTR ),
// DEFINE_FIELD( CEgon, m_pSprite, FIELD_CLASSPTR ),
DEFINE_FIELD ( CEgon , m_shootTime , FIELD_TIME ) ,
DEFINE_FIELD ( CEgon , m_fireState , FIELD_INTEGER ) ,
DEFINE_FIELD ( CEgon , m_fireMode , FIELD_INTEGER ) ,
DEFINE_FIELD ( CEgon , m_shakeTime , FIELD_TIME ) ,
DEFINE_FIELD ( CEgon , m_flAmmoUseTime , FIELD_TIME ) ,
} ;
IMPLEMENT_SAVERESTORE ( CEgon , CBasePlayerWeapon ) ;
TYPEDESCRIPTION CSatchel : : m_SaveData [ ] =
{
DEFINE_FIELD ( CSatchel , m_chargeReady , FIELD_INTEGER ) ,
} ;
IMPLEMENT_SAVERESTORE ( CSatchel , CBasePlayerWeapon ) ;