This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

304 lines
9.7 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef NPC_COMBINE_H
#define NPC_COMBINE_H
#ifdef _WIN32
#pragma once
#endif
#include "ai_baseactor.h"
#include "ai_basehumanoid.h"
#include "ai_basenpc.h"
#include "ai_behavior.h"
#include "ai_behavior_actbusy.h"
#include "ai_behavior_assault.h"
#include "ai_behavior_follow.h"
#include "ai_behavior_functank.h"
#include "ai_behavior_rappel.h"
#include "ai_behavior_standoff.h"
#include "ai_sentence.h"
// Used when only what combine to react to what the spotlight sees
#define SF_COMBINE_NO_LOOK (1 << 16)
#define SF_COMBINE_NO_GRENADEDROP (1 << 17)
#define SF_COMBINE_NO_AR2DROP (1 << 18)
//=========================================================
// >> CNPC_Combine
//=========================================================
class CNPC_Combine : public CAI_BaseActor {
DECLARE_DATADESC();
DEFINE_CUSTOM_AI;
DECLARE_CLASS(CNPC_Combine, CAI_BaseActor);
public:
CNPC_Combine();
// Create components
virtual bool CreateComponents();
bool CanThrowGrenade(const Vector &vecTarget);
bool CheckCanThrowGrenade(const Vector &vecTarget);
virtual bool CanGrenadeEnemy(bool bUseFreeKnowledge = true);
virtual bool CanAltFireEnemy(bool bUseFreeKnowledge);
int GetGrenadeConditions(float flDot, float flDist);
int RangeAttack2Conditions(float flDot,
float flDist); // For innate grenade attack
int MeleeAttack1Conditions(float flDot, float flDist); // For kick/punch
bool FVisible(CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS,
CBaseEntity **ppBlocker = NULL);
virtual bool IsCurTaskContinuousMove();
virtual float GetJumpGravity() const { return 1.8f; }
virtual Vector GetCrouchEyeOffset(void);
void Event_Killed(const CTakeDamageInfo &info);
void SetActivity(Activity NewActivity);
NPC_STATE SelectIdealState(void);
// Input handlers.
void InputLookOn(inputdata_t &inputdata);
void InputLookOff(inputdata_t &inputdata);
void InputStartPatrolling(inputdata_t &inputdata);
void InputStopPatrolling(inputdata_t &inputdata);
void InputAssault(inputdata_t &inputdata);
void InputHitByBugbait(inputdata_t &inputdata);
void InputThrowGrenadeAtTarget(inputdata_t &inputdata);
bool UpdateEnemyMemory(CBaseEntity *pEnemy, const Vector &position,
CBaseEntity *pInformer = NULL);
void Spawn(void);
void Precache(void);
void Activate();
Class_T Classify(void);
bool IsElite() { return m_fIsElite; }
void DelayAltFireAttack(float flDelay);
void DelaySquadAltFireAttack(float flDelay);
float MaxYawSpeed(void);
bool ShouldMoveAndShoot();
bool OverrideMoveFacing(const AILocalMoveGoal_t &move, float flInterval);
;
void HandleAnimEvent(animevent_t *pEvent);
Vector Weapon_ShootPosition();
Vector EyeOffset(Activity nActivity);
Vector EyePosition(void);
Vector BodyTarget(const Vector &posSrc, bool bNoisy = true);
Vector GetAltFireTarget();
void StartTask(const Task_t *pTask);
void RunTask(const Task_t *pTask);
void PostNPCInit();
void GatherConditions();
virtual void PrescheduleThink();
Activity NPC_TranslateActivity(Activity eNewActivity);
void BuildScheduleTestBits(void);
virtual int SelectSchedule(void);
virtual int SelectFailSchedule(int failedSchedule, int failedTask,
AI_TaskFailureCode_t taskFailCode);
int SelectScheduleAttack();
bool CreateBehaviors();
bool OnBeginMoveAndShoot();
void OnEndMoveAndShoot();
// Combat
WeaponProficiency_t CalcWeaponProficiency(CBaseCombatWeapon *pWeapon);
bool HasShotgun();
bool ActiveWeaponIsFullyLoaded();
bool HandleInteraction(int interactionType, void *data,
CBaseCombatCharacter *sourceEnt);
const char *GetSquadSlotDebugName(int iSquadSlot);
bool IsUsingTacticalVariant(int variant);
bool IsUsingPathfindingVariant(int variant) {
return m_iPathfindingVariant == variant;
}
bool IsRunningApproachEnemySchedule();
// -------------
// Sounds
// -------------
void DeathSound(void);
void PainSound(void);
void IdleSound(void);
void AlertSound(void);
void LostEnemySound(void);
void FoundEnemySound(void);
void AnnounceAssault(void);
void AnnounceEnemyType(CBaseEntity *pEnemy);
void AnnounceEnemyKill(CBaseEntity *pEnemy);
void NotifyDeadFriend(CBaseEntity *pFriend);
virtual float HearingSensitivity(void) { return 1.0; };
int GetSoundInterests(void);
virtual bool QueryHearSound(CSound *pSound);
// Speaking
void SpeakSentence(int sentType);
virtual int TranslateSchedule(int scheduleType);
void OnStartSchedule(int scheduleType);
virtual bool ShouldPickADeathPose(void);
protected:
void SetKickDamage(int nDamage) { m_nKickDamage = nDamage; }
CAI_Sentence<CNPC_Combine> *GetSentences() { return &m_Sentences; }
private:
//=========================================================
// Combine S schedules
//=========================================================
enum {
SCHED_COMBINE_SUPPRESS = BaseClass::NEXT_SCHEDULE,
SCHED_COMBINE_COMBAT_FAIL,
SCHED_COMBINE_VICTORY_DANCE,
SCHED_COMBINE_COMBAT_FACE,
SCHED_COMBINE_HIDE_AND_RELOAD,
SCHED_COMBINE_SIGNAL_SUPPRESS,
SCHED_COMBINE_ENTER_OVERWATCH,
SCHED_COMBINE_OVERWATCH,
SCHED_COMBINE_ASSAULT,
SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE,
SCHED_COMBINE_PRESS_ATTACK,
SCHED_COMBINE_WAIT_IN_COVER,
SCHED_COMBINE_RANGE_ATTACK1,
SCHED_COMBINE_RANGE_ATTACK2,
SCHED_COMBINE_TAKE_COVER1,
SCHED_COMBINE_TAKE_COVER_FROM_BEST_SOUND,
SCHED_COMBINE_RUN_AWAY_FROM_BEST_SOUND,
SCHED_COMBINE_GRENADE_COVER1,
SCHED_COMBINE_TOSS_GRENADE_COVER1,
SCHED_COMBINE_TAKECOVER_FAILED,
SCHED_COMBINE_GRENADE_AND_RELOAD,
SCHED_COMBINE_PATROL,
SCHED_COMBINE_BUGBAIT_DISTRACTION,
SCHED_COMBINE_CHARGE_TURRET,
SCHED_COMBINE_DROP_GRENADE,
SCHED_COMBINE_CHARGE_PLAYER,
SCHED_COMBINE_PATROL_ENEMY,
SCHED_COMBINE_BURNING_STAND,
SCHED_COMBINE_AR2_ALTFIRE,
SCHED_COMBINE_FORCED_GRENADE_THROW,
SCHED_COMBINE_MOVE_TO_FORCED_GREN_LOS,
SCHED_COMBINE_FACE_IDEAL_YAW,
SCHED_COMBINE_MOVE_TO_MELEE,
NEXT_SCHEDULE,
};
//=========================================================
// Combine Tasks
//=========================================================
enum {
TASK_COMBINE_FACE_TOSS_DIR = BaseClass::NEXT_TASK,
TASK_COMBINE_IGNORE_ATTACKS,
TASK_COMBINE_SIGNAL_BEST_SOUND,
TASK_COMBINE_DEFER_SQUAD_GRENADES,
TASK_COMBINE_CHASE_ENEMY_CONTINUOUSLY,
TASK_COMBINE_DIE_INSTANTLY,
TASK_COMBINE_PLAY_SEQUENCE_FACE_ALTFIRE_TARGET,
TASK_COMBINE_GET_PATH_TO_FORCED_GREN_LOS,
TASK_COMBINE_SET_STANDING,
NEXT_TASK
};
//=========================================================
// Combine Conditions
//=========================================================
enum Combine_Conds {
COND_COMBINE_NO_FIRE = BaseClass::NEXT_CONDITION,
COND_COMBINE_DEAD_FRIEND,
COND_COMBINE_SHOULD_PATROL,
COND_COMBINE_HIT_BY_BUGBAIT,
COND_COMBINE_DROP_GRENADE,
COND_COMBINE_ON_FIRE,
COND_COMBINE_ATTACK_SLOT_AVAILABLE,
NEXT_CONDITION
};
private:
// Select the combat schedule
int SelectCombatSchedule();
// Should we charge the player?
bool ShouldChargePlayer();
// Chase the enemy, updating the target position as the player moves
void StartTaskChaseEnemyContinuously(const Task_t *pTask);
void RunTaskChaseEnemyContinuously(const Task_t *pTask);
class CCombineStandoffBehavior
: public CAI_ComponentWithOuter<CNPC_Combine, CAI_StandoffBehavior> {
typedef CAI_ComponentWithOuter<CNPC_Combine, CAI_StandoffBehavior>
BaseClass;
virtual int SelectScheduleAttack() {
int result = GetOuter()->SelectScheduleAttack();
if (result == SCHED_NONE)
result = BaseClass::SelectScheduleAttack();
return result;
}
};
// Rappel
virtual bool IsWaitingToRappel(void) {
return m_RappelBehavior.IsWaitingToRappel();
}
void BeginRappel() { m_RappelBehavior.BeginRappel(); }
private:
int m_nKickDamage;
Vector m_vecTossVelocity;
EHANDLE m_hForcedGrenadeTarget;
bool m_bShouldPatrol;
bool m_bFirstEncounter; // only put on the handsign show in the squad's
// first encounter.
// Time Variables
float m_flNextPainSoundTime;
float m_flNextAlertSoundTime;
float m_flNextGrenadeCheck;
float m_flNextLostSoundTime;
float m_flAlertPatrolTime; // When to stop doing alert patrol
float m_flNextAltFireTime; // Elites only. Next time to begin considering
// alt-fire attack.
int m_nShots;
float m_flShotDelay;
float m_flStopMoveShootTime;
CAI_Sentence<CNPC_Combine> m_Sentences;
int m_iNumGrenades;
CAI_AssaultBehavior m_AssaultBehavior;
CCombineStandoffBehavior m_StandoffBehavior;
CAI_FollowBehavior m_FollowBehavior;
CAI_FuncTankBehavior m_FuncTankBehavior;
CAI_RappelBehavior m_RappelBehavior;
CAI_ActBusyBehavior m_ActBusyBehavior;
public:
int m_iLastAnimEventHandled;
bool m_fIsElite;
Vector m_vecAltFireTarget;
int m_iTacticalVariant;
int m_iPathfindingVariant;
};
#endif // NPC_COMBINE_H