|
|
|
/***
|
|
|
|
*
|
|
|
|
* 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 CBASE_H
|
|
|
|
#define CBASE_H
|
|
|
|
/*
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
#include "exportdef.h"
|
|
|
|
|
|
|
|
extern "C" EXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion );
|
|
|
|
extern "C" EXPORT int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
|
|
|
|
extern "C" EXPORT int Server_GetPhysicsInterface( int iVersion, server_physics_api_t *pfuncsFromEngine, physics_interface_t *pFunctionTable );
|
|
|
|
|
|
|
|
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, const 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 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
|
|
|
|
|
|
|
|
virtual 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 );
|
|
|
|
Vector FireBulletsPlayer( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq = 4, int iDamage = 0, entvars_t *pevAttacker = NULL, int shared_rand = 0 );
|
|
|
|
|
|
|
|
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; }
|
|
|
|
|
|
|
|
static CBaseEntity *Instance( edict_t *pent )
|
|
|
|
{
|
|
|
|
if( !pent )
|
|
|
|
pent = ENT( 0 );
|
|
|
|
CBaseEntity *pEnt = (CBaseEntity *)GET_PRIVATE( pent );
|
|
|
|
return pEnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 )
|
|
|
|
{
|
|
|
|
if( pFunction && !NAME_FOR_FUNCTION( (size_t)( pFunction ) ) )
|
|
|
|
ALERT( at_error, "No EXPORT: %s:%s (%08lx)\n", STRING( pev->classname ), name, (size_t)pFunction );
|
|
|
|
}
|
|
|
|
|
|
|
|
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( const 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 );
|
|
|
|
|
|
|
|
//We use this variables to store each ammo count.
|
|
|
|
int ammo_9mm;
|
|
|
|
int ammo_357;
|
|
|
|
int ammo_bolts;
|
|
|
|
int ammo_buckshot;
|
|
|
|
int ammo_rockets;
|
|
|
|
int ammo_uranium;
|
|
|
|
int ammo_hornets;
|
|
|
|
int ammo_argrens;
|
|
|
|
//Special stuff for grenades and satchels.
|
|
|
|
float m_flStartThrow;
|
|
|
|
float m_flReleaseThrow;
|
|
|
|
int m_chargeReady;
|
|
|
|
int m_fInAttack;
|
|
|
|
|
|
|
|
enum EGON_FIRESTATE { FIRE_OFF, FIRE_CHARGE };
|
|
|
|
int m_fireState;
|
|
|
|
};
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
#define ResetThink( ) m_pfnThink = static_cast <void (CBaseEntity::*)(void)> (NULL)
|
|
|
|
#define ResetTouch( ) m_pfnTouch = static_cast <void (CBaseEntity::*)(CBaseEntity *)> (NULL)
|
|
|
|
#define ResetUse( ) m_pfnUse = static_cast <void (CBaseEntity::*)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )> (NULL)
|
|
|
|
#define ResetBlocked( ) m_pfnBlocked = static_cast <void (CBaseEntity::*)(CBaseEntity *)> (NULL)
|
|
|
|
|
|
|
|
#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"
|
|
|
|
|
|
|
|
const 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 );
|
|
|
|
};
|
|
|
|
#endif
|