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

337 lines
11 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Hooks and classes for the support of humanoid NPCs with
// groovy facial animation capabilities, aka, "Actors"
//
//=============================================================================//
#ifndef AI_BASEACTOR_H
#define AI_BASEACTOR_H
#include <limits.h>
#include "AI_Interest_Target.h"
#include "ai_basehumanoid.h"
#include "ai_speech.h"
#if defined(_WIN32)
#pragma once
#endif
//-----------------------------------------------------------------------------
// CAI_BaseActor
//
// Purpose: The base class for all head/body/eye expressive NPCS.
//
//-----------------------------------------------------------------------------
enum PoseParameter_t { POSE_END = INT_MAX };
enum FlexWeight_t { FLEX_END = INT_MAX };
struct AILookTargetArgs_t {
EHANDLE hTarget;
Vector vTarget;
float flDuration;
float flInfluence;
float flRamp;
bool bExcludePlayers;
CAI_InterestTarget *pQueue;
};
class CAI_BaseActor : public CAI_ExpresserHost<CAI_BaseHumanoid> {
DECLARE_CLASS(CAI_BaseActor, CAI_ExpresserHost<CAI_BaseHumanoid>);
// friend CPoseParameter;
// friend CFlexWeight;
public:
// FIXME: this method is lame, isn't there some sort of template thing that
// would get rid of the Outer pointer?
void Init(PoseParameter_t &index, const char *szName) {
index = (PoseParameter_t)LookupPoseParameter(szName);
};
void Set(PoseParameter_t index, float flValue) {
SetPoseParameter((int)index, flValue);
}
float Get(PoseParameter_t index) { return GetPoseParameter((int)index); }
float ClampWithBias(PoseParameter_t index, float value, float base);
// Note, you must add all names to this static function in order for Init to
// work
static bool IsServerSideFlexController(char const *szName);
void Init(FlexWeight_t &index, const char *szName) {
// Make this fatal!!!
if (!IsServerSideFlexController(szName)) {
Error(
"You forgot to add flex controller %s to list in "
"CAI_BaseActor::IsServerSideFlexController().",
szName);
}
index = (FlexWeight_t)FindFlexController(szName);
}
void Set(FlexWeight_t index, float flValue) {
SetFlexWeight((LocalFlexController_t)index, flValue);
}
float Get(FlexWeight_t index) {
return GetFlexWeight((LocalFlexController_t)index);
}
public:
CAI_BaseActor()
: m_fLatchedPositions(0),
m_latchedEyeOrigin(vec3_origin),
m_latchedEyeDirection(vec3_origin),
m_latchedHeadDirection(vec3_origin),
m_flBlinktime(0),
m_hLookTarget(NULL),
m_iszExpressionScene(NULL_STRING),
m_iszIdleExpression(NULL_STRING),
m_iszAlertExpression(NULL_STRING),
m_iszCombatExpression(NULL_STRING),
m_iszDeathExpression(NULL_STRING),
m_iszExpressionOverride(NULL_STRING) {
memset(m_flextarget, 0, 64 * sizeof(m_flextarget[0]));
}
~CAI_BaseActor() { delete m_pExpresser; }
virtual void StudioFrameAdvance();
virtual void Precache();
virtual void SetModel(const char *szModelName);
virtual bool StartSceneEvent(CSceneEventInfo *info, CChoreoScene *scene,
CChoreoEvent *event, CChoreoActor *actor,
CBaseEntity *pTarget);
virtual bool ProcessSceneEvent(CSceneEventInfo *info, CChoreoScene *scene,
CChoreoEvent *event);
virtual bool ClearSceneEvent(CSceneEventInfo *info, bool fastKill,
bool canceled);
virtual bool CheckSceneEventCompletion(CSceneEventInfo *info,
float currenttime,
CChoreoScene *scene,
CChoreoEvent *event);
Vector EyePosition();
virtual Vector HeadDirection2D(void);
virtual Vector HeadDirection3D(void);
virtual Vector EyeDirection2D(void);
virtual Vector EyeDirection3D(void);
CBaseEntity *GetLooktarget() { return m_hLookTarget.Get(); }
virtual void OnNewLookTarget(){};
// CBaseFlex
virtual void SetViewtarget(const Vector &viewtarget);
// CAI_BaseNPC
virtual float PickLookTarget(bool bExcludePlayers = false,
float minTime = 1.5, float maxTime = 2.5);
virtual float PickLookTarget(CAI_InterestTarget &queue,
bool bExcludePlayers = false,
float minTime = 1.5, float maxTime = 2.5);
virtual bool PickTacticalLookTarget(AILookTargetArgs_t *pArgs);
virtual bool PickRandomLookTarget(AILookTargetArgs_t *pArgs);
virtual void MakeRandomLookTarget(AILookTargetArgs_t *pArgs, float minTime,
float maxTime);
virtual bool HasActiveLookTargets(void);
virtual void OnSelectedLookTarget(AILookTargetArgs_t *pArgs) { return; }
virtual void ClearLookTarget(CBaseEntity *pTarget);
virtual void ExpireCurrentRandomLookTarget() {
m_flNextRandomLookTime = gpGlobals->curtime - 0.1f;
}
virtual void StartTaskRangeAttack1(const Task_t *pTask);
virtual void AddLookTarget(CBaseEntity *pTarget, float flImportance,
float flDuration, float flRamp = 0.0);
virtual void AddLookTarget(const Vector &vecPosition, float flImportance,
float flDuration, float flRamp = 0.0);
virtual void SetHeadDirection(const Vector &vTargetPos, float flInterval);
void UpdateBodyControl(void);
void UpdateHeadControl(const Vector &vHeadTarget, float flHeadInfluence);
virtual float GetHeadDebounce(void) {
return 0.3;
} // how much of previous head turn to use
virtual void MaintainLookTargets(float flInterval);
virtual bool ValidEyeTarget(const Vector &lookTargetPos);
virtual bool ValidHeadTarget(const Vector &lookTargetPos);
virtual float HeadTargetValidity(const Vector &lookTargetPos);
virtual bool ShouldBruteForceFailedNav() { return true; }
void AccumulateIdealYaw(float flYaw, float flIntensity);
bool SetAccumulatedYawAndUpdate(void);
float m_flAccumYawDelta;
float m_flAccumYawScale;
//---------------------------------
virtual void OnStateChange(NPC_STATE OldState, NPC_STATE NewState);
//---------------------------------
virtual void PlayExpressionForState(NPC_STATE state);
virtual const char *SelectRandomExpressionForState(NPC_STATE state);
float SetExpression(const char *);
void ClearExpression();
const char *GetExpression();
enum {
SCENE_AI_BLINK = 1,
SCENE_AI_HOLSTER,
SCENE_AI_UNHOLSTER,
SCENE_AI_AIM,
SCENE_AI_RANDOMLOOK,
SCENE_AI_RANDOMFACEFLEX,
SCENE_AI_RANDOMHEADFLEX,
SCENE_AI_IGNORECOLLISION,
SCENE_AI_DISABLEAI
};
DECLARE_DATADESC();
private:
enum {
HUMANOID_LATCHED_EYE = 0x0001,
HUMANOID_LATCHED_HEAD = 0x0002,
HUMANOID_LATCHED_ALL = 0x0003,
};
//---------------------------------
void UpdateLatchedValues(void);
// Input handlers.
void InputSetExpressionOverride(inputdata_t &inputdata);
//---------------------------------
int m_fLatchedPositions;
Vector m_latchedEyeOrigin;
Vector m_latchedEyeDirection; // direction eyes are looking
Vector m_latchedHeadDirection; // direction head is aiming
void ClearHeadAdjustment(void);
Vector m_goalHeadDirection;
float m_goalHeadInfluence;
//---------------------------------
float m_goalSpineYaw;
float m_goalBodyYaw;
Vector m_goalHeadCorrection;
//---------------------------------
float m_flBlinktime;
EHANDLE m_hLookTarget;
CAI_InterestTarget m_lookQueue;
CAI_InterestTarget m_syntheticLookQueue;
CAI_InterestTarget m_randomLookQueue;
float m_flNextRandomLookTime; // FIXME: move to scene
//---------------------------------
string_t m_iszExpressionScene;
EHANDLE m_hExpressionSceneEnt;
float m_flNextRandomExpressionTime;
string_t m_iszExpressionOverride;
protected:
string_t m_iszIdleExpression;
string_t m_iszAlertExpression;
string_t m_iszCombatExpression;
string_t m_iszDeathExpression;
private:
//---------------------------------
// PoseParameter_t m_ParameterBodyTransY; //
// "body_trans_Y"
// PoseParameter_t m_ParameterBodyTransX; //
// "body_trans_X"
// PoseParameter_t m_ParameterBodyLift; //
// "body_lift"
PoseParameter_t m_ParameterBodyYaw; // "body_yaw"
// PoseParameter_t m_ParameterBodyPitch; //
// "body_pitch" PoseParameter_t m_ParameterBodyRoll;
// // "body_roll"
PoseParameter_t m_ParameterSpineYaw; // "spine_yaw"
// PoseParameter_t m_ParameterSpinePitch; //
// "spine_pitch"
// PoseParameter_t m_ParameterSpineRoll; //
// "spine_roll"
PoseParameter_t m_ParameterNeckTrans; // "neck_trans"
PoseParameter_t m_ParameterHeadYaw; // "head_yaw"
PoseParameter_t m_ParameterHeadPitch; // "head_pitch"
PoseParameter_t m_ParameterHeadRoll; // "head_roll"
// FlexWeight_t m_FlexweightMoveRightLeft; //
// "move_rightleft"
// FlexWeight_t m_FlexweightMoveForwardBack;//
// "move_forwardback" FlexWeight_t
// m_FlexweightMoveUpDown; // "move_updown"
FlexWeight_t m_FlexweightBodyRightLeft; // "body_rightleft"
// FlexWeight_t m_FlexweightBodyUpDown; //
// "body_updown"
// FlexWeight_t m_FlexweightBodyTilt; //
// "body_tilt"
FlexWeight_t m_FlexweightChestRightLeft; // "chest_rightleft"
// FlexWeight_t m_FlexweightChestUpDown; //
// "chest_updown"
// FlexWeight_t m_FlexweightChestTilt; //
// "chest_tilt"
FlexWeight_t m_FlexweightHeadForwardBack; // "head_forwardback"
FlexWeight_t m_FlexweightHeadRightLeft; // "head_rightleft"
FlexWeight_t m_FlexweightHeadUpDown; // "head_updown"
FlexWeight_t m_FlexweightHeadTilt; // "head_tilt"
PoseParameter_t m_ParameterGestureHeight; // "gesture_height"
PoseParameter_t m_ParameterGestureWidth; // "gesture_width"
FlexWeight_t m_FlexweightGestureUpDown; // "gesture_updown"
FlexWeight_t m_FlexweightGestureRightLeft; // "gesture_rightleft"
private:
//---------------------------------
bool RandomFaceFlex(CSceneEventInfo *info, CChoreoScene *scene,
CChoreoEvent *event);
bool RandomHeadFlex(CSceneEventInfo *info, CChoreoScene *scene,
CChoreoEvent *event);
float m_flextarget[64];
public:
virtual bool UseSemaphore(void);
protected:
bool m_bDontUseSemaphore;
public:
//---------------------------------
//
// Speech support
//
virtual CAI_Expresser *GetExpresser();
protected:
bool CreateComponents();
virtual CAI_Expresser *CreateExpresser();
private:
//---------------------------------
CAI_Expresser *m_pExpresser;
};
//-----------------------------------------------------------------------------
#endif // AI_BASEACTOR_H