text: /***
  *
  *	Copyright (c) 1999, 2000 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.
  *
  ****/
  /*
  
  Class Hierachy
  
  CBaseEntity
  	CBaseDelay
  		CBaseToggle
  			CBaseItem
  			CBaseMonster
  				CBaseCycler
  				CBasePlayer
  				CBaseGroup
  */
  
  #define		MAX_PATH_SIZE	10 // max number of nodes available for a path.
  
  // These are caps bits to indicate what an object's capabilities (currently used for save/restore and level transitions)
  #define		FCAP_CUSTOMSAVE				0x00000001
  #define		FCAP_ACROSS_TRANSITION		0x00000002		// should transfer between transitions
  #define		FCAP_MUST_SPAWN				0x00000004		// Spawn after restore
  #define		FCAP_DONT_SAVE				0x80000000		// Don't save this
  #define		FCAP_IMPULSE_USE			0x00000008		// can be used by the player
  #define		FCAP_CONTINUOUS_USE			0x00000010		// can be used by the player
  #define		FCAP_ONOFF_USE				0x00000020		// can be used by the player
  #define		FCAP_DIRECTIONAL_USE		0x00000040		// Player sends +/- 1 when using (currently only tracktrains)
  #define		FCAP_MASTER					0x00000080		// Can be used to "master" other entities (like multisource)
  
  // UNDONE: This will ignore transition volumes (trigger_transition), but not the PVS!!!
  #define		FCAP_FORCE_TRANSITION		0x00000080		// ALWAYS goes across transitions
  
  #include "saverestore.h"
  #include "schedule.h"
  
  #ifndef MONSTEREVENT_H
  #include "monsterevent.h"
  #endif
  
  // C functions for external declarations that call the appropriate C++ methods
  
  #ifdef _WIN32
  #define EXPORT	_declspec( dllexport )
  #else
  #define EXPORT  /* */
  #endif
  
  extern "C" EXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion );
  extern "C" EXPORT int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
  extern "C" EXPORT int GetNewDLLFunctions( NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
  
  extern int DispatchSpawn( edict_t *pent );
  extern void DispatchKeyValue( edict_t *pentKeyvalue, KeyValueData *pkvd );
  extern void DispatchTouch( edict_t *pentTouched, edict_t *pentOther );
  extern void DispatchUse( edict_t *pentUsed, edict_t *pentOther );
  extern void DispatchThink( edict_t *pent );
  extern void DispatchBlocked( edict_t *pentBlocked, edict_t *pentOther );
  extern void DispatchSave( edict_t *pent, SAVERESTOREDATA *pSaveData );
  extern int  DispatchRestore( edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity );
  extern void	DispatchObjectCollsionBox( edict_t *pent );
  extern void SaveWriteFields( SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount );
  extern void SaveReadFields( SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount );
  extern void SaveGlobalState( SAVERESTOREDATA *pSaveData );
  extern void RestoreGlobalState( SAVERESTOREDATA *pSaveData );
  extern void ResetGlobalState( void );
  
  typedef enum { USE_OFF = 0, USE_ON = 1, USE_SET = 2, USE_TOGGLE = 3 } USE_TYPE;
  
  extern void FireTargets( const char *targetName, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  
  typedef void (CBaseEntity::*BASEPTR)(void);
  typedef void (CBaseEntity::*ENTITYFUNCPTR)(CBaseEntity *pOther );
  typedef void (CBaseEntity::*USEPTR)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  
  // For CLASSIFY
  #define	CLASS_NONE				0
  #define CLASS_MACHINE			1
  #define CLASS_PLAYER			2
  #define	CLASS_HUMAN_PASSIVE		3
  #define CLASS_HUMAN_MILITARY	4
  #define CLASS_ALIEN_MILITARY	5
  #define CLASS_ALIEN_PASSIVE		6
  #define CLASS_ALIEN_MONSTER		7
  #define CLASS_ALIEN_PREY		8
  #define CLASS_ALIEN_PREDATOR	9
  #define CLASS_INSECT			10
  #define CLASS_PLAYER_ALLY		11
  #define CLASS_PLAYER_BIOWEAPON	12 // hornets and snarks.launched by players
  #define CLASS_ALIEN_BIOWEAPON	13 // hornets and snarks.launched by the alien menace
  #define	CLASS_BARNACLE			99 // special because no one pays attention to it, and it eats a wide cross-section of creatures.
  
  class CBaseEntity;
  class CBaseMonster;
  class CBasePlayerItem;
  class CSquadMonster;
  
  
  #define	SF_NORESPAWN	( 1 << 30 )// !!!set this bit on guns and stuff that should never respawn.
  
  //
  // EHANDLE. Safe way to point to CBaseEntities who may die between frames
  //
  class EHANDLE
  {
  private:
  	edict_t *m_pent;
  	int		m_serialnumber;
  public:
  	edict_t *Get( void );
  	edict_t *Set( edict_t *pent );
  
  	operator int ();
  
  	operator CBaseEntity *();
  
  	CBaseEntity * operator = (CBaseEntity *pEntity);
  	CBaseEntity * operator ->();
  };
  
  
  //
  // Base Entity.  All entity types derive from this
  //
  class CBaseEntity 
  {
  public:
  	// Constructor.  Set engine to use C/C++ callback functions
  	// pointers to engine data
  	entvars_t *pev;		// Don't need to save/restore this pointer, the engine resets it
  
  	// path corners
  	CBaseEntity			*m_pGoalEnt;// path corner we are heading towards
  	CBaseEntity			*m_pLink;// used for temporary link-list operations. 
  
  	// initialization functions
  	virtual void	Spawn( void ) { return; }
  	virtual void	Precache( void ) { return; }
  	virtual void	KeyValue( KeyValueData* pkvd) { pkvd->fHandled = FALSE; }
  	virtual int		Save( CSave &save );
  	virtual int		Restore( CRestore &restore );
  	virtual int		ObjectCaps( void ) { return FCAP_ACROSS_TRANSITION; }
  	virtual void	Activate( void ) {}
  	
  	// Setup the object->object collision box (pev->mins / pev->maxs is the object->world collision box)
  	virtual void	SetObjectCollisionBox( void );
  
  // Classify - returns the type of group (i.e, "houndeye", or "human military" so that monsters with different classnames
  // still realize that they are teammates. (overridden for monsters that form groups)
  	virtual int Classify ( void ) { return CLASS_NONE; };
  	virtual void DeathNotice ( entvars_t *pevChild ) {}// monster maker children use this to tell the monster maker that they have died.
  
  
  	static	TYPEDESCRIPTION m_SaveData[];
  
  	virtual void	TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
  	virtual int		TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
  	virtual int		TakeHealth( float flHealth, int bitsDamageType );
  	virtual void	Killed( entvars_t *pevAttacker, int iGib );
  	virtual int		BloodColor( void ) { return DONT_BLEED; }
  	virtual void	TraceBleed( float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType );
  	virtual BOOL    IsTriggered( CBaseEntity *pActivator ) {return TRUE;}
  	virtual CBaseMonster *MyMonsterPointer( void ) { return NULL;}
  	virtual CSquadMonster *MySquadMonsterPointer( void ) { return NULL;}
  	virtual	int		GetToggleState( void ) { return TS_AT_TOP; }
  	virtual void	AddPoints( int score, BOOL bAllowNegativeScore ) {}
  	virtual void	AddPointsToTeam( int score, BOOL bAllowNegativeScore ) {}
  	virtual BOOL	AddPlayerItem( CBasePlayerItem *pItem ) { return 0; }
  	virtual BOOL	RemovePlayerItem( CBasePlayerItem *pItem ) { return 0; }
  	virtual int 	GiveAmmo( int iAmount, char *szName, int iMax ) { return -1; };
  	virtual float	GetDelay( void ) { return 0; }
  	virtual int		IsMoving( void ) { return pev->velocity != g_vecZero; }
  	virtual void	OverrideReset( void ) {}
  	virtual int		DamageDecal( int bitsDamageType );
  	// This is ONLY used by the node graph to test movement through a door
  	virtual void	SetToggleState( int state ) {}
  	virtual void    StartSneaking( void ) {}
  	virtual void    StopSneaking( void ) {}
  	virtual BOOL	OnControls( entvars_t *pev ) { return FALSE; }
  	virtual BOOL    IsSneaking( void ) { return FALSE; }
  	virtual BOOL	IsAlive( void ) { return (pev->deadflag == DEAD_NO) && pev->health > 0; }
  	virtual BOOL	IsBSPModel( void ) { return pev->solid == SOLID_BSP || pev->movetype == MOVETYPE_PUSHSTEP; }
  	virtual BOOL	ReflectGauss( void ) { return ( IsBSPModel() && !pev->takedamage ); }
  	virtual BOOL	HasTarget( string_t targetname ) { return FStrEq(STRING(targetname), STRING(pev->targetname) ); }
  	virtual BOOL    IsInWorld( void );
  	virtual	BOOL	IsPlayer( void ) { return FALSE; }
  	virtual BOOL	IsNetClient( void ) { return FALSE; }
  	virtual const char *TeamID( void ) { return ""; }
  
  	virtual BOOL	IsDisc( void ) { return FALSE; };
  
  //	virtual void	SetActivator( CBaseEntity *pActivator ) {}
  	virtual CBaseEntity *GetNextTarget( void );
  	
  	// fundamental callbacks
  	void (CBaseEntity ::*m_pfnThink)(void);
  	void (CBaseEntity ::*m_pfnTouch)( CBaseEntity *pOther );
  	void (CBaseEntity ::*m_pfnUse)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  	void (CBaseEntity ::*m_pfnBlocked)( CBaseEntity *pOther );
  
  	virtual void Think( void ) { if (m_pfnThink) (this->*m_pfnThink)(); };
  	virtual void Touch( CBaseEntity *pOther ) { if (m_pfnTouch) (this->*m_pfnTouch)( pOther ); };
  	virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) 
  	{ 
  		if (m_pfnUse) 
  			(this->*m_pfnUse)( pActivator, pCaller, useType, value );
  	}
  	virtual void Blocked( CBaseEntity *pOther ) { if (m_pfnBlocked) (this->*m_pfnBlocked)( pOther ); };
  
  	// allow engine to allocate instance data
      void *operator new( size_t stAllocateBlock, entvars_t *pev )
  	{
  		return (void *)ALLOC_PRIVATE(ENT(pev), stAllocateBlock);
  	};
  
  	// don't use this.
  #if _MSC_VER >= 1200 // only build this code if MSVC++ 6.0 or higher
  	void operator delete(void *pMem, entvars_t *pev)
  	{
  		pev->flags |= FL_KILLME;
  	};
  #endif
  
  	void UpdateOnRemove( void );
  
  	// common member functions
  	void EXPORT SUB_Remove( void );
  	void EXPORT SUB_DoNothing( void );
  	void EXPORT SUB_StartFadeOut ( void );
  	void EXPORT SUB_FadeOut ( void );
  	void EXPORT SUB_CallUseToggle( void ) { this->Use( this, this, USE_TOGGLE, 0 ); }
  	int			ShouldToggle( USE_TYPE useType, BOOL currentState );
  	void		FireBullets( ULONG	cShots, Vector  vecSrc, Vector	vecDirShooting,	Vector	vecSpread, float flDistance, int iBulletType, int iTracerFreq = 4, int iDamage = 0, entvars_t *pevAttacker = NULL  );
  
  	virtual CBaseEntity *Respawn( void ) { return NULL; }
  
  	void SUB_UseTargets( CBaseEntity *pActivator, USE_TYPE useType, float value );
  	// Do the bounding boxes of these two intersect?
  	int		Intersects( CBaseEntity *pOther );
  	void	MakeDormant( void );
  	int		IsDormant( void );
  	BOOL    IsLockedByMaster( void ) { return FALSE; }
  
  #ifdef _DEBUG
  	static CBaseEntity *Instance( edict_t *pent ) 
  	{ 
  		if ( !pent )
  			pent = ENT(0);
  		CBaseEntity *pEnt = (CBaseEntity *)GET_PRIVATE(pent); 
  		ASSERT(pEnt!=NULL); 
  		return pEnt; 
  	}
  #else
  	static CBaseEntity *Instance( edict_t *pent )
  	{ 
  		if ( !pent )
  			pent = ENT(0);
  		CBaseEntity *pEnt = (CBaseEntity *)GET_PRIVATE(pent); 
  		return pEnt; 
  	}
  #endif
  
  	static CBaseEntity *Instance( entvars_t *pev ) { return Instance( ENT( pev ) ); }
  	static CBaseEntity *Instance( int eoffset) { return Instance( ENT( eoffset) ); }
  
  	CBaseMonster *GetMonsterPointer( entvars_t *pevMonster ) 
  	{ 
  		CBaseEntity *pEntity = Instance( pevMonster );
  		if ( pEntity )
  			return pEntity->MyMonsterPointer();
  		return NULL;
  	}
  	CBaseMonster *GetMonsterPointer( edict_t *pentMonster ) 
  	{ 
  		CBaseEntity *pEntity = Instance( pentMonster );
  		if ( pEntity )
  			return pEntity->MyMonsterPointer();
  		return NULL;
  	}
  
  
  	// Ugly code to lookup all functions to make sure they are exported when set.
  #ifdef _DEBUG
  	void FunctionCheck( void *pFunction, char *name ) 
  	{ 
  #ifdef _WIN32
  		if (pFunction && !NAME_FOR_FUNCTION((unsigned long)(pFunction)) )
  			ALERT( at_error, "No EXPORT: %s:%s (%08lx)\n", STRING(pev->classname), name, (unsigned long)pFunction );
  #endif // _WIN32
  	}
  
  	BASEPTR	ThinkSet( BASEPTR func, char *name ) 
  	{ 
  		m_pfnThink = func; 
  		FunctionCheck( (void *)*((int *)((char *)this + ( offsetof(CBaseEntity,m_pfnThink)))), name ); 
  		return func;
  	}
  	ENTITYFUNCPTR TouchSet( ENTITYFUNCPTR func, char *name ) 
  	{ 
  		m_pfnTouch = func; 
  		FunctionCheck( (void *)*((int *)((char *)this + ( offsetof(CBaseEntity,m_pfnTouch)))), name ); 
  		return func;
  	}
  	USEPTR	UseSet( USEPTR func, char *name ) 
  	{ 
  		m_pfnUse = func; 
  		FunctionCheck( (void *)*((int *)((char *)this + ( offsetof(CBaseEntity,m_pfnUse)))), name ); 
  		return func;
  	}
  	ENTITYFUNCPTR	BlockedSet( ENTITYFUNCPTR func, char *name ) 
  	{ 
  		m_pfnBlocked = func; 
  		FunctionCheck( (void *)*((int *)((char *)this + ( offsetof(CBaseEntity,m_pfnBlocked)))), name ); 
  		return func;
  	}
  
  #endif
  
  
  	// virtual functions used by a few classes
  	
  	// used by monsters that are created by the MonsterMaker
  	virtual	void UpdateOwner( void ) { return; };
  
  
  	//
  	static CBaseEntity *Create( char *szName, const Vector &vecOrigin, const Vector &vecAngles, edict_t *pentOwner = NULL );
  
  	virtual BOOL FBecomeProne( void ) {return FALSE;};
  	edict_t *edict() { return ENT( pev ); };
  	EOFFSET eoffset( ) { return OFFSET( pev ); };
  	int	  entindex( ) { return ENTINDEX( edict() ); };
  
  	virtual Vector Center( ) { return (pev->absmax + pev->absmin) * 0.5; }; // center point of entity
  	virtual Vector EyePosition( ) { return pev->origin + pev->view_ofs; };			// position of eyes
  	virtual Vector EarPosition( ) { return pev->origin + pev->view_ofs; };			// position of ears
  	virtual Vector BodyTarget( const Vector &posSrc ) { return Center( ); };		// position to shoot at
  
  	virtual int Illumination( ) { return GETENTITYILLUM( ENT( pev ) ); };
  
  	virtual	BOOL FVisible ( CBaseEntity *pEntity );
  	virtual	BOOL FVisible ( const Vector &vecOrigin );
  
  	// Last touched by Jump pad
  	float	m_flTouchedByJumpPad;
  };
  
  
  
  // Ugly technique to override base member functions
  // Normally it's illegal to cast a pointer to a member function of a derived class to a pointer to a 
  // member function of a base class.  static_cast is a sleezy way around that problem.
  
  #ifdef _DEBUG
  
  #define SetThink( a ) ThinkSet( static_cast <void (CBaseEntity::*)(void)> (a), #a )
  #define SetTouch( a ) TouchSet( static_cast <void (CBaseEntity::*)(CBaseEntity *)> (a), #a )
  #define SetUse( a ) UseSet( static_cast <void (CBaseEntity::*)(	CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )> (a), #a )
  #define SetBlocked( a ) BlockedSet( static_cast <void (CBaseEntity::*)(CBaseEntity *)> (a), #a )
  
  #else
  
  #define SetThink( a ) m_pfnThink = static_cast <void (CBaseEntity::*)(void)> (a)
  #define SetTouch( a ) m_pfnTouch = static_cast <void (CBaseEntity::*)(CBaseEntity *)> (a)
  #define SetUse( a ) m_pfnUse = static_cast <void (CBaseEntity::*)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )> (a)
  #define SetBlocked( a ) m_pfnBlocked = static_cast <void (CBaseEntity::*)(CBaseEntity *)> (a)
  
  #endif
  
  
  class CPointEntity : public CBaseEntity
  {
  public:
  	void	Spawn( void );
  	virtual int	ObjectCaps( void ) { return CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
  private:
  };
  
  
  typedef struct locksounds			// sounds that doors and buttons make when locked/unlocked
  {
  	string_t	sLockedSound;		// sound a door makes when it's locked
  	string_t	sLockedSentence;	// sentence group played when door is locked
  	string_t	sUnlockedSound;		// sound a door makes when it's unlocked
  	string_t	sUnlockedSentence;	// sentence group played when door is unlocked
  
  	int		iLockedSentence;		// which sentence in sentence group to play next
  	int		iUnlockedSentence;		// which sentence in sentence group to play next
  
  	float	flwaitSound;			// time delay between playing consecutive 'locked/unlocked' sounds
  	float	flwaitSentence;			// time delay between playing consecutive sentences
  	BYTE	bEOFLocked;				// true if hit end of list of locked sentences
  	BYTE	bEOFUnlocked;			// true if hit end of list of unlocked sentences
  } locksound_t;
  
  void PlayLockSounds(entvars_t *pev, locksound_t *pls, int flocked, int fbutton);
  
  //
  // MultiSouce
  //
  
  #define MAX_MULTI_TARGETS	16 // maximum number of targets a single multi_manager entity may be assigned.
  #define MS_MAX_TARGETS 32
  
  class CMultiSource : public CPointEntity
  {
  public:
  	void Spawn( );
  	void KeyValue( KeyValueData *pkvd );
  	void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  	int	ObjectCaps( void ) { return (CPointEntity::ObjectCaps() | FCAP_MASTER); }
  	BOOL IsTriggered( CBaseEntity *pActivator );
  	void EXPORT Register( void );
  	virtual int		Save( CSave &save );
  	virtual int		Restore( CRestore &restore );
  
  	static	TYPEDESCRIPTION m_SaveData[];
  
  	EHANDLE		m_rgEntities[MS_MAX_TARGETS];
  	int			m_rgTriggered[MS_MAX_TARGETS];
  
  	int			m_iTotal;
  	string_t	m_globalstate;
  };
  
  
  //
  // generic Delay entity.
  //
  class CBaseDelay : public CBaseEntity
  {
  public:
  	float		m_flDelay;
  	int			m_iszKillTarget;
  
  	virtual void	KeyValue( KeyValueData* pkvd);
  	virtual int		Save( CSave &save );
  	virtual int		Restore( CRestore &restore );
  	
  	static	TYPEDESCRIPTION m_SaveData[];
  	// common member functions
  	void SUB_UseTargets( CBaseEntity *pActivator, USE_TYPE useType, float value );
  	void EXPORT DelayThink( void );
  };
  
  
  class CBaseAnimating : public CBaseDelay
  {
  public:
  	virtual int		Save( CSave &save );
  	virtual int		Restore( CRestore &restore );
  
  	static	TYPEDESCRIPTION m_SaveData[];
  
  	// Basic Monster Animation functions
  	float StudioFrameAdvance( float flInterval = 0.0 ); // accumulate animation frame time from last time called until now
  	int	 GetSequenceFlags( void );
  	int  LookupActivity ( int activity );
  	int  LookupActivityHeaviest ( int activity );
  	int  LookupSequence ( const char *label );
  	void ResetSequenceInfo ( );
  	void DispatchAnimEvents ( float flFutureInterval = 0.1 ); // Handle events that have happend since last time called up until X seconds into the future
  	virtual void HandleAnimEvent( MonsterEvent_t *pEvent ) { return; };
  	float SetBoneController ( int iController, float flValue );
  	void InitBoneControllers ( void );
  	float SetBlending ( int iBlender, float flValue );
  	void GetBonePosition ( int iBone, Vector &origin, Vector &angles );
  	void GetAutomovement( Vector &origin, Vector &angles, float flInterval = 0.1 );
  	int  FindTransition( int iEndingSequence, int iGoalSequence, int *piDir );
  	void GetAttachment ( int iAttachment, Vector &origin, Vector &angles );
  	void SetBodygroup( int iGroup, int iValue );
  	int GetBodygroup( int iGroup );
  	int ExtractBbox( int sequence, float *mins, float *maxs );
  	void SetSequenceBox( void );
  
  	// animation needs
  	float				m_flFrameRate;		// computed FPS for current sequence
  	float				m_flGroundSpeed;	// computed linear movement rate for current sequence
  	float				m_flLastEventCheck;	// last time the event list was checked
  	BOOL				m_fSequenceFinished;// flag set when StudioAdvanceFrame moves across a frame boundry
  	BOOL				m_fSequenceLoops;	// true if the sequence loops
  };
  
  
  //
  // generic Toggle entity.
  //
  #define	SF_ITEM_USE_ONLY	256 //  ITEM_USE_ONLY = BUTTON_USE_ONLY = DOOR_USE_ONLY!!! 
  
  class CBaseToggle : public CBaseAnimating
  {
  public:
  	void				KeyValue( KeyValueData *pkvd );
  
  	TOGGLE_STATE		m_toggle_state;
  	float				m_flActivateFinished;//like attack_finished, but for doors
  	float				m_flMoveDistance;// how far a door should slide or rotate
  	float				m_flWait;
  	float				m_flLip;
  	float				m_flTWidth;// for plats
  	float				m_flTLength;// for plats
  
  	Vector				m_vecPosition1;
  	Vector				m_vecPosition2;
  	Vector				m_vecAngle1;
  	Vector				m_vecAngle2;
  
  	int					m_cTriggersLeft;		// trigger_counter only, # of activations remaining
  	float				m_flHeight;
  	EHANDLE				m_hActivator;
  	void (CBaseToggle::*m_pfnCallWhenMoveDone)(void);
  	Vector				m_vecFinalDest;
  	Vector				m_vecFinalAngle;
  
  	int					m_bitsDamageInflict;	// DMG_ damage type that the door or tigger does
  
  	virtual int		Save( CSave &save );
  	virtual int		Restore( CRestore &restore );
  
  	static	TYPEDESCRIPTION m_SaveData[];
  
  	virtual int		GetToggleState( void ) { return m_toggle_state; }
  	virtual float	GetDelay( void ) { return m_flWait; }
  
  	// common member functions
  	void LinearMove( Vector	vecDest, float flSpeed );
  	void EXPORT LinearMoveDone( void );
  	void AngularMove( Vector vecDestAngle, float flSpeed );
  	void EXPORT AngularMoveDone( void );
  	BOOL IsLockedByMaster( void );
  
  	static float		AxisValue( int flags, const Vector &angles );
  	static void			AxisDir( entvars_t *pev );
  	static float		AxisDelta( int flags, const Vector &angle1, const Vector &angle2 );
  
  	string_t m_sMaster;		// If this button has a master switch, this is the targetname.
  							// A master switch must be of the multisource type. If all 
  							// of the switches in the multisource have been triggered, then
  							// the button will be allowed to operate. Otherwise, it will be
  							// deactivated.
  };
  #define SetMoveDone( a ) m_pfnCallWhenMoveDone = static_cast <void (CBaseToggle::*)(void)> (a)
  
  
  // people gib if their health is <= this at the time of death
  #define	GIB_HEALTH_VALUE	-30
  
  #define	ROUTE_SIZE			8 // how many waypoints a monster can store at one time
  #define MAX_OLD_ENEMIES		4 // how many old enemies to remember
  
  #define	bits_CAP_DUCK			( 1 << 0 )// crouch
  #define	bits_CAP_JUMP			( 1 << 1 )// jump/leap
  #define bits_CAP_STRAFE			( 1 << 2 )// strafe ( walk/run sideways)
  #define bits_CAP_SQUAD			( 1 << 3 )// can form squads
  #define	bits_CAP_SWIM			( 1 << 4 )// proficiently navigate in water
  #define bits_CAP_CLIMB			( 1 << 5 )// climb ladders/ropes
  #define bits_CAP_USE			( 1 << 6 )// open doors/push buttons/pull levers
  #define bits_CAP_HEAR			( 1 << 7 )// can hear forced sounds
  #define bits_CAP_AUTO_DOORS		( 1 << 8 )// can trigger auto doors
  #define bits_CAP_OPEN_DOORS		( 1 << 9 )// can open manual doors
  #define bits_CAP_TURN_HEAD		( 1 << 10)// can turn head, always bone controller 0
  
  #define bits_CAP_RANGE_ATTACK1	( 1 << 11)// can do a range attack 1
  #define bits_CAP_RANGE_ATTACK2	( 1 << 12)// can do a range attack 2
  #define bits_CAP_MELEE_ATTACK1	( 1 << 13)// can do a melee attack 1
  #define bits_CAP_MELEE_ATTACK2	( 1 << 14)// can do a melee attack 2
  
  #define bits_CAP_FLY			( 1 << 15)// can fly, move all around
  
  #define bits_CAP_DOORS_GROUP    (bits_CAP_USE | bits_CAP_AUTO_DOORS | bits_CAP_OPEN_DOORS)
  
  // used by suit voice to indicate damage sustained and repaired type to player
  
  // instant damage
  
  #define DMG_GENERIC			0			// generic damage was done
  #define DMG_CRUSH			(1 << 0)	// crushed by falling or moving object
  #define DMG_BULLET			(1 << 1)	// shot
  #define DMG_SLASH			(1 << 2)	// cut, clawed, stabbed
  #define DMG_BURN			(1 << 3)	// heat burned
  #define DMG_FREEZE			(1 << 4)	// frozen
  #define DMG_FALL			(1 << 5)	// fell too far
  #define DMG_BLAST			(1 << 6)	// explosive blast damage
  #define DMG_CLUB			(1 << 7)	// crowbar, punch, headbutt
  #define DMG_SHOCK			(1 << 8)	// electric shock
  #define DMG_SONIC			(1 << 9)	// sound pulse shockwave
  #define DMG_ENERGYBEAM		(1 << 10)	// laser or other high energy beam 
  #define DMG_NEVERGIB		(1 << 12)	// with this bit OR'd in, no damage type will be able to gib victims upon death
  #define DMG_ALWAYSGIB		(1 << 13)	// with this bit OR'd in, any damage type can be made to gib victims upon death.
  #define DMG_DROWN			(1 << 14)	// Drowning
  // time-based damage
  #define DMG_TIMEBASED		(~(0x3fff))	// mask for time-based damage
  
  #define DMG_PARALYZE		(1 << 15)	// slows affected creature down
  #define DMG_NERVEGAS		(1 << 16)	// nerve toxins, very bad
  #define DMG_POISON			(1 << 17)	// blood poisioning
  #define DMG_RADIATION		(1 << 18)	// radiation exposure
  #define DMG_DROWNRECOVER	(1 << 19)	// drowning recovery
  #define DMG_ACID			(1 << 20)	// toxic chemicals or acid burns
  #define DMG_SLOWBURN		(1 << 21)	// in an oven
  #define DMG_SLOWFREEZE		(1 << 22)	// in a subzero freezer
  #define DMG_MORTAR			(1 << 23)	// Hit by air raid (done to distinguish grenade from mortar)
  
  // these are the damage types that are allowed to gib corpses
  #define DMG_GIB_CORPSE		( DMG_CRUSH | DMG_FALL | DMG_BLAST | DMG_SONIC | DMG_CLUB )
  
  // these are the damage types that have client hud art
  #define DMG_SHOWNHUD		(DMG_POISON | DMG_ACID | DMG_FREEZE | DMG_SLOWFREEZE | DMG_DROWN | DMG_BURN | DMG_SLOWBURN | DMG_NERVEGAS | DMG_RADIATION | DMG_SHOCK)
  
  // NOTE: tweak these values based on gameplay feedback:
  
  #define PARALYZE_DURATION	2		// number of 2 second intervals to take damage
  #define PARALYZE_DAMAGE		1.0		// damage to take each 2 second interval
  
  #define NERVEGAS_DURATION	2
  #define NERVEGAS_DAMAGE		5.0
  
  #define POISON_DURATION		5
  #define POISON_DAMAGE		2.0
  
  #define RADIATION_DURATION	2
  #define RADIATION_DAMAGE	1.0
  
  #define ACID_DURATION		2
  #define ACID_DAMAGE			5.0
  
  #define SLOWBURN_DURATION	2
  #define SLOWBURN_DAMAGE		1.0
  
  #define SLOWFREEZE_DURATION	2
  #define SLOWFREEZE_DAMAGE	1.0
  
  
  #define	itbd_Paralyze		0		
  #define	itbd_NerveGas		1
  #define	itbd_Poison			2
  #define	itbd_Radiation		3
  #define	itbd_DrownRecover	4
  #define	itbd_Acid			5
  #define	itbd_SlowBurn		6
  #define	itbd_SlowFreeze		7
  #define CDMG_TIMEBASED		8
  
  // when calling KILLED(), a value that governs gib behavior is expected to be 
  // one of these three values
  #define GIB_NORMAL			0// gib if entity was overkilled
  #define GIB_NEVER			1// never gib, no matter how much death damage is done ( freezing, etc )
  #define GIB_ALWAYS			2// always gib ( Houndeye Shock, Barnacle Bite )
  
  class CBaseMonster;
  class CCineMonster;
  class CSound;
  
  #include "basemonster.h"
  
  
  char *ButtonSound( int sound );				// get string of button sound number
  
  
  //
  // Generic Button
  //
  class CBaseButton : public CBaseToggle
  {
  public:
  	void Spawn( void );
  	virtual void Precache( void );
  	void RotSpawn( void );
  	virtual void KeyValue( KeyValueData* pkvd);
  
  	void ButtonActivate( );
  	void SparkSoundCache( void );
  
  	void EXPORT ButtonShot( void );
  	void EXPORT ButtonTouch( CBaseEntity *pOther );
  	void EXPORT ButtonSpark ( void );
  	void EXPORT TriggerAndWait( void );
  	void EXPORT ButtonReturn( void );
  	void EXPORT ButtonBackHome( void );
  	void EXPORT ButtonUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  	virtual int		TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
  	virtual int		Save( CSave &save );
  	virtual int		Restore( CRestore &restore );
  	
  	enum BUTTON_CODE { BUTTON_NOTHING, BUTTON_ACTIVATE, BUTTON_RETURN };
  	BUTTON_CODE	ButtonResponseToTouch( void );
  	
  	static	TYPEDESCRIPTION m_SaveData[];
  	// Buttons that don't take damage can be IMPULSE used
  	virtual int	ObjectCaps( void ) { return (CBaseToggle:: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | (pev->takedamage?0:FCAP_IMPULSE_USE); }
  
  	BOOL	m_fStayPushed;	// button stays pushed in until touched again?
  	BOOL	m_fRotating;		// a rotating button?  default is a sliding button.
  
  	string_t m_strChangeTarget;	// if this field is not null, this is an index into the engine string array.
  							// when this button is touched, it's target entity's TARGET field will be set
  							// to the button's ChangeTarget. This allows you to make a func_train switch paths, etc.
  
  	locksound_t m_ls;			// door lock sounds
  	
  	BYTE	m_bLockedSound;		// ordinals from entity selection
  	BYTE	m_bLockedSentence;	
  	BYTE	m_bUnlockedSound;	
  	BYTE	m_bUnlockedSentence;
  	int		m_sounds;
  };
  
  //
  // Weapons 
  //
  
  #define	BAD_WEAPON 0x00007FFF
  
  //
  // Converts a entvars_t * to a class pointer
  // It will allocate the class and entity if necessary
  //
  template <class T> T * GetClassPtr( T *a )
  {
  	entvars_t *pev = (entvars_t *)a;
  
  	// allocate entity if necessary
  	if (pev == NULL)
  		pev = VARS(CREATE_ENTITY());
  
  	// get the private data
  	a = (T *)GET_PRIVATE(ENT(pev));
  
  	if (a == NULL) 
  	{
  		// allocate private data 
  		a = new(pev) T;
  		a->pev = pev;
  	}
  	return a;
  }
  
  
  /*
  bit_PUSHBRUSH_DATA | bit_TOGGLE_DATA
  bit_MONSTER_DATA
  bit_DELAY_DATA
  bit_TOGGLE_DATA | bit_DELAY_DATA | bit_MONSTER_DATA
  bit_PLAYER_DATA | bit_MONSTER_DATA
  bit_MONSTER_DATA | CYCLER_DATA
  bit_LIGHT_DATA
  path_corner_data
  bit_MONSTER_DATA | wildcard_data
  bit_MONSTER_DATA | bit_GROUP_DATA
  boid_flock_data
  boid_data
  CYCLER_DATA
  bit_ITEM_DATA
  bit_ITEM_DATA | func_hud_data
  bit_TOGGLE_DATA | bit_ITEM_DATA
  EOFFSET
  env_sound_data
  env_sound_data
  push_trigger_data
  */
  
  #define TRACER_FREQ		4			// Tracers fire every 4 bullets
  
  typedef struct _SelAmmo
  {
  	BYTE	Ammo1Type;
  	BYTE	Ammo1;
  	BYTE	Ammo2Type;
  	BYTE	Ammo2;
  } SelAmmo;
  
  
  // this moved here from world.cpp, to allow classes to be derived from it
  //=======================
  // CWorld
  //
  // This spawns first when each level begins.
  //=======================
  class CWorld : public CBaseEntity
  {
  public:
  	void Spawn( void );
  	void Precache( void );
  	void KeyValue( KeyValueData *pkvd );
  
  	int	 m_iArenaOff;
  };
  