mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-05-08 11:38:01 +03:00
480 lines
16 KiB
C++
480 lines
16 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2015 the OpenMoHAA team
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
// simpleactor.h: Base class for character AI.
|
|
|
|
#pragma once
|
|
|
|
#include "weapon.h"
|
|
#include "sentient.h"
|
|
#include "container.h"
|
|
#include "stack.h"
|
|
#include "navigate.h"
|
|
#include "scriptmaster.h"
|
|
#include "characterstate.h"
|
|
#include "actorpath.h"
|
|
|
|
enum eEmotionMode {
|
|
EMOTION_NONE,
|
|
EMOTION_NEUTRAL,
|
|
EMOTION_WORRY,
|
|
EMOTION_PANIC,
|
|
EMOTION_FEAR,
|
|
EMOTION_DISGUST,
|
|
EMOTION_ANGER,
|
|
EMOTION_AIMING,
|
|
EMOTION_DETERMINED,
|
|
EMOTION_DEAD,
|
|
EMOTION_CURIOUS
|
|
};
|
|
|
|
enum eAnimMode {
|
|
ANIM_MODE_NONE,
|
|
ANIM_MODE_NORMAL,
|
|
ANIM_MODE_PATH,
|
|
ANIM_MODE_PATH_GOAL,
|
|
ANIM_MODE_DEST,
|
|
ANIM_MODE_SCRIPTED,
|
|
ANIM_MODE_NOCLIP,
|
|
ANIM_MODE_FALLING_PATH,
|
|
ANIM_MODE_FROZEN,
|
|
ANIM_MODE_ATTACHED,
|
|
};
|
|
|
|
enum eAnimWeightType {
|
|
ANIM_WEIGHT_NONE,
|
|
ANIM_WEIGHT_MOTION,
|
|
ANIM_WEIGHT_ACTION,
|
|
ANIM_WEIGHT_CROSSBLEND_1,
|
|
ANIM_WEIGHT_CROSSBLEND_2,
|
|
ANIM_WEIGHT_CROSSBLEND_DIALOG,
|
|
ANIM_WEIGHT_SAY,
|
|
ANIM_WEIGHT_AIM,
|
|
ANIM_WEIGHT_LASTFRAME,
|
|
};
|
|
|
|
class SimpleActor;
|
|
|
|
typedef SafePtr<SimpleActor> SimpleActorPtr;
|
|
|
|
class SimpleActor : public Sentient
|
|
{
|
|
public:
|
|
int m_eAnimMode;
|
|
ScriptThreadLabel m_Anim;
|
|
SafePtr<ScriptThread> m_pAnimThread;
|
|
int m_eNextAnimMode;
|
|
const_str m_csNextAnimString;
|
|
ScriptThreadLabel m_NextAnimLabel;
|
|
bool m_bNextForceStart;
|
|
float m_fCrouchWeight;
|
|
bool m_YawAchieved;
|
|
float m_DesiredYaw;
|
|
bool m_bHasDesiredLookDest;
|
|
bool m_bHasDesiredLookAngles;
|
|
Vector m_vDesiredLookDest;
|
|
Vector m_DesiredLookAngles;
|
|
Vector m_DesiredGunDir;
|
|
ActorPath m_Path;
|
|
float m_Dest[3];
|
|
float m_NoClipDest[3];
|
|
float path_failed_time;
|
|
float m_fPathGoalTime;
|
|
bool m_bStartPathGoalEndAnim;
|
|
const_str m_csPathGoalEndAnimScript;
|
|
qboolean m_walking;
|
|
qboolean m_groundPlane;
|
|
vec3_t m_groundPlaneNormal;
|
|
Vector watch_offset;
|
|
bool m_bThink;
|
|
int m_PainTime;
|
|
eEmotionMode m_eEmotionMode;
|
|
float m_fAimLimit_up;
|
|
float m_fAimLimit_down;
|
|
int m_ChangeMotionAnimIndex;
|
|
int m_ChangeActionAnimIndex;
|
|
int m_ChangeSayAnimIndex;
|
|
|
|
protected:
|
|
unsigned int m_weightType[MAX_FRAMEINFOS];
|
|
float m_weightBase[MAX_FRAMEINFOS];
|
|
float m_weightCrossBlend[MAX_FRAMEINFOS];
|
|
bool m_AnimMotionHigh;
|
|
bool m_AnimActionHigh;
|
|
bool m_AnimDialogHigh;
|
|
|
|
public:
|
|
int hit_obstacle_time;
|
|
float obstacle_vel[2];
|
|
const_str m_csAnimName;
|
|
const_str m_csSayAnim;
|
|
const_str m_csUpperAnim;
|
|
const_str m_csCurrentPosition;
|
|
int m_bPathErrorTime;
|
|
class PathNode *m_NearestNode;
|
|
Vector m_vNearestNodePos;
|
|
short m_bUpdateAnimDoneFlags;
|
|
float m_maxspeed;
|
|
const_str m_csMood;
|
|
const_str m_csIdleMood;
|
|
int m_iMotionSlot;
|
|
int m_iActionSlot;
|
|
int m_iSaySlot;
|
|
bool m_bLevelMotionAnim;
|
|
bool m_bLevelActionAnim;
|
|
byte m_bLevelSayAnim;
|
|
byte m_bNextLevelSayAnim;
|
|
bool m_bMotionAnimSet;
|
|
bool m_bActionAnimSet;
|
|
bool m_bSayAnimSet;
|
|
bool m_bAimAnimSet;
|
|
int m_iVoiceTime;
|
|
bool m_bDoAI;
|
|
ScriptThreadLabel m_PainHandler;
|
|
ScriptThreadLabel m_DeathHandler;
|
|
ScriptThreadLabel m_AttackHandler;
|
|
ScriptThreadLabel m_SniperHandler;
|
|
float m_fCrossblendTime;
|
|
|
|
public:
|
|
CLASS_PROTOTYPE(SimpleActor);
|
|
|
|
SimpleActor();
|
|
~SimpleActor();
|
|
|
|
void Archive(Archiver &arc) override;
|
|
virtual void SetMoveInfo(mmove_t *mm);
|
|
virtual void GetMoveInfo(mmove_t *mm);
|
|
bool CanSeeFrom(vec3_t pos, Entity *ent);
|
|
virtual bool CanTarget(void);
|
|
virtual bool IsImmortal(void);
|
|
bool DoesTheoreticPathExist(Vector vDestPos, float fMaxPath);
|
|
void
|
|
SetPath(Vector vDestPos, const char *description, int iMaxDirtyTime, float *vLeashHome, float fLeashDistSquared);
|
|
void SetPath(SimpleEntity *pDestNode, const char *description, int iMaxDirtyTime);
|
|
void SetPathWithinDistance(Vector vDestPos, char *description, float fMaxPath, int iMaxDirtyTime);
|
|
void FindPathAway(vec3_t vAwayFrom, vec2_t vDirPreferred, float fMinSafeDist);
|
|
void ClearPath(void);
|
|
bool PathComplete(void) const;
|
|
bool PathExists(void) const;
|
|
bool PathIsValid(void) const;
|
|
bool PathAvoidsSquadMates(void) const;
|
|
void ShortenPathToAvoidSquadMates(void);
|
|
PathInfo *CurrentPathNode(void) const;
|
|
PathInfo *LastPathNode(void) const;
|
|
float PathDist(void) const;
|
|
bool PathHasCompleteLookahead(void) const;
|
|
Vector PathGoal(void) const;
|
|
const float *PathDelta(void) const;
|
|
bool PathGoalSlowdownStarted(void) const;
|
|
void SetDest(vec3_t dest);
|
|
void StopTurning(void);
|
|
void SetDesiredYaw(float yaw);
|
|
void SetDesiredYawDir(const vec2_t vec);
|
|
void SetDesiredYawDest(const vec3_t vec);
|
|
void UpdateEmotion(void);
|
|
int GetEmotionAnim(void);
|
|
int GetMotionSlot(int slot);
|
|
int GetActionSlot(int slot);
|
|
int GetSaySlot(void);
|
|
void StartCrossBlendAnimSlot(int slot);
|
|
void StartMotionAnimSlot(int slot, int anim, float weight);
|
|
void StartAimMotionAnimSlot(int slot, int anim);
|
|
void StartActionAnimSlot(int anim);
|
|
void StartSayAnimSlot(int anim);
|
|
void StartAimAnimSlot(int slot, int anim);
|
|
void SetBlendedWeight(int slot);
|
|
void EventSetAnimLength(Event *ev);
|
|
void UpdateNormalAnimSlot(int slot);
|
|
void UpdateCrossBlendAnimSlot(int slot);
|
|
void UpdateCrossBlendDialogAnimSlot(int slot);
|
|
void UpdateSayAnimSlot(int slot);
|
|
void UpdateLastFrameSlot(int slot);
|
|
void UpdateAnimSlot(int slot);
|
|
void StopAllAnimating(void);
|
|
void ChangeMotionAnim(void);
|
|
void ChangeActionAnim(void);
|
|
void ChangeSayAnim(void);
|
|
void StopAnimating(int slot);
|
|
void AnimFinished(int slot) override;
|
|
void UpdateAim(void);
|
|
void UpdateAimMotion(void);
|
|
void EventAIOn(Event *ev);
|
|
void EventAIOff(Event *ev);
|
|
void EventGetWeaponGroup(Event *ev);
|
|
void EventGetWeaponType(Event *ev);
|
|
void EventGetPainHandler(Event *ev);
|
|
void EventSetPainHandler(Event *ev);
|
|
void EventGetDeathHandler(Event *ev);
|
|
void EventSetDeathHandler(Event *ev);
|
|
void EventGetAttackHandler(Event *ev);
|
|
void EventSetAttackHandler(Event *ev);
|
|
void EventGetSniperHandler(Event *ev);
|
|
void EventSetSniperHandler(Event *ev);
|
|
void EventSetCrossblendTime(Event *ev);
|
|
void EventGetCrossblendTime(Event *ev);
|
|
void EventSetEmotion(Event *ev);
|
|
void EventGetPosition(Event *ev);
|
|
void EventSetPosition(Event *ev);
|
|
void EventGetAnimMode(Event *ev);
|
|
void EventSetAnimMode(Event *ev);
|
|
void EventSetAnimFinal(Event *ev);
|
|
void EventNoAnimLerp(Event *ev); // Added in 2.0
|
|
const_str GetRunAnim(void);
|
|
const_str GetWalkAnim(void);
|
|
void DesiredAnimation(int eAnimMode, const_str csAnimString);
|
|
void StartAnimation(int eAnimMode, const_str csAnimString);
|
|
void DesiredAnimation(int eAnimMode, ScriptThreadLabel AnimLabel);
|
|
void StartAnimation(int eAnimMode, ScriptThreadLabel AnimLabel);
|
|
void ContinueAnimationAllowNoPath(void);
|
|
void ContinueAnimation(void);
|
|
void SetPathGoalEndAnim(const_str csEndAnim);
|
|
bool UpdateSelectedAnimation(void);
|
|
void Anim_Attack(void);
|
|
void Anim_Suppress(void); // Added in 2.0
|
|
void Anim_Sniper(void);
|
|
void Anim_Aim(void);
|
|
void Anim_Shoot(void);
|
|
void Anim_Idle(void);
|
|
void Anim_Crouch(void);
|
|
void Anim_Prone(void);
|
|
void Anim_Stand(void);
|
|
void Anim_Cower(void);
|
|
void Anim_Killed(void);
|
|
void Anim_StartPain(void);
|
|
void Anim_Pain(void);
|
|
void Anim_CrouchRunTo(int eAnimMode);
|
|
void Anim_CrouchWalkTo(int eAnimMode);
|
|
void Anim_StandRunTo(int eAnimMode);
|
|
void Anim_StandWalkTo(int eAnimMode);
|
|
void Anim_RunTo(int eAnimMode);
|
|
void Anim_WalkTo(int eAnimMode);
|
|
void Anim_RunAwayFiring(int eAnimMode);
|
|
void Anim_RunToShooting(int eAnimMode);
|
|
void Anim_RunToAlarm(int eAnimMode);
|
|
void Anim_RunToCasual(int eAnimMode);
|
|
void Anim_RunToCover(int eAnimMode);
|
|
void Anim_RunToDanger(int eAnimMode);
|
|
void Anim_RunToDive(int eAnimMode);
|
|
void Anim_RunToFlee(int eAnimMode);
|
|
void Anim_RunToInOpen(int eAnimMode);
|
|
void Anim_Emotion(eEmotionMode eEmotMode);
|
|
void Anim_Say(const_str csSayAnimScript, int iMinTimeSinceLastSay, bool bCanInterrupt);
|
|
void Anim_FullBody(const_str csFullBodyAnim, int eAnimMode);
|
|
virtual const char *DumpCallTrace(const char *pszFmt, ...) const;
|
|
};
|
|
|
|
inline void SimpleActor::StartAnimation(int eAnimMode, const_str csAnimString)
|
|
{
|
|
m_eNextAnimMode = eAnimMode;
|
|
m_csNextAnimString = csAnimString;
|
|
m_bNextForceStart = true;
|
|
}
|
|
|
|
inline void SimpleActor::DesiredAnimation(int eAnimMode, const_str csAnimString)
|
|
{
|
|
m_eNextAnimMode = eAnimMode;
|
|
m_csNextAnimString = csAnimString;
|
|
m_bNextForceStart = false;
|
|
}
|
|
|
|
inline void SimpleActor::StartAnimation(int eAnimMode, ScriptThreadLabel AnimLabel)
|
|
{
|
|
m_eNextAnimMode = eAnimMode;
|
|
m_csNextAnimString = STRING_NULL;
|
|
m_NextAnimLabel = AnimLabel;
|
|
m_bNextForceStart = true;
|
|
}
|
|
|
|
inline void SimpleActor::DesiredAnimation(int eAnimMode, ScriptThreadLabel AnimLabel)
|
|
{
|
|
m_eNextAnimMode = eAnimMode;
|
|
m_csNextAnimString = STRING_NULL;
|
|
m_NextAnimLabel = AnimLabel;
|
|
m_bNextForceStart = false;
|
|
}
|
|
|
|
inline void SimpleActor::ContinueAnimationAllowNoPath(void)
|
|
{
|
|
if (m_eNextAnimMode < ANIM_MODE_NONE) {
|
|
m_eNextAnimMode = m_eAnimMode;
|
|
m_csNextAnimString = STRING_NULL;
|
|
m_NextAnimLabel = m_Anim;
|
|
m_bNextForceStart = false;
|
|
}
|
|
}
|
|
|
|
inline void SimpleActor::ContinueAnimation(void)
|
|
{
|
|
ContinueAnimationAllowNoPath();
|
|
|
|
if ((m_eNextAnimMode == ANIM_MODE_PATH || m_eNextAnimMode == ANIM_MODE_PATH_GOAL) && !PathExists()) {
|
|
assert(!"ContinueAnimation() called on a pathed animation, but no path exists");
|
|
Anim_Stand();
|
|
}
|
|
}
|
|
|
|
inline void SimpleActor::SetPathGoalEndAnim(const_str csEndAnim)
|
|
{
|
|
m_csPathGoalEndAnimScript = csEndAnim;
|
|
}
|
|
|
|
inline void SimpleActor::Archive(Archiver& arc)
|
|
{
|
|
int i;
|
|
|
|
Sentient::Archive(arc);
|
|
|
|
arc.ArchiveInteger(&m_eAnimMode);
|
|
m_Anim.Archive(arc);
|
|
|
|
arc.ArchiveBool(&m_bHasDesiredLookDest);
|
|
arc.ArchiveBool(&m_bHasDesiredLookAngles);
|
|
arc.ArchiveVector(&m_vDesiredLookDest);
|
|
arc.ArchiveVec3(m_DesiredLookAngles);
|
|
arc.ArchiveVec3(m_DesiredGunDir);
|
|
|
|
m_Path.Archive(arc);
|
|
arc.ArchiveVec3(m_Dest);
|
|
arc.ArchiveVec3(m_NoClipDest);
|
|
|
|
arc.ArchiveFloat(&path_failed_time);
|
|
arc.ArchiveFloat(&m_fPathGoalTime);
|
|
arc.ArchiveBool(&m_bStartPathGoalEndAnim);
|
|
Director.ArchiveString(arc, m_csPathGoalEndAnimScript);
|
|
|
|
arc.ArchiveInteger(&m_eNextAnimMode);
|
|
Director.ArchiveString(arc, m_csNextAnimString);
|
|
m_NextAnimLabel.Archive(arc);
|
|
arc.ArchiveBool(&m_bNextForceStart);
|
|
|
|
arc.ArchiveBoolean(&m_walking);
|
|
arc.ArchiveBoolean(&m_groundPlane);
|
|
arc.ArchiveVec3(m_groundPlaneNormal);
|
|
|
|
arc.ArchiveVector(&watch_offset);
|
|
arc.ArchiveBool(&m_bThink);
|
|
arc.ArchiveInteger(&m_PainTime);
|
|
|
|
arc.ArchiveBool(&m_bAimAnimSet);
|
|
arc.ArchiveBool(&m_bActionAnimSet);
|
|
|
|
Director.ArchiveString(arc, m_csMood);
|
|
Director.ArchiveString(arc, m_csIdleMood);
|
|
|
|
ArchiveEnum(m_eEmotionMode, eEmotionMode);
|
|
|
|
arc.ArchiveFloat(&m_fAimLimit_up);
|
|
arc.ArchiveFloat(&m_fAimLimit_down);
|
|
|
|
for (i = 0; i < MAX_FRAMEINFOS; i++) {
|
|
arc.ArchiveUnsigned(&m_weightType[i]);
|
|
}
|
|
|
|
for (i = 0; i < MAX_FRAMEINFOS; i++) {
|
|
arc.ArchiveFloat(&m_weightBase[i]);
|
|
}
|
|
|
|
for (i = 0; i < MAX_FRAMEINFOS; i++) {
|
|
arc.ArchiveFloat(&m_weightCrossBlend[i]);
|
|
}
|
|
|
|
arc.ArchiveBool(&m_AnimMotionHigh);
|
|
arc.ArchiveBool(&m_AnimActionHigh);
|
|
arc.ArchiveBool(&m_AnimDialogHigh);
|
|
|
|
arc.ArchiveVec2(obstacle_vel);
|
|
|
|
Director.ArchiveString(arc, m_csCurrentPosition);
|
|
|
|
arc.ArchiveBool(&m_bMotionAnimSet);
|
|
arc.ArchiveBool(&m_bDoAI);
|
|
|
|
arc.ArchiveFloat(&m_fCrossblendTime);
|
|
|
|
arc.ArchiveSafePointer(&m_pAnimThread);
|
|
|
|
arc.ArchiveBool(&m_YawAchieved);
|
|
arc.ArchiveFloat(&m_DesiredYaw);
|
|
|
|
arc.ArchiveInteger(&m_iVoiceTime);
|
|
arc.ArchiveBool(&m_bSayAnimSet);
|
|
|
|
arc.ArchiveInteger(&hit_obstacle_time);
|
|
|
|
Director.ArchiveString(arc, m_csAnimName);
|
|
|
|
arc.ArchiveInteger(&m_bPathErrorTime);
|
|
arc.ArchiveInteger(&m_iMotionSlot);
|
|
arc.ArchiveInteger(&m_iActionSlot);
|
|
arc.ArchiveInteger(&m_iSaySlot);
|
|
|
|
arc.ArchiveBool(&m_bLevelMotionAnim);
|
|
arc.ArchiveBool(&m_bLevelActionAnim);
|
|
arc.ArchiveByte(&m_bLevelSayAnim);
|
|
arc.ArchiveByte(&m_bNextLevelSayAnim);
|
|
|
|
Director.ArchiveString(arc, m_csSayAnim);
|
|
Director.ArchiveString(arc, m_csUpperAnim);
|
|
|
|
m_PainHandler.Archive(arc);
|
|
m_DeathHandler.Archive(arc);
|
|
m_AttackHandler.Archive(arc);
|
|
m_SniperHandler.Archive(arc);
|
|
|
|
arc.ArchiveObjectPointer((Class **)&m_NearestNode);
|
|
arc.ArchiveVector(&m_vNearestNodePos);
|
|
|
|
arc.ArchiveFloat(&m_fCrouchWeight);
|
|
arc.ArchiveFloat(&m_maxspeed);
|
|
}
|
|
|
|
inline void SimpleActor::StopTurning(void)
|
|
{
|
|
m_YawAchieved = true;
|
|
}
|
|
|
|
inline void SimpleActor::SetDesiredYaw(float yaw)
|
|
{
|
|
m_YawAchieved = false;
|
|
m_DesiredYaw = yaw;
|
|
}
|
|
|
|
inline void SimpleActor::SetDesiredYawDir(const vec2_t vec)
|
|
{
|
|
SetDesiredYaw(vectoyaw(vec));
|
|
}
|
|
|
|
inline void SimpleActor::SetDesiredYawDest(const vec3_t vec)
|
|
{
|
|
vec2_t facedir;
|
|
VectorSub2D(vec, origin, facedir);
|
|
|
|
if (!facedir[0] || !facedir[1]) {
|
|
SetDesiredYawDir(facedir);
|
|
}
|
|
}
|
|
|
|
inline void SimpleActor::SetDest(vec3_t dest)
|
|
{
|
|
VectorCopy(dest, m_Dest);
|
|
}
|