/*** * * 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. * ****/ #pragma once #if !defined(CBASE_H) #define CBASE_H /* Class Hierachy CBaseEntity CPointEntity CBasePlayerAmmo CBaseDelay CBaseAnimating CBasePlayerItem CBasePlayerWeapon CBaseToggle CBaseButton CBaseDoor CBaseTrigger CBasePlatTrain CBaseMonster CCycler CBasePlayer CCineMonster */ #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) // LRC: no longer used #define FCAP_ONLYDIRECT_USE 0x00000100 //LRC - can't use this entity through a wall. // 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" #if !defined(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 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 ); //extern CBaseEntity *g_pDesiredList; //LRC- handles DesiredVel, for movewith //LRC- added USE_SAME, USE_NOT, and USE_KILL typedef enum { USE_OFF = 0, USE_ON = 1, USE_SET = 2, USE_TOGGLE = 3, USE_KILL = 4, // special signals, never actually get sent: USE_SAME = 5, USE_NOT = 6, } USE_TYPE; extern const char *GetStringForUseType( USE_TYPE useType ); 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_FACTION_A 14 //LRC - very simple new classes, for use with Behaves As #define CLASS_FACTION_B 15 #define CLASS_FACTION_C 16 #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; class CThinker; #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. CBaseEntity *m_pMoveWith; // LRC- the entity I move with. int m_MoveWith; //LRC- Name of that entity CBaseEntity *m_pChildMoveWith; //LRC- one of the entities that's moving with me. CBaseEntity *m_pSiblingMoveWith; //LRC- another entity that's Moving With the same ent as me. (linked list.) Vector m_vecMoveWithOffset; // LRC- Position I should be in relative to m_pMoveWith->pev->origin. Vector m_vecRotWithOffset; // LRC- Angles I should be facing relative to m_pMoveWith->pev->angles. CBaseEntity *m_pAssistLink; // LRC- link to the next entity which needs to be Assisted before physics are applied. Vector m_vecPostAssistVel; // LRC Vector m_vecPostAssistAVel; // LRC float m_fNextThink; // LRC - for SetNextThink and SetPhysThink. Marks the time when a think will be performed - not necessarily the same as pev->nextthink! float m_fPevNextThink; // LRC - always set equal to pev->nextthink, so that we can tell when the latter gets changed by the @#$^¬! engine. int m_iLFlags; // LRC- a new set of flags. (pev->spawnflags and pev->flags are full...) virtual void DesiredAction( void ) {}; // LRC - for postponing stuff until PostThink time, not as a think. int m_iStyle; // LRC - almost anything can have a lightstyle these days... Vector m_vecSpawnOffset; // LRC- To fix things which (for example) MoveWith a door which Starts Open. BOOL m_activated; // LRC- moved here from func_train. Signifies that an entity has already been // activated. (and hence doesn't need reactivating.) //LRC - decent mechanisms for setting think times! // this should have been done a long time ago, but MoveWith finally forced me. virtual void SetNextThink( float delay ) { SetNextThink(delay, FALSE); } virtual void SetNextThink( float delay, BOOL correctSpeed ); virtual void AbsoluteNextThink( float time ) { AbsoluteNextThink(time, FALSE); } virtual void AbsoluteNextThink( float time, BOOL correctSpeed ); void SetEternalThink( ); // this is called by an entity which is starting to move, and will reach // its destination after the given wait. // Its think function should be called at that time, to make it stop moving. // void SetPhysThink( float delay ); // this is called by an entity which is movingWith another entity. // it signifies that the other entity is starting to move and will reach its // destination after the given wait. // This entity will need to think at that time (so that physics gets // processed correctly), but the Think function shouldn't actually get // called; the parent will intervene to make it stop. // void SetMWPhysThink( float delay ); // this is called by an entity which is starting to move, and wants its children // to follow it. // void SetChildrenThink( float delay ); //LRC use this instead of "SetThink( NULL )" or "pev->nextthink = -1". void DontThink( void ); //LRC similar, but called by the parent when a think needs to be aborted. // void DontMWThink( void ); virtual void ThinkCorrection( void ); //LRC - loci virtual Vector CalcPosition( CBaseEntity *pLocus ) { return pev->origin; } virtual Vector CalcVelocity( CBaseEntity *pLocus ) { return pev->velocity; } virtual float CalcRatio( CBaseEntity *pLocus ) { return 0; } //LRC - aliases virtual BOOL IsAlias( void ) { return FALSE; } // initialization functions virtual void Spawn( void ) { return; } virtual void Precache( void ) { return; } virtual void KeyValue( KeyValueData* pkvd) { //LRC - MoveWith for all! if (FStrEq(pkvd->szKeyName, "movewith")) { m_MoveWith = ALLOC_STRING(pkvd->szValue); pkvd->fHandled = TRUE; } else if (FStrEq(pkvd->szKeyName, "skill")) { m_iLFlags = atoi(pkvd->szValue); pkvd->fHandled = TRUE; } else if (FStrEq(pkvd->szKeyName, "style")) { m_iStyle = atoi(pkvd->szValue); pkvd->fHandled = TRUE; } else pkvd->fHandled = FALSE; } virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); //LRC - if I MoveWith something, then only cross transitions if the MoveWith entity does too. virtual int ObjectCaps( void ) { return m_pMoveWith?m_pMoveWith->ObjectCaps()&FCAP_ACROSS_TRANSITION:FCAP_ACROSS_TRANSITION; } virtual void Activate( void ); //LRC void InitMoveWith( void ); //LRC - called by Activate() to set up moveWith values virtual void PostSpawn( void ) {} //LRC - called by Activate() to handle entity-specific initialisation. // (mostly setting positions, for MoveWith support) // 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 (e.g., "alien monster", or "human military" so that monsters // on the same side won't attack each other, even if they have different classnames. 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. // LRC- this supports a global concept of "entities with states", so that state_watchers and // mastership (mastery? masterhood?) can work universally. virtual STATE GetState ( void ) { return STATE_OFF; }; // For team-specific doors in multiplayer, etc: a master's state depends on who wants to know. virtual STATE GetState ( CBaseEntity* pEnt ) { return GetState(); }; 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 ); //LRC- superceded by GetState ( pActivator ). // 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->target) ); } 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 ) // a think function used at spawn time. Don't apply the moveWith fix to it. { this->Use( this, this, USE_TOGGLE, 0 ); } int ShouldToggle( USE_TYPE useType, BOOL currentState ); int ShouldToggle( USE_TYPE useType ); //LRC this version uses GetState() 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. #if _DEBUG void FunctionCheck( void *pFunction, char *name ) { if( pFunction && !NAME_FOR_FUNCTION( 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_50ae; int ammo_buckshot; int ammo_9mmar; // 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; }; //LRC- moved here from player.cpp. I'd put it in util.h with its friends, but it needs CBaseEntity to be declared. inline BOOL FNullEnt( CBaseEntity *ent ) { return ent == NULL || FNullEnt( ent->edict() ); } // 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. #if _DEBUG #define SetThink( a ) ThinkSet( static_cast (a), #a ) #define SetTouch( a ) TouchSet( static_cast (a), #a ) #define SetUse( a ) UseSet( static_cast (a), #a ) #define SetBlocked( a ) BlockedSet( static_cast (a), #a ) #define ResetThink() SetThink(NULL) #else #define SetThink( a ) m_pfnThink = static_cast (a) #define SetTouch( a ) m_pfnTouch = static_cast (a) #define SetUse( a ) m_pfnUse = static_cast (a) #define SetBlocked( a ) m_pfnBlocked = static_cast (a) #define ResetThink( ) m_pfnThink = static_cast (NULL) #define ResetTouch( ) m_pfnTouch = static_cast (NULL) #define ResetUse( ) m_pfnUse = static_cast (NULL) #define ResetBlocked( ) m_pfnBlocked = static_cast (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 ); STATE GetState( void ); 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; string_t m_iszKillTarget; EHANDLE m_hActivator; //LRC - moved here from CBaseToggle 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 ); //LRC int GetBoneCount( void ); void SetBones( float (*data)[3], int datasize ); 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; void (CBaseToggle::*m_pfnCallWhenMoveDone)(void); Vector m_vecFinalDest; float m_flLinearMoveSpeed; // LRC- allows a LinearMove to be delayed until a think. float m_flAngularMoveSpeed; // LRC 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; } // LRC- overridden because toggling entities have general rules governing their states. virtual STATE GetState( void ); virtual float GetDelay( void ) { return m_flWait; } // common member functions void LinearMove( Vector vecInput, float flSpeed ); //void LinearMove( Vector vecInput, float flSpeed, BOOL bNow ); void EXPORT LinearMoveNow( void ); //LRC- think function that lets us guarantee a LinearMove gets done as a think. void EXPORT LinearMoveDone( void ); void EXPORT LinearMoveDoneNow( void ); //LRC // void EXPORT LinearMoveFinalDone( void ); void AngularMove( Vector vecDestAngle, float flSpeed ); void EXPORT AngularMoveNow( void ); //LRC- think function that lets us guarantee an AngularMove gets done as a think. void EXPORT AngularMoveDone( void ); void EXPORT AngularMoveDoneNow( 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 (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) #define DMG_SPEAR (1 << 24) // 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 PostSpawn( void ); //LRC 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_IgnorePlayer( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); 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[]; virtual int ObjectCaps( void ); 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 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; //LRC- much as I hate to add new globals, I can't see how to read data from the World entity. extern BOOL g_startSuit; //LRC- moved here from alias.cpp so that util functions can use these defs. class CBaseAlias : public CPointEntity { public: BOOL IsAlias( void ) { return TRUE; }; virtual CBaseEntity *FollowAlias( CBaseEntity *pFrom ) { return NULL; }; virtual void ChangeValue( int iszValue ) { ALERT(at_error, "%s entities cannot change value!", STRING(pev->classname)); } virtual void ChangeValue( CBaseEntity *pValue ) { ChangeValue(pValue->pev->targetname); } virtual void FlushChanges( void ) {}; virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; CBaseAlias *m_pNextAlias; }; class CInfoGroup : public CPointEntity { public: void KeyValue( KeyValueData *pkvd ); void Use(CBaseEntity* pActivator, CBaseEntity* pCaller, USE_TYPE useType, float value); int GetMember( const char* szMemberName ); virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; int m_cMembers; int m_iszMemberName [ MAX_MULTI_TARGETS ]; int m_iszMemberValue [ MAX_MULTI_TARGETS ]; int m_iszDefaultMember; }; class CMultiAlias : public CBaseAlias { public: void KeyValue( KeyValueData *pkvd ); virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; CBaseEntity *FollowAlias( CBaseEntity *pFrom ); int m_cTargets; int m_iszTargets [ MAX_MULTI_TARGETS ]; int m_iTotalValue; int m_iValues [ MAX_MULTI_TARGETS ]; int m_iMode; }; // 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 ); CBaseAlias *m_pFirstAlias; }; extern CWorld *g_pWorld; #endif