-
Notifications
You must be signed in to change notification settings - Fork 0
/
basemonster.h
371 lines (286 loc) · 13.7 KB
/
basemonster.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/***
*
* Copyright (c) 1996-2001, 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.
*
****/
#pragma once
//
// 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
// Scripted sequence Info
SCRIPTSTATE m_scriptState; // internal cinematic state
CCineMonster* m_pCine;
float m_flLastYawTime;
bool m_AllowItemDropping = true;
bool Save(CSave& save) override;
bool Restore(CRestore& restore) override;
static TYPEDESCRIPTION m_SaveData[];
bool KeyValue(KeyValueData* pkvd) override;
// 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
int BloodColor() override { return m_bloodColor; }
CBaseMonster* MyMonsterPointer() override { return this; }
virtual void Look(int iDistance); // basic sight function for monsters
virtual void RunAI(); // core ai function!
void Listen();
bool IsAlive() override { return (pev->deadflag != DEAD_DEAD); }
virtual bool ShouldFadeOnDeath();
// Basic Monster AI functions
virtual float ChangeYaw(int speed);
float VecToYaw(Vector vecDir);
float FlYawDiff();
float DamageForce(float damage);
// stuff written for new state machine
virtual void MonsterThink();
void EXPORT CallMonsterThink() { this->MonsterThink(); }
virtual int IRelationship(CBaseEntity* pTarget);
virtual void MonsterInit();
virtual void MonsterInitDead(); // Call after animation/pose is set up
virtual void BecomeDead();
void EXPORT CorpseFallThink();
void EXPORT MonsterInitThink();
virtual void StartMonster();
virtual CBaseEntity* BestVisibleEnemy(); // 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
void HandleAnimEvent(MonsterEvent_t* pEvent) override;
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() { return ACT_IDLE; }
virtual void Stop() { m_IdealActivity = GetStoppedActivity(); }
// This will stop animation until you call ResetSequenceInfo() at some point in the future
inline void StopAnimation() { 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();
bool FScheduleValid();
void ClearSchedule();
bool FScheduleDone();
void ChangeSchedule(Schedule_t* pNewSchedule);
void NextScheduledTask();
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();
virtual void StartTask(Task_t* pTask);
virtual void RunTask(Task_t* pTask);
virtual Schedule_t* GetScheduleOfType(int Type);
virtual Schedule_t* GetSchedule();
virtual void ScheduleChange() {}
// virtual bool CanPlaySequence() { return ((m_pCine == NULL) && (m_MonsterState == MONSTERSTATE_NONE || m_MonsterState == MONSTERSTATE_IDLE || m_IdealMonsterState == MONSTERSTATE_IDLE)); }
virtual bool CanPlaySequence(bool fDisregardState, int interruptLevel);
virtual bool CanPlaySentence(bool fDisregardState) { return IsAlive() && (m_MonsterState == MONSTERSTATE_SCRIPT || pev->deadflag == DEAD_NO); }
void PlaySentence(const char* pszSentence, float duration, float volume, float attenuation);
protected:
virtual void PlaySentenceCore(const char* pszSentence, float duration, float volume, float attenuation);
public:
virtual void PlayScriptedSentence(const char* pszSentence, float duration, float volume, float attenuation, bool bConcurrent, CBaseEntity* pListener);
virtual void SentenceStop();
Task_t* GetTask();
virtual MONSTERSTATE GetIdealState();
virtual void SetActivity(Activity NewActivity);
void SetSequenceByName(const char* szSequence);
void SetState(MONSTERSTATE State);
virtual void ReportAIState();
void CheckAttacks(CBaseEntity* pTarget, float flDist);
virtual bool CheckEnemy(CBaseEntity* pEnemy);
void PushEnemy(CBaseEntity* pEnemy, Vector& vecLastKnownPos);
bool PopEnemy();
bool FGetNodeRoute(Vector vecDest);
inline void TaskComplete()
{
if (!HasConditions(bits_COND_TASK_FAILED))
m_iTaskStatus = TASKSTATUS_COMPLETE;
}
void MovementComplete();
inline void TaskFail() { SetConditions(bits_COND_TASK_FAILED); }
inline void TaskBegin() { m_iTaskStatus = TASKSTATUS_RUNNING; }
bool TaskIsRunning();
inline bool TaskIsComplete() { return (m_iTaskStatus == TASKSTATUS_COMPLETE); }
inline bool MovementIsComplete() { return (m_movementGoal == MOVEGOAL_NONE); }
int IScheduleFlags();
bool FRefreshRoute();
bool FRouteClear();
void RouteSimplify(CBaseEntity* pTargetEnt);
void AdvanceRoute(float distance);
virtual bool FTriangulate(const Vector& vecStart, const Vector& vecEnd, float flDist, CBaseEntity* pTargetEnt, Vector* pApex);
void MakeIdealYaw(Vector vecTarget);
virtual void SetYawSpeed() {} // 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() { return 784; } // Default cover radius
virtual bool FCanCheckAttacks();
virtual void CheckAmmo() {}
virtual int IgnoreConditions();
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();
virtual bool FCanActiveIdle();
void SetTurnActivity();
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();
virtual CSound* PBestSound();
virtual CSound* PBestScent();
virtual float HearingSensitivity() { return 1.0; }
bool FBecomeProne() override;
virtual void BarnacleVictimBitten(entvars_t* pevBarnacle);
virtual void BarnacleVictimReleased();
void SetEyePosition();
bool FShouldEat(); // 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();
bool FCheckAITrigger(); // checks and, if necessary, fires the monster's trigger target.
bool NoFriendlyFire();
bool BBoxFlat();
// PrescheduleThink
virtual void PrescheduleThink() {}
bool GetEnemy();
void MakeDamageBloodDecal(int cCount, float flNoise, TraceResult* ptr, const Vector& vecDir);
void TraceAttack(entvars_t* pevAttacker, float flDamage, Vector vecDir, TraceResult* ptr, int bitsDamageType) override;
// combat functions
float UpdateTarget(entvars_t* pevTarget);
virtual Activity GetDeathActivity();
Activity GetSmallFlinchActivity();
void Killed(entvars_t* pevAttacker, int iGib) override;
virtual void GibMonster();
bool ShouldGibMonster(int iGib);
void CallGibMonster();
virtual bool HasHumanGibs();
virtual bool HasAlienGibs();
virtual void FadeMonster(); // Called instead of GibMonster() when gibs are disabled
Vector ShootAtEnemy(const Vector& shootOrigin);
Vector BodyTarget(const Vector& posSrc) override { return Center() * 0.75 + EyePosition() * 0.25; } // position to shoot at
virtual Vector GetGunPosition();
bool TakeHealth(float flHealth, int bitsDamageType) override;
bool TakeDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType) override;
bool 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);
bool IsMoving() override { return m_movementGoal != MOVEGOAL_NONE; }
void RouteClear();
void RouteNew();
virtual void DeathSound() {}
virtual void AlertSound() {}
virtual void IdleSound() {}
virtual void PainSound() {}
virtual void StopFollowing(bool clearSchedule) {}
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();
/**
* @brief Drop an item.
* Will return @c nullptr if item dropping is disabled for this NPC.
*/
CBaseEntity* DropItem(const char* pszItemName, const Vector& vecPos, const Vector& vecAng);
};