421 lines
18 KiB
C++
421 lines
18 KiB
C++
/***
|
|
*
|
|
* 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.
|
|
*
|
|
* This source code contains proprietary and confidential information of
|
|
* Valve LLC and its suppliers. Access to this code is restricted to
|
|
* persons who have executed a written SDK license with Valve. Any access,
|
|
* use or distribution of this code by or to any unlicensed person is illegal.
|
|
*
|
|
****/
|
|
|
|
#ifndef BASEMONSTER_H
|
|
#define BASEMONSTER_H
|
|
|
|
#include "AI_Target.h"
|
|
|
|
#define AI_CALC_YAW_SPEED -1
|
|
#define AI_KEEP_YAW_SPEED -2
|
|
|
|
//
|
|
// generic Monster
|
|
//
|
|
class CBaseMonster : public CBaseToggle
|
|
{
|
|
private:
|
|
int m_afConditions;
|
|
|
|
public:
|
|
typedef enum
|
|
{
|
|
SCRIPT_PLAYING = 0, // Playing the sequence
|
|
SCRIPT_WAIT, // Waiting on everyone in the script to be ready
|
|
SCRIPT_CLEANUP, // Cancelling the script / cleaning up
|
|
SCRIPT_WALK_TO_MARK,
|
|
SCRIPT_RUN_TO_MARK,
|
|
} SCRIPTSTATE;
|
|
|
|
|
|
|
|
// these fields have been added in the process of reworking the state machine. (sjb)
|
|
EHANDLE m_hEnemy; // the entity that the monster is fighting.
|
|
EHANDLE m_hTargetEnt; // the entity that the monster is trying to reach
|
|
EHANDLE m_hOldEnemy[ MAX_OLD_ENEMIES ];
|
|
Vector m_vecOldEnemy[ MAX_OLD_ENEMIES ];
|
|
|
|
float m_flFieldOfView;// width of monster's field of view ( dot product )
|
|
float m_flWaitFinished;// if we're told to wait, this is the time that the wait will be over.
|
|
float m_flMoveWaitFinished;
|
|
|
|
Activity m_Activity;// what the monster is doing (animation)
|
|
Activity m_IdealActivity;// monster should switch to this activity
|
|
|
|
int m_LastHitGroup; // the last body region that took damage
|
|
|
|
MONSTERSTATE m_MonsterState;// monster's current state
|
|
MONSTERSTATE m_IdealMonsterState;// monster should change to this state
|
|
|
|
int m_iTaskStatus;
|
|
Schedule_t *m_pSchedule;
|
|
int m_iScheduleIndex;
|
|
|
|
WayPoint_t m_Route[ ROUTE_SIZE ]; // Positions of movement
|
|
int m_movementGoal; // Goal that defines route
|
|
int m_iRouteIndex; // index into m_Route[]
|
|
float m_moveWaitTime; // How long I should wait for something to move
|
|
|
|
Vector m_vecMoveGoal; // kept around for node graph moves, so we know our ultimate goal
|
|
Activity m_movementActivity; // When moving, set this activity
|
|
|
|
int m_iAudibleList; // first index of a linked list of sounds that the monster can hear.
|
|
int m_afSoundTypes;
|
|
|
|
Vector m_vecLastPosition;// monster sometimes wants to return to where it started after an operation.
|
|
|
|
int m_iHintNode; // this is the hint node that the monster is moving towards or performing active idle on.
|
|
|
|
int m_afMemory;
|
|
|
|
int m_iMaxHealth;// keeps track of monster's maximum health value (for re-healing, etc)
|
|
|
|
Vector m_vecEnemyLKP;// last known position of enemy. (enemy's origin)
|
|
|
|
int m_cAmmoLoaded; // how much ammo is in the weapon (used to trigger reload anim sequences)
|
|
|
|
int m_afCapability;// tells us what a monster can/can't do.
|
|
|
|
float m_flNextAttack; // cannot attack again until this time
|
|
|
|
int m_bitsDamageType; // what types of damage has monster (player) taken
|
|
BYTE m_rgbTimeBasedDamage[CDMG_TIMEBASED];
|
|
|
|
int m_lastDamageAmount;// how much damage did monster (player) last take
|
|
// time based damage counters, decr. 1 per 2 seconds
|
|
int m_bloodColor; // color of blood particless
|
|
|
|
int m_failSchedule; // Schedule type to choose if current schedule fails
|
|
|
|
float m_flHungryTime;// set this is a future time to stop the monster from eating for a while.
|
|
|
|
float m_flDistTooFar; // if enemy farther away than this, bits_COND_ENEMY_TOOFAR set in CheckEnemy
|
|
float m_flDistLook; // distance monster sees (Default 2048)
|
|
|
|
int m_iTriggerCondition;// for scripted AI, this is the condition that will cause the activation of the monster's TriggerTarget
|
|
string_t m_iszTriggerTarget;// name of target that should be fired.
|
|
|
|
Vector m_HackedGunPos; // HACK until we can query end of gun
|
|
|
|
int m_iUseAlertAnims; // buz: start in alert state
|
|
|
|
// Scripted sequence Info
|
|
SCRIPTSTATE m_scriptState; // internal cinematic state
|
|
CCineMonster *m_pCine;
|
|
|
|
virtual int Save( CSave &save );
|
|
virtual int Restore( CRestore &restore );
|
|
|
|
static TYPEDESCRIPTION m_SaveData[];
|
|
|
|
void KeyValue( KeyValueData *pkvd );
|
|
|
|
// monster use function
|
|
void EXPORT MonsterUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
|
void EXPORT CorpseUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
|
|
|
// overrideable Monster member functions
|
|
|
|
// LRC- to allow level-designers to change monster allegiances
|
|
int m_iClass;
|
|
int m_iPlayerReact;
|
|
virtual int Classify( void ) { return m_iClass?m_iClass:CLASS_NONE; }
|
|
|
|
virtual int BloodColor( void ) { return m_bloodColor; }
|
|
|
|
virtual CBaseMonster *MyMonsterPointer( void ) { return this; }
|
|
virtual void Look ( int iDistance );// basic sight function for monsters
|
|
virtual void RunAI ( void );// core ai function!
|
|
void RunAnimation( void );
|
|
void Listen ( void );
|
|
|
|
virtual BOOL AllowDecal( entvars_t *pevAttacker );
|
|
virtual BOOL IsAlive( void ) { return (pev->deadflag != DEAD_DEAD); }
|
|
virtual BOOL ShouldFadeOnDeath( void );
|
|
|
|
// Basic Monster AI functions
|
|
virtual float ChangeYaw ( int speed );
|
|
float VecToYaw( Vector vecDir );
|
|
float DeltaIdealYaw( void );
|
|
|
|
void CalcFacing( float flInterval );
|
|
float ClampYaw( float yawSpeedPerSec, float current, float target, float time );
|
|
float CalcIdealYaw( const Vector &vecTarget );
|
|
// Run the current or specified timestep worth of rotation
|
|
void UpdateYaw( int speed = -1 );
|
|
|
|
void MoveFacing( void );
|
|
|
|
// ----------------------------------------------------
|
|
// Rotational movement (yaw); goal and speed
|
|
// ----------------------------------------------------
|
|
|
|
void SetYawSpeed( float yawSpeed ) { pev->yaw_speed = yawSpeed; }
|
|
float GetYawSpeed( void ) const { return pev->yaw_speed; }
|
|
float GetIdealYaw( void ) const { return pev->ideal_yaw; }
|
|
void SetIdealYaw( float idealYaw ) { pev->ideal_yaw = idealYaw; }
|
|
|
|
// Set ideal yaw specified as a vector
|
|
void SetIdealYaw( const Vector &vecFacing ) { SetIdealYaw( UTIL_VecToYaw( vecFacing )); }
|
|
|
|
// Force the heading to the ideal yaw
|
|
void SnapYaw( void ) { UpdateYaw( 360 ); }
|
|
|
|
// Set ideal yaw based on a specified target
|
|
void SetIdealYawToTarget( const Vector &target );
|
|
float CalcYawSpeed( void );
|
|
void RecalculateYawSpeed( void );
|
|
|
|
// Set the ideal yaw and run the current or specified timestep worth of rotation. Note
|
|
// it is not correct to call any "update" variant of these methods more
|
|
// than once per think cycle
|
|
void SetIdealYawAndUpdate( float idealYaw, float yawSpeed = AI_CALC_YAW_SPEED );
|
|
void SetIdealYawAndUpdate( const Vector &vecFacing, float yawSpeed = AI_CALC_YAW_SPEED ) { SetIdealYawAndUpdate( UTIL_VecToYaw( vecFacing ), yawSpeed ); }
|
|
void SetIdealYawToTargetAndUpdate( const Vector &target, float yawSpeed = AI_CALC_YAW_SPEED );
|
|
|
|
float DamageForce( float damage );
|
|
void AutoSetSize( void );
|
|
|
|
// stuff written for new state machine
|
|
virtual void MonsterThink( void );
|
|
void EXPORT CallMonsterThink( void ) { this->MonsterThink(); }
|
|
virtual int IRelationship ( CBaseEntity *pTarget );
|
|
virtual void MonsterInit ( void );
|
|
virtual void MonsterInitDead( void ); // Call after animation/pose is set up
|
|
virtual void BecomeDead( void );
|
|
void EXPORT CorpseFallThink( void );
|
|
|
|
void EXPORT MonsterInitThink ( void );
|
|
virtual void StartMonster ( void );
|
|
virtual CBaseEntity* BestVisibleEnemy ( void );// finds best visible enemy for attack
|
|
virtual BOOL FInViewCone ( CBaseEntity *pEntity );// see if pEntity is in monster's view cone
|
|
virtual BOOL FInViewCone ( Vector *pOrigin );// see if given location is in monster's view cone
|
|
virtual void HandleAnimEvent( MonsterEvent_t *pEvent );
|
|
|
|
virtual int CheckLocalMove ( const Vector &vecStart, const Vector &vecEnd, CBaseEntity *pTarget, float *pflDist );// check validity of a straight move through space
|
|
virtual void Move( float flInterval = 0.1 );
|
|
virtual void MoveExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval );
|
|
virtual BOOL ShouldAdvanceRoute( float flWaypointDist );
|
|
|
|
virtual Activity GetStoppedActivity( void ) { return ACT_IDLE; }
|
|
virtual void Stop( void ) { m_IdealActivity = GetStoppedActivity(); }
|
|
|
|
// This will stop animation until you call ResetSequenceInfo() at some point in the future
|
|
inline void StopAnimation( void ) { pev->framerate = 0; }
|
|
|
|
// these functions will survey conditions and set appropriate conditions bits for attack types.
|
|
virtual BOOL CheckRangeAttack1( float flDot, float flDist );
|
|
virtual BOOL CheckRangeAttack2( float flDot, float flDist );
|
|
virtual BOOL CheckMeleeAttack1( float flDot, float flDist );
|
|
virtual BOOL CheckMeleeAttack2( float flDot, float flDist );
|
|
|
|
BOOL FHaveSchedule( void );
|
|
BOOL FScheduleValid ( void );
|
|
void ClearSchedule( void );
|
|
BOOL FScheduleDone ( void );
|
|
void ChangeSchedule ( Schedule_t *pNewSchedule );
|
|
void NextScheduledTask ( void );
|
|
Schedule_t *ScheduleInList( const char *pName, Schedule_t **pList, int listCount );
|
|
|
|
virtual Schedule_t *ScheduleFromName( const char *pName );
|
|
static Schedule_t *m_scheduleList[];
|
|
|
|
void MaintainSchedule ( void );
|
|
virtual void StartTask ( Task_t *pTask );
|
|
virtual void RunTask ( Task_t *pTask );
|
|
virtual Schedule_t *GetScheduleOfType( int Type );
|
|
virtual Schedule_t *GetSchedule( void );
|
|
virtual void ScheduleChange( void ) {}
|
|
// virtual int CanPlaySequence( void ) { return ((m_pCine == NULL) && (m_MonsterState == MONSTERSTATE_NONE || m_MonsterState == MONSTERSTATE_IDLE || m_IdealMonsterState == MONSTERSTATE_IDLE)); }
|
|
virtual int CanPlaySequence( int interruptFlags );
|
|
// virtual int CanPlaySequence( BOOL fDisregardState, int interruptLevel );
|
|
virtual int CanPlaySentence( BOOL fDisregardState ) { return IsAlive(); }
|
|
virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation );
|
|
virtual void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener );
|
|
|
|
virtual void SentenceStop( void );
|
|
|
|
Task_t *GetTask ( void );
|
|
virtual MONSTERSTATE GetIdealState ( void );
|
|
virtual void SetActivity ( Activity NewActivity );
|
|
void SetIdealActivity( Activity NewActivity );
|
|
void SetSequenceByName ( char *szSequence );
|
|
void SetState ( MONSTERSTATE State );
|
|
virtual void ReportAIState( void );
|
|
|
|
void CheckAttacks ( CBaseEntity *pTarget, float flDist );
|
|
virtual int CheckEnemy ( CBaseEntity *pEnemy );
|
|
void PushEnemy( CBaseEntity *pEnemy, Vector &vecLastKnownPos );
|
|
BOOL PopEnemy( void );
|
|
|
|
BOOL FGetNodeRoute ( Vector vecDest );
|
|
|
|
inline void TaskComplete( void ) { if ( !HasConditions(bits_COND_TASK_FAILED) ) m_iTaskStatus = TASKSTATUS_COMPLETE; }
|
|
void MovementComplete( void );
|
|
inline void TaskFail( void ) { SetConditions(bits_COND_TASK_FAILED); }
|
|
inline void TaskBegin( void ) { m_iTaskStatus = TASKSTATUS_RUNNING; }
|
|
int TaskIsRunning( void );
|
|
inline int TaskIsComplete( void ) { return (m_iTaskStatus == TASKSTATUS_COMPLETE); }
|
|
inline int MovementIsComplete( void ) { return (m_movementGoal == MOVEGOAL_NONE); }
|
|
|
|
int IScheduleFlags ( void );
|
|
BOOL FRefreshRoute( void );
|
|
BOOL FRouteClear ( void );
|
|
void RouteSimplify( CBaseEntity *pTargetEnt );
|
|
void AdvanceRoute ( float distance );
|
|
virtual BOOL FTriangulate ( const Vector &vecStart , const Vector &vecEnd, float flDist, CBaseEntity *pTargetEnt, Vector *pApex );
|
|
virtual float MaxYawSpeed ( void ); // allows different yaw_speeds for each activity
|
|
BOOL BuildRoute ( const Vector &vecGoal, int iMoveFlag, CBaseEntity *pTarget );
|
|
virtual BOOL BuildNearestRoute ( Vector vecThreat, Vector vecViewOffset, float flMinDist, float flMaxDist );
|
|
int RouteClassify( int iMoveFlag );
|
|
void InsertWaypoint ( Vector vecLocation, int afMoveFlags );
|
|
|
|
BOOL FindLateralCover ( const Vector &vecThreat, const Vector &vecViewOffset );
|
|
virtual BOOL FindCover ( Vector vecThreat, Vector vecViewOffset, float flMinDist, float flMaxDist );
|
|
virtual BOOL FValidateCover ( const Vector &vecCoverLocation ) { return TRUE; };
|
|
virtual float CoverRadius( void ) { return 784; } // Default cover radius
|
|
|
|
virtual BOOL FCanCheckAttacks ( void );
|
|
virtual void CheckAmmo( void ) { return; };
|
|
virtual int IgnoreConditions ( void );
|
|
|
|
inline void SetConditions( int iConditions ) { m_afConditions |= iConditions; }
|
|
inline void ClearConditions( int iConditions ) { m_afConditions &= ~iConditions; }
|
|
inline BOOL HasConditions( int iConditions ) { if ( m_afConditions & iConditions ) return TRUE; return FALSE; }
|
|
inline BOOL HasAllConditions( int iConditions ) { if ( (m_afConditions & iConditions) == iConditions ) return TRUE; return FALSE; }
|
|
|
|
virtual BOOL FValidateHintType( short sHint );
|
|
int FindHintNode ( void );
|
|
virtual BOOL FCanActiveIdle ( void );
|
|
void SetTurnActivity ( void );
|
|
float FLSoundVolume ( CSound *pSound );
|
|
|
|
BOOL MoveToNode( Activity movementAct, float waitTime, const Vector &goal );
|
|
BOOL MoveToTarget( Activity movementAct, float waitTime );
|
|
BOOL MoveToLocation( Activity movementAct, float waitTime, const Vector &goal );
|
|
BOOL MoveToEnemy( Activity movementAct, float waitTime );
|
|
|
|
// Returns the time when the door will be open
|
|
float OpenDoorAndWait( entvars_t *pevDoor );
|
|
|
|
virtual int ISoundMask( void );
|
|
virtual CSound* PBestSound ( void );
|
|
virtual CSound* PBestScent ( void );
|
|
virtual float HearingSensitivity( void ) { return 1.0; };
|
|
|
|
BOOL FBecomeProne ( void );
|
|
virtual void BarnacleVictimBitten( entvars_t *pevBarnacle );
|
|
virtual void BarnacleVictimReleased( void );
|
|
|
|
virtual void SetEyePosition ( void );
|
|
|
|
BOOL FShouldEat( void );// see if a monster is 'hungry'
|
|
void Eat ( float flFullDuration );// make the monster 'full' for a while.
|
|
|
|
CBaseEntity *CheckTraceHullAttack( float flDist, int iDamage, int iDmgType );
|
|
BOOL FacingIdeal( void );
|
|
|
|
BOOL FCheckAITrigger( void );// checks and, if necessary, fires the monster's trigger target.
|
|
BOOL NoFriendlyFire( void );
|
|
|
|
BOOL BBoxFlat( void );
|
|
|
|
// PrescheduleThink
|
|
virtual void PrescheduleThink( void ) { return; };
|
|
|
|
virtual BOOL GetEnemy ( void ); // buz: make virtual
|
|
void MakeDamageBloodDecal ( int cCount, float flNoise, TraceResult *ptr, const Vector &vecDir );
|
|
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
|
|
|
|
// combat functions
|
|
float UpdateTarget ( entvars_t *pevTarget );
|
|
virtual Activity GetDeathActivity ( void );
|
|
Activity GetSmallFlinchActivity( void );
|
|
virtual void Killed( entvars_t *pevAttacker, int iGib );
|
|
virtual void GibMonster( void );
|
|
BOOL ShouldGibMonster( int iGib );
|
|
void CallGibMonster( void );
|
|
virtual const char* DamageDecal( int bitsDamageType );
|
|
virtual int HasCustomGibs( void ) { return FALSE; } //LRC
|
|
virtual BOOL HasHumanGibs( void );
|
|
virtual BOOL HasAlienGibs( void );
|
|
virtual void FadeMonster( void ); // Called instead of GibMonster() when gibs are disabled
|
|
|
|
virtual Vector ShootAtEnemy( const Vector &shootOrigin );
|
|
// virtual Vector BodyTarget( const Vector &posSrc ) { return Center( ) * 0.75 + EyePosition() * 0.25; }; // position to shoot at
|
|
virtual Vector BodyTarget( const Vector &posSrc ) { return Center( ) * 0.5 + EyePosition() * 0.5; }; // buz: fix to allow grunts shoot over obstacles
|
|
|
|
virtual Vector GetGunPosition( void );
|
|
|
|
virtual int TakeHealth( float flHealth, int bitsDamageType );
|
|
virtual int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType);
|
|
int DeadTakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
|
|
|
|
void RadiusDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType );
|
|
void RadiusDamage(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType );
|
|
virtual int IsMoving( void ) { return m_movementGoal != MOVEGOAL_NONE; }
|
|
|
|
void RouteClear( void );
|
|
void RouteNew( void );
|
|
|
|
virtual void DeathSound ( void ) { return; };
|
|
virtual void AlertSound ( void ) { return; };
|
|
virtual void IdleSound ( void ) { return; };
|
|
virtual void PainSound ( void ) { return; };
|
|
virtual void BlockedByPlayer ( CBasePlayer *pBlocker ) { return; }; // buz
|
|
virtual void StepSound( void );
|
|
|
|
virtual void StopFollowing( BOOL clearSchedule, int speakSentence = TRUE ) {} // buz
|
|
|
|
inline void Remember( int iMemory ) { m_afMemory |= iMemory; }
|
|
inline void Forget( int iMemory ) { m_afMemory &= ~iMemory; }
|
|
inline BOOL HasMemory( int iMemory ) { if ( m_afMemory & iMemory ) return TRUE; return FALSE; }
|
|
inline BOOL HasAllMemories( int iMemory ) { if ( (m_afMemory & iMemory) == iMemory ) return TRUE; return FALSE; }
|
|
|
|
BOOL ExitScriptedSequence( );
|
|
BOOL CineCleanup( );
|
|
|
|
void StartPatrol( CBaseEntity *path );
|
|
|
|
CBaseEntity* DropItem ( char *pszItemName, const Vector &vecPos, const Vector &vecAng );// drop an item.
|
|
|
|
//LRC
|
|
float CalcRatio( CBaseEntity *pLocus )
|
|
{
|
|
/*ALERT(at_console, "monster CR: %f/%f = %f\n", pev->health, pev->max_health, pev->health / pev->max_health);*/
|
|
return pev->health / pev->max_health;
|
|
}
|
|
|
|
void AddFacingTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp );
|
|
void AddFacingTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp );
|
|
void AddFacingTarget( CBaseEntity *pTarget, const Vector &vecPosition, float flImportance, float flDuration, float flRamp );
|
|
float GetFacingDirection( Vector &vecDir );
|
|
|
|
CMonsterTarget m_facingQueue;
|
|
|
|
Vector m_vecFacingDir;
|
|
Vector m_vecDirection;
|
|
|
|
// buz: rush vars
|
|
string_t m_hRushEntity;
|
|
int m_iRushMovetype;
|
|
float m_flRushDistance;
|
|
float m_flRushNextTime;
|
|
};
|
|
|
|
|
|
|
|
#endif // BASEMONSTER_H
|