Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

419 lines
12 KiB

5 years ago
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef NPC_ANTLION_H
#define NPC_ANTLION_H
#ifdef _WIN32
#pragma once
#endif
#include "ai_blended_movement.h"
#include "soundent.h"
#include "ai_behavior_follow.h"
#include "ai_behavior_assault.h"
class CAntlionTemplateMaker;
#define ANTLION_FOLLOW_DISTANCE 350
#define ANTLION_FOLLOW_DISTANCE_SQR (ANTLION_FOLLOW_DISTANCE*ANTLION_FOLLOW_DISTANCE)
#define ANTLION_SKIN_COUNT 4
class CNPC_Antlion;
// Antlion follow behavior
class CAI_AntlionFollowBehavior : public CAI_FollowBehavior
{
typedef CAI_FollowBehavior BaseClass;
public:
CAI_AntlionFollowBehavior()
: BaseClass( AIF_ANTLION )
{
}
bool FarFromFollowTarget( void )
{
return ( GetFollowTarget() && (GetAbsOrigin() - GetFollowTarget()->GetAbsOrigin()).LengthSqr() > ANTLION_FOLLOW_DISTANCE_SQR );
}
bool ShouldFollow( void )
{
if ( GetFollowTarget() == NULL )
return false;
if ( GetEnemy() != NULL )
return false;
return true;
}
};
//
// Antlion class
//
enum AntlionMoveState_e
{
ANTLION_MOVE_FREE,
ANTLION_MOVE_FOLLOW,
ANTLION_MOVE_FIGHT_TO_GOAL,
};
#define SF_ANTLION_BURROW_ON_ELUDED ( 1 << 16 )
#define SF_ANTLION_USE_GROUNDCHECKS ( 1 << 17 )
#define SF_ANTLION_WORKER ( 1 << 18 ) // Use the "worker" model
typedef CAI_BlendingHost< CAI_BehaviorHost<CAI_BlendedNPC> > CAI_BaseAntlionBase;
class CNPC_Antlion : public CAI_BaseAntlionBase
{
public:
DECLARE_CLASS( CNPC_Antlion, CAI_BaseAntlionBase );
CNPC_Antlion( void );
virtual float InnateRange1MinRange( void ) { return 50*12; }
virtual float InnateRange1MaxRange( void ) { return 250*12; }
bool IsWorker( void ) const { return HasSpawnFlags( SF_ANTLION_WORKER ); } // NOTE: IsAntlionWorker function must agree!
float GetIdealAccel( void ) const;
float MaxYawSpeed( void );
bool FInViewCone( CBaseEntity *pEntity );
bool FInViewCone( const Vector &vecSpot );
void Activate( void );
void HandleAnimEvent( animevent_t *pEvent );
void StartTask( const Task_t *pTask );
void RunTask( const Task_t *pTask );
void IdleSound( void );
void PainSound( const CTakeDamageInfo &info );
void Precache( void );
void Spawn( void );
int OnTakeDamage_Alive( const CTakeDamageInfo &info );
void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
void BuildScheduleTestBits( void );
void GatherConditions( void );
void PrescheduleThink( void );
void ZapThink( void );
void BurrowUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
bool CreateVPhysics();
bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const;
bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter *sender = NULL );
bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false );
bool ShouldPlayIdleSound( void );
bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval );
bool IsValidEnemy(CBaseEntity *pEnemy);
bool QueryHearSound( CSound *pSound );
bool IsLightDamage( const CTakeDamageInfo &info );
bool CreateBehaviors( void );
bool ShouldHearBugbait( void ) { return ( m_bIgnoreBugbait == false ); }
int SelectSchedule( void );
void Touch( CBaseEntity *pOther );
virtual int RangeAttack1Conditions( float flDot, float flDist );
virtual int MeleeAttack1Conditions( float flDot, float flDist );
virtual int MeleeAttack2Conditions( float flDot, float flDist );
virtual int GetSoundInterests( void ) { return (BaseClass::GetSoundInterests())|(SOUND_DANGER|SOUND_PHYSICS_DANGER|SOUND_THUMPER|SOUND_BUGBAIT); }
virtual bool IsHeavyDamage( const CTakeDamageInfo &info );
Class_T Classify( void ) { return CLASS_ANTLION; }
void Event_Killed( const CTakeDamageInfo &info );
bool FValidateHintType ( CAI_Hint *pHint );
void GatherEnemyConditions( CBaseEntity *pEnemy );
bool IsAllied( void );
bool ShouldGib( const CTakeDamageInfo &info );
bool CorpseGib( const CTakeDamageInfo &info );
float GetMaxJumpSpeed() const { return 1024.0f; }
void SetFightTarget( CBaseEntity *pTarget );
void InputFightToPosition( inputdata_t &inputdata );
void InputStopFightToPosition( inputdata_t &inputdata );
void InputJumpAtTarget( inputdata_t &inputdata );
void SetFollowTarget( CBaseEntity *pTarget );
int TranslateSchedule( int scheduleType );
virtual Activity NPC_TranslateActivity( Activity baseAct );
bool ShouldResumeFollow( void );
bool ShouldAbandonFollow( void );
void SetMoveState( AntlionMoveState_e state );
int ChooseMoveSchedule( void );
DECLARE_DATADESC();
bool m_bStartBurrowed;
float m_flNextJumpPushTime;
void SetParentSpawnerName( const char *szName ) { m_strParentSpawner = MAKE_STRING( szName ); }
const char *GetParentSpawnerName( void ) { return STRING( m_strParentSpawner ); }
virtual void StopLoopingSounds( void );
bool AllowedToBePushed( void );
virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true );
virtual float GetAutoAimRadius() { return 36.0f; }
void ClearBurrowPoint( const Vector &origin );
void Flip( bool bZapped = false );
bool CanBecomeRagdoll();
virtual void NotifyDeadFriend( CBaseEntity *pFriend );
private:
inline CBaseEntity *EntityToWatch( void );
void UpdateHead( void );
bool FindChasePosition( const Vector &targetPos, Vector &result );
bool GetGroundPosition( const Vector &testPos, Vector &result );
bool GetPathToSoundFleePoint( int soundType );
inline bool IsFlipped( void );
void Burrow( void );
void Unburrow( void );
void InputUnburrow( inputdata_t &inputdata );
void InputBurrow( inputdata_t &inputdata );
void InputBurrowAway( inputdata_t &inputdata );
void InputDisableJump( inputdata_t &inputdata );
void InputEnableJump( inputdata_t &inputdata );
void InputIgnoreBugbait( inputdata_t &inputdata );
void InputHearBugbait( inputdata_t &inputdata );
bool FindBurrow( const Vector &origin, float distance, int type, bool excludeNear = true );
void CreateDust( bool placeDecal = true );
bool ValidBurrowPoint( const Vector &point );
bool CheckLanding( void );
bool Alone( void );
bool CheckAlertRadius( void );
bool ShouldJump( void );
void MeleeAttack( float distance, float damage, QAngle& viewPunch, Vector& shove );
void SetWings( bool state );
void StartJump( void );
void LockJumpNode( void );
bool IsUnusableNode(int iNodeID, CAI_Hint *pHint);
bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
void ManageFleeCapabilities( bool bEnable );
int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
bool IsFirmlyOnGround( void );
void CascadePush( const Vector &vecForce );
virtual bool CanRunAScriptedNPCInteraction( bool bForced = false );
virtual void Ignite ( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner );
virtual bool GetSpitVector( const Vector &vecStartPos, const Vector &vecTarget, Vector *vecOut );
virtual bool InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions );
virtual bool FCanCheckAttacks( void );
bool SeenEnemyWithinTime( float flTime );
void DelaySquadAttack( float flDuration );
#if HL2_EPISODIC
void DoPoisonBurst();
#endif
float m_flIdleDelay;
float m_flBurrowTime;
float m_flJumpTime;
float m_flAlertRadius;
float m_flPounceTime;
int m_iUnBurrowAttempts;
int m_iContext; //for FValidateHintType context
Vector m_vecSaveSpitVelocity; // Saved when we start to attack and used if we failed to get a clear shot once we release
CAI_AntlionFollowBehavior m_FollowBehavior;
CAI_AssaultBehavior m_AssaultBehavior;
AntlionMoveState_e m_MoveState;
COutputEvent m_OnReachFightGoal; //Reached our scripted destination to fight to
COutputEvent m_OnUnBurrowed; //Unburrowed
Vector m_vecSavedJump;
Vector m_vecLastJumpAttempt;
float m_flIgnoreSoundTime; // Sound time to ignore if earlier than
float m_flNextAcknowledgeTime; // Next time an antlion can make an acknowledgement noise
float m_flSuppressFollowTime; // Amount of time to suppress our follow time
float m_flObeyFollowTime; // A range of time the antlions must be obedient
Vector m_vecHeardSound;
bool m_bHasHeardSound;
bool m_bAgitatedSound; //Playing agitated sound?
bool m_bWingsOpen; //Are the wings open?
bool m_bIgnoreBugbait; //If the antlion should ignore bugbait sounds
string_t m_strParentSpawner; //Name of our spawner
EHANDLE m_hFollowTarget;
EHANDLE m_hFightGoalTarget;
float m_flEludeDistance; //Distance until the antlion will consider himself "eluded" if so flagged
bool m_bLeapAttack;
bool m_bDisableJump;
float m_flTimeDrown;
float m_flTimeDrownSplash;
bool m_bDontExplode; // Suppresses worker poison burst when drowning, failing to unburrow, etc.
bool m_bLoopingStarted;
bool m_bSuppressUnburrowEffects; // Don't kick up dust when spawning
#if HL2_EPISODIC
bool m_bHasDoneAirAttack; ///< only allowed to apply this damage once per glide
#endif
bool m_bForcedStuckJump;
int m_nBodyBone;
// Used to trigger a heavy damage interrupt if sustained damage is taken
int m_nSustainedDamage;
float m_flLastDamageTime;
float m_flZapDuration;
protected:
int m_poseHead_Yaw, m_poseHead_Pitch;
virtual void PopulatePoseParameters( void );
private:
HSOUNDSCRIPTHANDLE m_hFootstep;
DEFINE_CUSTOM_AI;
//==================================================
// AntlionConditions
//==================================================
enum
{
COND_ANTLION_FLIPPED = LAST_SHARED_CONDITION,
COND_ANTLION_ON_NPC,
COND_ANTLION_CAN_JUMP,
COND_ANTLION_FOLLOW_TARGET_TOO_FAR,
COND_ANTLION_RECEIVED_ORDERS,
COND_ANTLION_IN_WATER,
COND_ANTLION_CAN_JUMP_AT_TARGET,
COND_ANTLION_SQUADMATE_KILLED
};
//==================================================
// AntlionSchedules
//==================================================
enum
{
SCHED_ANTLION_CHASE_ENEMY_BURROW = LAST_SHARED_SCHEDULE,
SCHED_ANTLION_JUMP,
SCHED_ANTLION_RUN_TO_BURROW_IN,
SCHED_ANTLION_BURROW_IN,
SCHED_ANTLION_BURROW_WAIT,
SCHED_ANTLION_BURROW_OUT,
SCHED_ANTLION_WAIT_FOR_UNBORROW_TRIGGER,
SCHED_ANTLION_WAIT_FOR_CLEAR_UNBORROW,
SCHED_ANTLION_WAIT_UNBORROW,
SCHED_ANTLION_FLEE_THUMPER,
SCHED_ANTLION_CHASE_BUGBAIT,
SCHED_ANTLION_FLIP,
SCHED_ANTLION_DISMOUNT_NPC,
SCHED_ANTLION_RUN_TO_FIGHT_GOAL,
SCHED_ANTLION_RUN_TO_FOLLOW_GOAL,
SCHED_ANTLION_BUGBAIT_IDLE_STAND,
SCHED_ANTLION_BURROW_AWAY,
SCHED_ANTLION_FLEE_PHYSICS_DANGER,
SCHED_ANTLION_POUNCE,
SCHED_ANTLION_POUNCE_MOVING,
SCHED_ANTLION_DROWN,
SCHED_ANTLION_WORKER_RANGE_ATTACK1,
SCHED_ANTLION_WORKER_RUN_RANDOM,
SCHED_ANTLION_TAKE_COVER_FROM_ENEMY,
SCHED_ANTLION_ZAP_FLIP,
SCHED_ANTLION_WORKER_FLANK_RANDOM,
SCHED_ANTLION_TAKE_COVER_FROM_SAVEPOSITION
};
//==================================================
// AntlionTasks
//==================================================
enum
{
TASK_ANTLION_SET_CHARGE_GOAL = LAST_SHARED_TASK,
TASK_ANTLION_FIND_BURROW_IN_POINT,
TASK_ANTLION_FIND_BURROW_OUT_POINT,
TASK_ANTLION_BURROW,
TASK_ANTLION_UNBURROW,
TASK_ANTLION_VANISH,
TASK_ANTLION_BURROW_WAIT,
TASK_ANTLION_CHECK_FOR_UNBORROW,
TASK_ANTLION_JUMP,
TASK_ANTLION_WAIT_FOR_TRIGGER,
TASK_ANTLION_GET_THUMPER_ESCAPE_PATH,
TASK_ANTLION_GET_PATH_TO_BUGBAIT,
TASK_ANTLION_FACE_BUGBAIT,
TASK_ANTLION_DISMOUNT_NPC,
TASK_ANTLION_REACH_FIGHT_GOAL,
TASK_ANTLION_GET_PHYSICS_DANGER_ESCAPE_PATH,
TASK_ANTLION_FACE_JUMP,
TASK_ANTLION_DROWN,
TASK_ANTLION_GET_PATH_TO_RANDOM_NODE,
TASK_ANTLION_FIND_COVER_FROM_SAVEPOSITION,
};
};
//-----------------------------------------------------------------------------
// Purpose: Shield
//-----------------------------------------------------------------------------
class CAntlionRepellant : public CPointEntity
{
DECLARE_DATADESC();
public:
DECLARE_CLASS( CAntlionRepellant, CPointEntity );
~CAntlionRepellant();
public:
void Spawn( void );
void InputEnable( inputdata_t &inputdata );
void InputDisable( inputdata_t &inputdata );
float GetRadius( void );
void SetRadius( float flRadius ) { m_flRepelRadius = flRadius; }
static bool IsPositionRepellantFree( Vector vDesiredPos );
void OnRestore( void );
private:
float m_flRepelRadius;
bool m_bEnabled;
};
extern bool IsAntlion( CBaseEntity *pEntity );
extern bool IsAntlionWorker( CBaseEntity *pEntity );
#ifdef HL2_EPISODIC
extern float AntlionWorkerBurstRadius( void );
#endif // HL2_EPISODIC
#endif // NPC_ANTLION_H