diff --git a/README.md b/README.md
index 968428bb..136beceb 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Archive's bin directory contains 2 subdirectories, 'bugfixed' and 'pure'
## Current status
- Counter-Strike 1.6 - 100%
-- Counter-Strike: Condition Zero - 35%
+- Counter-Strike: Condition Zero - 63%
## Build instructions
diff --git a/regamedll/common/mathlib.h b/regamedll/common/mathlib.h
index 2c084aa7..3fb018d9 100644
--- a/regamedll/common/mathlib.h
+++ b/regamedll/common/mathlib.h
@@ -32,7 +32,7 @@
#pragma once
#endif
-#ifdef HOOK_GAMEDLL
+#ifdef PLAY_GAMEDLL
// probably gamedll compiled with flag /fpmath:fasted,
// so we need to use type double, otherwise will be the test failed
@@ -43,7 +43,7 @@ typedef double float_precision;
typedef float float_precision;
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
/* <42b7f> ../common/mathlib.h:3 */
typedef float vec_t;
diff --git a/regamedll/dlls/animation.h b/regamedll/dlls/animation.h
index 024fbcf3..4da17dfe 100644
--- a/regamedll/dlls/animation.h
+++ b/regamedll/dlls/animation.h
@@ -58,7 +58,7 @@ int GetBodygroup(void *pmodel, entvars_t *pev, int iGroup);
C_DLLEXPORT int Server_GetBlendingInterface(int version, struct sv_blending_interface_s **ppinterface, struct engine_studio_api_s *pstudio, float *rotationmatrix, float *bonetransform);
void AngleQuaternion(vec_t *angles, vec_t *quaternion);
void QuaternionSlerp(vec_t *p, vec_t *q, float t, vec_t *qt);
-NOBODY void QuaternionMatrix(vec_t *quaternion, float (*matrix)[4]);
+void QuaternionMatrix(vec_t *quaternion, float (*matrix)[4]);
mstudioanim_t *StudioGetAnim(model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc);
mstudioanim_t *LookupAnimation(model_t *model, mstudioseqdesc_t *pseqdesc, int index);
void StudioCalcBoneAdj(float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen);
diff --git a/regamedll/dlls/bot/cs_bot_init.cpp b/regamedll/dlls/bot/cs_bot_init.cpp
index f7055d9d..8750b1b2 100644
--- a/regamedll/dlls/bot/cs_bot_init.cpp
+++ b/regamedll/dlls/bot/cs_bot_init.cpp
@@ -3,8 +3,12 @@
/* <333bca> ../cstrike/dlls/bot/cs_bot_init.cpp:57 */
NOBODY void InstallBotControl(void)
{
-// ~CBotManager(CBotManager *const this,
-// int const __in_chrg); // 60
+ if (TheBots != NULL)
+ {
+ delete TheBots;
+ }
+
+ TheBots = new CCSBotManager;
}
/* <333cb3> ../cstrike/dlls/bot/cs_bot_init.cpp:68 */
diff --git a/regamedll/dlls/cbase.h b/regamedll/dlls/cbase.h
index d6df7516..f2bb168a 100644
--- a/regamedll/dlls/cbase.h
+++ b/regamedll/dlls/cbase.h
@@ -718,7 +718,7 @@ public:
int LookupSequence(const char *label);
void ResetSequenceInfo(void);
void DispatchAnimEvents(float flFutureInterval = 0.1f);
- float SetBoneController(int iController, float flValue);
+ float SetBoneController(int iController, float flValue = 0.0f);
void InitBoneControllers(void);
NOXREF float SetBlending(int iBlender, float flValue);
diff --git a/regamedll/dlls/client.cpp b/regamedll/dlls/client.cpp
index 49c85949..7a9bf49e 100644
--- a/regamedll/dlls/client.cpp
+++ b/regamedll/dlls/client.cpp
@@ -2271,7 +2271,7 @@ BOOL HandleMenu_ChooseTeam(CBasePlayer *player, int slot)
TheBots->OnEvent(EVENT_PLAYER_CHANGED_TEAM, player);
}
- TeamChangeUpdate(player, team);
+ TeamChangeUpdate(player, player->m_iTeam);
szOldTeam = GetTeam(oldTeam);
szNewTeam = GetTeam(team);
diff --git a/regamedll/dlls/combat.cpp b/regamedll/dlls/combat.cpp
index c23275ae..3cae8f3b 100644
--- a/regamedll/dlls/combat.cpp
+++ b/regamedll/dlls/combat.cpp
@@ -794,14 +794,14 @@ int CBaseMonster::__MAKE_VHOOK(TakeDamage)(entvars_t *pevInflictor, entvars_t *p
if (pInflictor)
{
-#if 0
+#ifndef PLAY_GAMEDLL
vecDir = (pInflictor->Center() - Vector(0, 0, 10) - Center()).Normalize();
#else
// TODO: fix test demo
vecDir = NormalizeSubtract<
float_precision, float, float_precision, float_precision
>(Center(), pInflictor->Center() - Vector(0, 0, 10));
-#endif
+#endif // PLAY_GAMEDLL
vecDir = g_vecAttackDir = vecDir.Normalize();
}
}
diff --git a/regamedll/dlls/gamerules.cpp b/regamedll/dlls/gamerules.cpp
index 24444018..64ba8abe 100644
--- a/regamedll/dlls/gamerules.cpp
+++ b/regamedll/dlls/gamerules.cpp
@@ -40,13 +40,13 @@ edict_t *CGameRules::__MAKE_VHOOK(GetPlayerSpawnSpot)(CBasePlayer *pPlayer)
{
edict_t *pentSpawnSpot = EntSelectSpawnPoint(pPlayer);
-#if HOOK_GAMEDLL
+#ifndef PLAY_GAMEDLL
+ pPlayer->pev->origin = VARS(pentSpawnSpot)->origin + Vector(0, 0, 1);
+#else
// TODO: fix test demo
pPlayer->pev->origin = VARS(pentSpawnSpot)->origin;
pPlayer->pev->origin.z += 1;
-#else
- pPlayer->pev->origin = VARS(pentSpawnSpot)->origin + Vector(0, 0, 1);
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
pPlayer->pev->v_angle = g_vecZero;
pPlayer->pev->velocity = g_vecZero;
diff --git a/regamedll/dlls/hostage/hostage.cpp b/regamedll/dlls/hostage/hostage.cpp
index 4ac39323..2d1895ed 100644
--- a/regamedll/dlls/hostage/hostage.cpp
+++ b/regamedll/dlls/hostage/hostage.cpp
@@ -192,7 +192,7 @@ void CHostage::SetActivity(int act)
void CHostage::IdleThink(void)
{
float flInterval;
- const float upkeepRate = 0.3f;
+ const float upkeepRate = 0.03f;
const float giveUpTime = (1 / 30.0f);
float const updateRate = 0.1f;
@@ -240,7 +240,7 @@ void CHostage::IdleThink(void)
return;
}
- if (m_hTargetEnt != NULL && (m_bStuck && gpGlobals->time - m_flStuckTime > 5.0 || m_hTargetEnt->pev->deadflag != DEAD_NO))
+ if (m_hTargetEnt != NULL && (m_bStuck && gpGlobals->time - m_flStuckTime > 5.0f || m_hTargetEnt->pev->deadflag != DEAD_NO))
{
m_State = STAND;
m_hTargetEnt = NULL;
@@ -325,8 +325,8 @@ void CHostage::IdleThink(void)
MESSAGE_BEGIN(MSG_SPEC, SVC_DIRECTOR);
WRITE_BYTE(9);
WRITE_BYTE(DRC_CMD_EVENT);
- WRITE_SHORT((player != NULL) ? player->entindex() : 0);
- WRITE_SHORT(player->entindex());
+ WRITE_SHORT(player != NULL ? player->entindex() : 0);
+ WRITE_SHORT(entindex());
WRITE_LONG(15);
MESSAGE_END();
@@ -840,7 +840,7 @@ void CHostage::__MAKE_VHOOK(Touch)(CBaseEntity *pOther)
vPush = (pev->origin - pOther->pev->origin).Make2D();
-#ifndef HOOK_GAMEDLL
+#ifndef PLAY_GAMEDLL
vPush = vPush.Normalize() * pushForce;
pev->velocity.x += vPush.x;
@@ -848,7 +848,7 @@ void CHostage::__MAKE_VHOOK(Touch)(CBaseEntity *pOther)
#else
// TODO: fix test demo
pev->velocity = pev->velocity + NormalizeMulScalar(vPush, pushForce);
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
}
/* <45dd66> ../cstrike/dlls/hostage/hostage.cpp:910 */
@@ -1173,14 +1173,14 @@ void CHostage::Wiggle(void)
}
}
-#ifndef HOOK_GAMEDLL
+#ifndef PLAY_GAMEDLL
vec = vec + Vector(RANDOM_FLOAT(-3, 3), RANDOM_FLOAT(-3, 3), 0);
#else
// TODO: fix test demo
vec.y = vec.y + RANDOM_FLOAT(-3.0, 3.0);
vec.x = vec.x + RANDOM_FLOAT(-3.0, 3.0);
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
pev->velocity = pev->velocity + (vec.Normalize() * 100);
}
diff --git a/regamedll/dlls/hostage/hostage.h b/regamedll/dlls/hostage/hostage.h
index d508e839..b88cf6a1 100644
--- a/regamedll/dlls/hostage/hostage.h
+++ b/regamedll/dlls/hostage/hostage.h
@@ -154,12 +154,10 @@ public:
bool IsFollowingSomeone(void)
{
- UNTESTED
return m_improv->IsFollowing();
}
CBaseEntity *GetLeader(void)
{
- UNTESTED
if (m_improv != NULL)
{
return m_improv->GetFollowLeader();
@@ -173,19 +171,20 @@ public:
}
bool IsValid(void)
{
- UNTESTED
return (pev->takedamage == DAMAGE_YES);
}
bool IsDead(void)
{
- UNTESTED
return (pev->deadflag == DEAD_DEAD);
}
bool IsAtHome(void)
{
return (pev->origin - m_vStart).IsLengthGreaterThan(20) != true;
}
- NOBODY const Vector *GetHomePosition(void);
+ const Vector *GetHomePosition(void)
+ {
+ return &m_vStart;
+ }
public:
enum state
@@ -243,7 +242,6 @@ public:
class SimpleChatter
{
public:
-
SimpleChatter(void);
~SimpleChatter(void);
diff --git a/regamedll/dlls/hostage/hostage_improv.cpp b/regamedll/dlls/hostage/hostage_improv.cpp
index 69899a49..6732619b 100644
--- a/regamedll/dlls/hostage/hostage_improv.cpp
+++ b/regamedll/dlls/hostage/hostage_improv.cpp
@@ -1,11 +1,16 @@
#include "precompiled.h"
/* <4703fc> ../cstrike/dlls/hostage/hostage_improv.cpp:19 */
-inline void DrawAxes(Vector &origin, int red, int green, int blue)
+inline void DrawAxes(const Vector &origin, int red, int green, int blue)
{
-// {
-// float size; // 21
-// }
+ float size = 10;
+
+ if (cv_hostage_debug.value != 1.0f)
+ return;
+
+ UTIL_DrawBeamPoints(origin - Vector(size, 0, 0), origin + Vector(size, 0, 0), 2, red, green, blue);
+ UTIL_DrawBeamPoints(origin - Vector(0, size, 0), origin + Vector(0, size, 0), 2, red, green, blue);
+ UTIL_DrawBeamPoints(origin + Vector(0, 0, size), origin - Vector(0, 0, size), 2, red, green, blue);
}
/* <47353e> ../cstrike/dlls/hostage/hostage_improv.cpp:41 */
@@ -72,7 +77,7 @@ bool CHostageImprov::DiscontinuityJump(float ground, bool onlyJumpDown, bool mus
Jump();
return true;
}
-
+
return false;
}
@@ -104,290 +109,373 @@ void CHostageImprov::__MAKE_VHOOK(ClearFaceTo)(void)
/* <476a30> ../cstrike/dlls/hostage/hostage_improv.cpp:154 */
void CHostageImprov::MoveTowards(const Vector &pos, float deltaT)
-{
- Vector move;
- float_precision accelRate;
- const float crouchWalkRate = 250.0f;
-
- //
- // Jump up on ledges
- // Because we may not be able to get to our goal position and enter the next
- // area because our extent collides with a nearby vertical ledge, make sure
- // we look far enough ahead to avoid this situation.
- // Can't look too far ahead, or bots will try to jump up slopes.
- //
- // NOTE: We need to do this frequently to catch edges at the right time
- // @todo Look ahead *along path* instead of straight line
- //
-
- ClearPath();
-
- if ((m_lastKnownArea == NULL || !(m_lastKnownArea->GetAttributes() & 8)) && !IsUsingLadder() && !IsJumping() && IsOnGround() && !IsCrouching())
- {
- float ground;
- Vector aheadRay(pos.x - GetFeet().x, pos.y - GetFeet().y, 0);
- aheadRay.NormalizeInPlace();
-
- bool jumped = false;
- if (IsRunning())
- {
- const float farLookAheadRange = 80.0f;
- Vector normal;
- Vector stepAhead = GetFeet() + farLookAheadRange * aheadRay;
- stepAhead.z += HumanHeight;
-
- if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground, &normal ))
- {
- if (normal.z > 0.9f)
- jumped = DiscontinuityJump(ground, HOSTAGE_ONLY_JUMP_DOWN);
- }
- }
-
- if (!jumped)
- {
- // close up jumping
- // cant be less or will miss jumps over low walls
- const float lookAheadRange = 30.0f;
- Vector stepAhead = GetFeet() + lookAheadRange * aheadRay;
- stepAhead.z += HumanHeight;
-
- if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground))
- {
- jumped = DiscontinuityJump(ground);
- }
- }
-
- if (!jumped)
- {
- // about to fall gap-jumping
- const float lookAheadRange = 10.0f;
- Vector stepAhead = GetFeet() + lookAheadRange * aheadRay;
- stepAhead.z += HumanHeight;
-
- if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground))
- {
- jumped = DiscontinuityJump(ground, HOSTAGE_ONLY_JUMP_DOWN, HOSTAGE_MUST_JUMP);
- }
- }
- }
-
- move = (pos - GetFeet());
- move.z = 0;
-
- if (!move.IsZero())
- {
- move.NormalizeInPlace();
- }
-
- switch (m_moveType)
- {
- case Stopped:
- accelRate = 0;
- break;
- case Walking:
- if (IsCrouching())
- accelRate = crouchWalkRate;
- else
- accelRate = 400;
- break;
- case Running:
- if (IsCrouching())
- accelRate = crouchWalkRate;
- else
- accelRate = 1000;
- break;
- }
-
- m_vel.x = move.x * accelRate * deltaT + m_vel.x;
+{
+ Vector move;
+ float_precision accelRate;
+ const float crouchWalkRate = 250.0f;
+
+ // Jump up on ledges
+ // Because we may not be able to get to our goal position and enter the next
+ // area because our extent collides with a nearby vertical ledge, make sure
+ // we look far enough ahead to avoid this situation.
+ // Can't look too far ahead, or bots will try to jump up slopes.
+ //
+ // NOTE: We need to do this frequently to catch edges at the right time
+ // TODO: Look ahead *along path* instead of straight line
+
+ ClearPath();
+
+ if ((m_lastKnownArea == NULL || !(m_lastKnownArea->GetAttributes() & 8)) && !IsUsingLadder() && !IsJumping() && IsOnGround() && !IsCrouching())
+ {
+ float ground;
+ Vector aheadRay(pos.x - GetFeet().x, pos.y - GetFeet().y, 0);
+ aheadRay.NormalizeInPlace();
+
+ bool jumped = false;
+ if (IsRunning())
+ {
+ const float farLookAheadRange = 80.0f;
+ Vector normal;
+ Vector stepAhead = GetFeet() + farLookAheadRange * aheadRay;
+ stepAhead.z += HumanHeight;
+
+ if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground, &normal ))
+ {
+ if (normal.z > 0.9f)
+ jumped = DiscontinuityJump(ground, HOSTAGE_ONLY_JUMP_DOWN);
+ }
+ }
+
+ if (!jumped)
+ {
+ // close up jumping
+ // cant be less or will miss jumps over low walls
+ const float lookAheadRange = 30.0f;
+ Vector stepAhead = GetFeet() + lookAheadRange * aheadRay;
+ stepAhead.z += HumanHeight;
+
+ if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground))
+ {
+ jumped = DiscontinuityJump(ground);
+ }
+ }
+
+ if (!jumped)
+ {
+ // about to fall gap-jumping
+ const float lookAheadRange = 10.0f;
+ Vector stepAhead = GetFeet() + lookAheadRange * aheadRay;
+ stepAhead.z += HumanHeight;
+
+ if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground))
+ {
+ jumped = DiscontinuityJump(ground, HOSTAGE_ONLY_JUMP_DOWN, HOSTAGE_MUST_JUMP);
+ }
+ }
+ }
+
+ move = (pos - GetFeet());
+ move.z = 0;
+
+ if (!move.IsZero())
+ {
+ move.NormalizeInPlace();
+ }
+
+ switch (m_moveType)
+ {
+ case Stopped:
+ accelRate = 0;
+ break;
+ case Walking:
+ if (IsCrouching())
+ accelRate = crouchWalkRate;
+ else
+ accelRate = 400;
+ break;
+ case Running:
+ if (IsCrouching())
+ accelRate = crouchWalkRate;
+ else
+ accelRate = 1000;
+ break;
+ }
+
+ m_vel.x = move.x * accelRate * deltaT + m_vel.x;
m_vel.y = move.y * accelRate * deltaT + m_vel.y;
}
-void (*pCHostageImprov__FaceTowards)();
-
/* <473e46> ../cstrike/dlls/hostage/hostage_improv.cpp:262 */
-NOBODY bool __declspec(naked) CHostageImprov::FaceTowards(const Vector &target, float deltaT)
+bool CHostageImprov::FaceTowards(const Vector &target, float deltaT)
{
- __asm
+ float error = 0;
+ Vector2D to = (target - GetFeet()).Make2D();
+
+#ifndef PLAY_GAMEDLL
+ to.NormalizeInPlace();
+#else
+ // TODO: fix test demo
+ float_precision float_x = target.x - GetFeet().x;
+ float_precision float_y = target.y - GetFeet().y;
+ float_precision flLen = to.Length();
+
+ if (flLen <= 0)
{
- jmp pCHostageImprov__FaceTowards
+ to.x = 1;
+ to.y = 0;
+ }
+ else
+ {
+ to.x = float_x / flLen;
+ to.y = float_y / flLen;
+ }
+#endif // PLAY_GAMEDLL
+
+ float moveAngle = GetMoveAngle();
+
+ Vector2D lat(BotCOS(moveAngle), BotSIN(moveAngle));
+ Vector2D dir(-lat.y, lat.x);
+
+ float_precision dot = DotProduct(to, dir);
+
+ if (DotProduct(to, lat) < 0.0f)
+ {
+ if (dot >= 0.0f)
+ dot = 1.0f;
+ else
+ dot = -1.0f;
+
+ error = 1;
+ }
+
+ const float maxTurnRate = 0.05f;
+
+ if (error || fabs(dot) >= maxTurnRate)
+ {
+ const float tolerance = 300.0f;
+ float moveRatio = dot * deltaT * tolerance + moveAngle;
+
+ BotCOS(moveRatio);
+ BotSIN(moveRatio);
+
+ m_moveAngle = moveRatio;
+ m_hostage->pev->angles.y = moveRatio;
+
+ return false;
}
-// {
-// class Vector2D to; // 264
-// float moveAngle; // 267
-// class Vector2D dir; // 270
-// class Vector2D lat; // 271
-// float const maxTurnRate; // 273
-// float error; // 275
-// float dot; // 278
-// operator-(const Vector *const this,
-// const Vector &v); // 264
-// NormalizeInPlace(Vector2D *const this); // 265
-// DotProduct(const class Vector2D &a,
-// const class Vector2D &b); // 275
-// DotProduct(const class Vector2D &a,
-// const class Vector2D &b); // 278
-// {
-// float const tolerance; // 285
-// fabs(double __x); // 286
-// }
-// SetMoveAngle(CHostageImprov *const this,
-// float angle); // 298
-// }
+ return true;
}
/* <47402b> ../cstrike/dlls/hostage/hostage_improv.cpp:308 */
-NOBODY void CHostageImprov::FaceOutwards(void)
+void CHostageImprov::FaceOutwards(void)
{
-// {
-// TraceResult result; // 310
-// Vector to; // 312
-// float farthestRange; // 313
-// int farthest; // 314
-// int const cornerCount; // 316
-// Vector corner; // 317
-// {
-// int i; // 325
-// {
-// float range; // 328
-// operator+(const Vector *const this,
-// const Vector &v); // 327
-// operator-(const Vector *const this,
-// const Vector &v); // 328
-// LengthSquared(const Vector *const this); // 328
-// }
-// }
-// operator+(const Vector *const this,
-// const Vector &v); // 337
-// Vector(Vector *const this,
-// float X,
-// float Y,
-// float Z); // 323
-// Vector(Vector *const this,
-// float X,
-// float Y,
-// float Z); // 323
-// Vector(Vector *const this,
-// float X,
-// float Y,
-// float Z); // 323
-// Vector(Vector *const this,
-// float X,
-// float Y,
-// float Z); // 323
-// }
+ TraceResult result;
+ Vector to;
+ float farthestRange = 0.0f;
+ int farthest = 0;
+
+ Vector corner[] =
+ {
+ Vector(-1000, 1000, 0),
+ Vector(1000, 1000, 0),
+ Vector(-1000, -1000, 0),
+ Vector(1000, -1000, 0)
+ };
+
+ const int cornerCount = ARRAYSIZE(corner);
+
+ for (int i = 0; i < cornerCount; ++i)
+ {
+ to = GetCentroid() + corner[i];
+
+ UTIL_TraceLine(GetCentroid(), to, ignore_monsters, ignore_glass, m_hostage->edict(), &result);
+
+ float_precision range = (result.vecEndPos - GetCentroid()).LengthSquared();
+
+ if (range > farthestRange)
+ {
+ farthestRange = range;
+ farthest = i;
+ }
+ }
+
+ to = GetCentroid() + corner[farthest];
+ FaceTo(to);
}
/* <470e23> ../cstrike/dlls/hostage/hostage_improv.cpp:344 */
-NOBODY bool CHostageImprov::__MAKE_VHOOK(IsAtMoveGoal)(float error) const
+bool CHostageImprov::__MAKE_VHOOK(IsAtMoveGoal)(float error) const
{
-// operator-(const Vector *const this,
-// const Vector &v); // 346
-// IsLengthLessThan(const Vector *const this,
-// float length); // 346
+ return (GetFeet() - m_moveGoal).IsLengthLessThan(error);
}
/* <470eab> ../cstrike/dlls/hostage/hostage_improv.cpp:353 */
-NOBODY bool CHostageImprov::__MAKE_VHOOK(IsAtFaceGoal)(void) const
+bool CHostageImprov::__MAKE_VHOOK(IsAtFaceGoal)(void) const
{
+ return false;
}
+// Return true if a friend is between us and the given position
+
/* <46fb4b> ../cstrike/dlls/hostage/hostage_improv.cpp:395 */
-NOBODY bool CHostageImprov::__MAKE_VHOOK(IsFriendInTheWay)(const Vector &goalPos) const
+bool CHostageImprov::__MAKE_VHOOK(IsFriendInTheWay)(const Vector &goalPos) const
{
-// {
-// float const avoidFriendInterval; // 403
-// IsElapsed(const class CountdownTimer *const this); // 398
-// {
-// class CheckWayFunctor check; // 411
-// }
-// {
-// int i; // 421
-// {
-// class CBasePlayer *player; // 423
-// }
-// }
-// }
-// IsFriendInTheWay(const class CHostageImprov *const this,
-// const Vector &goalPos); // 395
+ // do this check less often to ease CPU burden
+ if (!m_avoidFriendTimer.IsElapsed())
+ {
+ return m_isFriendInTheWay;
+ }
+
+ const float avoidFriendInterval = 0.5f;
+ m_avoidFriendTimer.Start(avoidFriendInterval);
+
+ CheckWayFunctor check(this, goalPos);
+
+ if (g_pHostages != NULL)
+ {
+ g_pHostages->ForEachHostage(check);
+
+ if (check.m_blocker != NULL)
+ {
+ return m_isFriendInTheWay = true;
+ }
+ }
+
+ // check if any CT are overlapping this linear path
+ for (int i = 1; i <= gpGlobals->maxClients; ++i)
+ {
+ CBasePlayer *player = static_cast(UTIL_PlayerByIndex(i));
+
+ if (player == NULL)
+ continue;
+
+ if (FNullEnt(player->pev))
+ continue;
+
+ if (!player->IsAlive() || player->m_iTeam == TERRORIST)
+ continue;
+
+ if (IsFriendInTheWay(player, goalPos))
+ {
+ m_isFriendInTheWay = true;
+ break;
+ }
+ }
+
+ return m_isFriendInTheWay;
}
+// Return true if a friend is between us and the given entity
+
/* <472b83> ../cstrike/dlls/hostage/hostage_improv.cpp:453 */
-NOBODY bool CHostageImprov::__MAKE_VHOOK(IsFriendInTheWay)(CBaseEntity *myFriend, const Vector &goalPos) const
+bool CHostageImprov::__MAKE_VHOOK(IsFriendInTheWay)(CBaseEntity *myFriend, const Vector &goalPos) const
{
-// {
-// Vector moveDir; // 460
-// float length; // 463
-// Vector friendFeet; // 465
-// Vector toFriend; // 476
-// float const personalSpace; // 479
-// float friendDistAlong; // 484
-// Vector pos; // 491
-// float const friendRadius; // 498
-// operator-(const Vector *const this,
-// const Vector &v); // 460
-// NormalizeInPlace(Vector *const this); // 463
-// operator-(const Vector *const this,
-// const Vector &v); // 476
-// IsLengthGreaterThan(const Vector *const this,
-// float length); // 480
-// DotProduct(Vector &a,
-// const Vector &b); // 484
-// operator-(const Vector *const this,
-// const Vector &v); // 499
-// IsLengthLessThan(const Vector *const this,
-// float length); // 499
-// IsZero(Vector *const this,
-// float tolerance); // 504
-// DotProduct(Vector &a,
-// const Vector &b); // 507
-// operator*(float fl,
-// const Vector &v); // 495
-// operator+(const Vector *const this,
-// const Vector &v); // 495
-// }
+ if (m_hostage == myFriend)
+ return false;
+
+ // compute ray along intended path
+ Vector moveDir = goalPos - GetFeet();
+ Vector friendFeet = myFriend->pev->origin;
+
+ // make it a unit vector
+ float length = moveDir.NormalizeInPlace();
+
+ if (myFriend->IsPlayer())
+ friendFeet.z = myFriend->pev->absmin.z;
+
+ Vector toFriend = friendFeet - GetFeet();
+
+ // check if friend is in our "personal space"
+ const float personalSpace = 100.0f;
+ if (toFriend.IsLengthGreaterThan(personalSpace))
+ return false;
+
+ // find distance of friend along our movement path
+ float friendDistAlong = DotProduct(toFriend, moveDir);
+
+ // if friend is behind us, ignore him
+ if (friendDistAlong <= 0.0f)
+ return false;
+
+ // constrain point to be on path segment
+ Vector pos;
+ if (friendDistAlong >= length)
+ pos = goalPos;
+ else
+ pos = GetFeet() + moveDir * friendDistAlong;
+
+ // check if friend overlaps our intended line of movement
+ const float friendRadius = 30.0f;
+ if (!(pos - friendFeet).IsLengthLessThan(friendRadius))
+ return false;
+
+ if (!myFriend->pev->velocity.IsZero())
+ {
+ if (DotProduct(myFriend->pev->velocity, m_hostage->pev->velocity) >= 0.0)
+ return false;
+ }
+
+ // friend is in our personal space and overlaps our intended line of movement
+ return true;
}
/* <474309> ../cstrike/dlls/hostage/hostage_improv.cpp:557 */
-NOBODY bool CHostageImprov::IsFriendInTheWay(void)
+bool CHostageImprov::IsFriendInTheWay(void) const
{
-// {
-// class CheckAhead check; // 559
-// CheckAhead(CheckAhead *const this,
-// const class CHostageImprov *me); // 559
-// ForEachHostage(const class CHostageManager *const this,
-// class CheckAhead &func); // 561
-// ForEachPlayer(CheckAhead &func); // 562
-// }
+ CheckAhead check(this);
+ g_pHostages->ForEachHostage(check);
+ ForEachPlayer(check);
+
+ return check.IsBlocked();
}
/* <474631> ../cstrike/dlls/hostage/hostage_improv.cpp:568 */
-NOBODY float CHostageImprov::GetSpeed(void)
+float CHostageImprov::GetSpeed(void)
{
+ return -1.0f;
}
/* <46f249> ../cstrike/dlls/hostage/hostage_improv.cpp:592 */
-NOBODY bool CHostageImprov::__MAKE_VHOOK(Jump)(void)
+bool CHostageImprov::__MAKE_VHOOK(Jump)(void)
{
-// IsElapsed(const class CountdownTimer *const this); // 604
-// {
-// float const epsilon; // 609
-// float const minJumpInterval; // 618
-// {
-// float const fudge; // 613
-// }
-// }
-// Jump(CHostageImprov *const this); // 592
+ if (IsCrouching() || g_pHostages->IsNearbyHostageJumping(this))
+ return false;
+
+ if (!m_jumpTimer.IsElapsed())
+ return false;
+
+ const float epsilon = 1.0f;
+
+ m_hasJumped = false;
+ m_moveFlags |= IN_JUMP;
+
+ if (m_hostage->pev->velocity.LengthSquared() < epsilon)
+ {
+ const float fudge = 2.0f;
+ m_hostage->pev->origin.z += fudge;
+ }
+
+ const float minJumpInterval = 3.0f;
+ m_jumpTimer.Start(minJumpInterval);
+
+ m_animateState.Reset();
+ m_animateState.SetPerformance(HostageAnimateState::Jump);
+ m_animateState.AddSequence(this, ACT_HOP);
+
+ return true;
}
/* <470ed3> ../cstrike/dlls/hostage/hostage_improv.cpp:632 */
-NOBODY void CHostageImprov::__MAKE_VHOOK(Run)(void)
+void CHostageImprov::__MAKE_VHOOK(Run)(void)
{
+ m_moveType = m_moveLimit;
}
/* <470efb> ../cstrike/dlls/hostage/hostage_improv.cpp:638 */
-NOBODY void CHostageImprov::__MAKE_VHOOK(Walk)(void)
+void CHostageImprov::__MAKE_VHOOK(Walk)(void)
{
+ m_moveType = (m_moveLimit > Walking) ? Walking : m_moveLimit;
}
/* <470f23> ../cstrike/dlls/hostage/hostage_improv.cpp:644 */
@@ -395,7 +483,7 @@ void CHostageImprov::__MAKE_VHOOK(Stop)(void)
{
MoveTo(GetFeet());
m_hostage->pev->velocity = Vector(0, 0, 0);
-
+
if (m_moveLimit > Stopped)
m_moveType = Stopped;
else
@@ -423,18 +511,16 @@ const Vector &CHostageImprov::__MAKE_VHOOK(GetEyes)(void) const
}
/* <470fc4> ../cstrike/dlls/hostage/hostage_improv.cpp:681 */
-NOBODY bool CHostageImprov::__MAKE_VHOOK(IsOnGround)(void) const
+bool CHostageImprov::__MAKE_VHOOK(IsOnGround)(void) const
{
+ return (m_hostage->pev->flags & FL_ONGROUND) != 0;
}
/* <470fec> ../cstrike/dlls/hostage/hostage_improv.cpp:687 */
-NOBODY bool CHostageImprov::__MAKE_VHOOK(IsMoving)(void) const
+bool CHostageImprov::__MAKE_VHOOK(IsMoving)(void) const
{
-// {
-// float const epsilon; // 689
-// IsLengthGreaterThan(const Vector *const this,
-// float length); // 690
-// }
+ float const epsilon = 10.0f;
+ return m_actualVel.IsLengthGreaterThan(epsilon);
}
/* <4715d1> ../cstrike/dlls/hostage/hostage_improv.cpp:697 */
@@ -448,51 +534,84 @@ bool CHostageImprov::__MAKE_VHOOK(IsVisible)(const Vector &pos, bool testFOV) co
}
/* <472938> ../cstrike/dlls/hostage/hostage_improv.cpp:728 */
-NOBODY bool CHostageImprov::__MAKE_VHOOK(IsPlayerLookingAtMe)(CBasePlayer *other, float cosTolerance) const
+bool CHostageImprov::__MAKE_VHOOK(IsPlayerLookingAtMe)(CBasePlayer *other, float cosTolerance) const
{
-// {
-// class Vector2D toOther; // 730
-// class Vector2D otherDir; // 737
-// NormalizeInPlace(Vector2D *const this); // 733
-// operator+(const Vector *const this,
-// const Vector &v); // 736
-// NormalizeInPlace(Vector2D *const this); // 740
-// }
+ Vector2D toOther = (other->pev->origin - GetCentroid()).Make2D();
+ toOther.NormalizeInPlace();
+
+ UTIL_MakeVectors(other->pev->punchangle + other->pev->v_angle);
+
+ Vector2D otherDir = gpGlobals->v_forward.Make2D();
+ otherDir.NormalizeInPlace();
+
+ if (-cosTolerance > DotProduct(toOther, otherDir))
+ {
+ if (IsVisible(other->EyePosition()))
+ {
+ return true;
+ }
+ }
+
+ return false;
}
/* <472a9f> ../cstrike/dlls/hostage/hostage_improv.cpp:757 */
-NOBODY CBasePlayer *CHostageImprov::__MAKE_VHOOK(IsAnyPlayerLookingAtMe)(int team, float cosTolerance) const
+CBasePlayer *CHostageImprov::__MAKE_VHOOK(IsAnyPlayerLookingAtMe)(int team, float cosTolerance) const
{
-// {
-// int i; // 759
-// {
-// class CBasePlayer *player; // 761
-// IsEntityValid(CBaseEntity *entity); // 763
-// }
-// }
+ for (int i = 1; i <= gpGlobals->maxClients; ++i)
+ {
+ CBasePlayer *player = static_cast(UTIL_PlayerByIndex(i));
+
+ if (!IsEntityValid(player))
+ continue;
+
+ if (player->IsAlive() && (team == UNASSIGNED || player->m_iTeam == team))
+ {
+ if (IsPlayerLookingAtMe(player, cosTolerance))
+ {
+ return player;
+ }
+ }
+ }
+
+ return NULL;
}
/* <472e7b> ../cstrike/dlls/hostage/hostage_improv.cpp:783 */
-NOBODY CBasePlayer *CHostageImprov::__MAKE_VHOOK(GetClosestPlayerByTravelDistance)(int team, float *range) const
+CBasePlayer *CHostageImprov::__MAKE_VHOOK(GetClosestPlayerByTravelDistance)(int team, float *range) const
{
-// {
-// class CBasePlayer *close; // 788
-// float closeRange; // 789
-// {
-// int i; // 791
-// {
-// class CBasePlayer *player; // 793
-// class ShortestPathCost cost; // 804
-// Vector vecCenter; // 805
-// float range; // 806
-// IsEntityValid(CBaseEntity *entity); // 795
-// NavAreaTravelDistance(const Vector *startPos,
-// class CNavArea *startArea,
-// const Vector *goalPos,
-// class ShortestPathCost &costFunc); // 806
-// }
-// }
-// }
+ CBasePlayer *close = NULL;
+ float closeRange = 9.9999998e10f;
+
+ if (GetLastKnownArea() == NULL)
+ return NULL;
+
+ for (int i = 1; i <= gpGlobals->maxClients; ++i)
+ {
+ CBasePlayer *player = static_cast(UTIL_PlayerByIndex(i));
+
+ if (!IsEntityValid(player))
+ continue;
+
+ if (player->IsAlive() && (team == UNASSIGNED || player->m_iTeam == team))
+ {
+ ShortestPathCost cost;
+ Vector vecCenter = player->Center();
+
+ float_precision range = NavAreaTravelDistance(GetLastKnownArea(), TheNavAreaGrid.GetNearestNavArea(&vecCenter), cost);
+
+ if (range > 0 && range < closeRange)
+ {
+ closeRange = range;
+ close = player;
+ }
+ }
+ }
+
+ if (range)
+ *range = closeRange;
+
+ return close;
}
/* <47166d> ../cstrike/dlls/hostage/hostage_improv.cpp:822 */
@@ -553,28 +672,51 @@ void CHostageImprov::__MAKE_VHOOK(OnReset)(void)
}
/* <474659> ../cstrike/dlls/hostage/hostage_improv.cpp:886 */
-NOBODY void CHostageImprov::UpdateVision(void)
+void CHostageImprov::UpdateVision(void)
{
-// IsElapsed(const class CountdownTimer *const this); // 888
-// {
-// int i; // 893
-// {
-// class CBasePlayer *player; // 895
-// FNullEnt(entvars_t *pev); // 900
-// Start(IntervalTimer *const this); // 914
-// Start(IntervalTimer *const this); // 916
-// }
-// }
-// Start(CountdownTimer *const this,
-// float duration); // 924
+ if (!m_visionTimer.IsElapsed())
+ return;
+
+ m_visiblePlayerCount = false;
+
+ for (int i = 1; i <= gpGlobals->maxClients; ++i)
+ {
+ CBasePlayer *player = static_cast(UTIL_PlayerByIndex(i));
+
+ if (player == NULL)
+ continue;
+
+ if (FNullEnt(player->pev))
+ continue;
+
+ if (FStrEq(STRING(player->pev->netname), ""))
+ continue;
+
+ if (player->IsAlive() && IsVisible(player->pev->origin, true))
+ {
+ m_visiblePlayer[m_visiblePlayerCount] = player;
+
+ if (player->m_iTeam == TERRORIST)
+ m_lastSawT.Start();
+ else
+ m_lastSawCT.Start();
+
+ if (++m_visiblePlayerCount == ARRAYSIZE(m_visiblePlayer))
+ break;
+ }
+ }
+
+ m_visionTimer.Start(RANDOM_FLOAT(0.4, 0.6));
}
/* <476e49> ../cstrike/dlls/hostage/hostage_improv.cpp:997 */
-NOBODY void CHostageImprov::__MAKE_VHOOK(TrackPath)(const Vector &pathGoal, float deltaT)
+void CHostageImprov::__MAKE_VHOOK(TrackPath)(const Vector &pathGoal, float deltaT)
{
-// TrackPath(CHostageImprov *const this,
-// const Vector &pathGoal,
-// float deltaT); // 997
+ FaceTowards(pathGoal, deltaT);
+ MoveTowards(pathGoal, deltaT);
+
+ m_jumpTarget = pathGoal;
+ DrawAxes(pathGoal, 255, 0, 255);
}
/* <474781> ../cstrike/dlls/hostage/hostage_improv.cpp:1014 */
@@ -630,121 +772,261 @@ void CHostageImprov::ResetToKnownGoodPosition(void)
}
/* <47105c> ../cstrike/dlls/hostage/hostage_improv.cpp:1082 */
-void CHostageImprov::__MAKE_VHOOK(StartLadder)(const class CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos)
+void CHostageImprov::__MAKE_VHOOK(StartLadder)(const CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos)
{
m_traversingLadder = true;
}
/* <4710c4> ../cstrike/dlls/hostage/hostage_improv.cpp:1094 */
-NOBODY bool CHostageImprov::__MAKE_VHOOK(TraverseLadder)(const CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos, float deltaT)
+bool CHostageImprov::__MAKE_VHOOK(TraverseLadder)(const CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos, float deltaT)
{
-// {
-// Vector goal; // 1098
-// AddDirectionVector(Vector *v,
-// enum NavDirType dir,
-// float amount); // 1122
-// {
-// float const atGoalRange; // 1198
-// {
-// float closeRange; // 1158
-// float range; // 1158
-// operator-(const Vector *const this,
-// const Vector &v); // 1162
-// LengthSquared(const Vector *const this); // 1162
-// operator-(const Vector *const this,
-// const Vector &v); // 1174
-// LengthSquared(const Vector *const this); // 1174
-// operator-(const Vector *const this,
-// const Vector &v); // 1186
-// LengthSquared(const Vector *const this); // 1186
-// }
-// operator-(const Vector *const this,
-// const Vector &v); // 1199
-// IsLengthLessThan(const class Vector2D *const this,
-// float length); // 1199
-// }
-// {
-// float const walkRange; // 1130
-// float const ladderRange; // 1135
-// operator-(const Vector *const this,
-// const Vector &v); // 1131
-// IsLengthLessThan(const class Vector2D *const this,
-// float length); // 1131
-// operator-(const Vector *const this,
-// const Vector &v); // 1136
-// IsLengthLessThan(const class Vector2D *const this,
-// float length); // 1136
-// }
-// AddDirectionVector(Vector *v,
-// enum NavDirType dir,
-// float amount); // 1103
-// {
-// float const ladderRange; // 1108
-// operator-(const Vector *const this,
-// const Vector &v); // 1109
-// IsLengthLessThan(const class Vector2D *const this,
-// float length); // 1109
-// }
-// }
+ Vector goal;
+
+ if (how == GO_LADDER_DOWN)
+ {
+ goal = ladder->m_bottom;
+ AddDirectionVector(&goal, ladder->m_dir, 16);
+
+ if (ladder->m_top.z - 36.0f > GetFeet().z)
+ {
+ const float atGoalRange = 50.0f;
+ if ((GetFeet() - goal).Make2D().IsLengthLessThan(atGoalRange))
+ {
+ m_hostage->pev->velocity.z = -100.0f;
+ }
+ }
+
+ if (ladder->m_bottom.z + 36.0f > GetFeet().z)
+ return true;
+ }
+ else if (m_traversingLadder)
+ {
+ goal = ladder->m_top;
+ AddDirectionVector(&goal, ladder->m_dir, 16);
+
+ const float walkRange = 100.0f;
+
+ if ((GetFeet() - goal).Make2D().IsLengthLessThan(walkRange))
+ {
+ Walk();
+ }
+
+ const float ladderRange = 40.0f;
+ if ((GetFeet() - goal).Make2D().IsLengthLessThan(ladderRange))
+ {
+ m_hostage->pev->velocity.z = 150.0;
+ }
+
+ if (GetFeet().z > ladder->m_top.z)
+ m_traversingLadder = false;
+ }
+ else
+ {
+ if (departPos != NULL)
+ {
+ float closeRange = 1e6;
+ float range;
+
+ if (ladder->m_topForwardArea != NULL)
+ {
+ range = (*departPos - *ladder->m_topForwardArea->GetCenter()).LengthSquared();
+
+ if (range < closeRange)
+ {
+ closeRange = range;
+ goal = *ladder->m_topForwardArea->GetCenter();
+
+ if (ladder->m_topForwardArea->GetAttributes() & NAV_CROUCH)
+ {
+ Crouch();
+ }
+ }
+ }
+ if (ladder->m_topLeftArea != NULL)
+ {
+ range = (*departPos - *ladder->m_topLeftArea->GetCenter()).LengthSquared();
+
+ if (closeRange > range)
+ {
+ goal = *ladder->m_topLeftArea->GetCenter();
+
+ if (ladder->m_topLeftArea->GetAttributes() & NAV_CROUCH)
+ {
+ Crouch();
+ }
+ }
+ }
+ if (ladder->m_topRightArea != NULL)
+ {
+ range = (*departPos - *ladder->m_topRightArea->GetCenter()).LengthSquared();
+
+ if (closeRange > range)
+ {
+ goal = *ladder->m_topRightArea->GetCenter();
+
+ if (ladder->m_topRightArea->GetAttributes() & NAV_CROUCH)
+ {
+ Crouch();
+ }
+ }
+ }
+ }
+
+ const float ladderRange = 20.0f;
+ if ((GetFeet() - goal).Make2D().IsLengthLessThan(ladderRange))
+ {
+ return true;
+ }
+ }
+
+ TrackPath(goal, deltaT);
+ return false;
}
/* <477691> ../cstrike/dlls/hostage/hostage_improv.cpp:1214 */
-NOBODY void CHostageImprov::UpdatePosition(float deltaT)
+void CHostageImprov::UpdatePosition(float deltaT)
{
-// {
-// class CNavArea *area; // 1217
-// float const friction; // 1344
-// float speed; // 1349
-// float const maxSpeed; // 1351
-// class KeepPersonalSpace spacer; // 1365
-// {
-// float const pushSpeed; // 1258
-// Vector dir; // 1260
-// operator-(const Vector *const this,
-// const Vector &v); // 1260
-// NormalizeInPlace(Vector *const this); // 1262
-// ResetJump(CHostageImprov *const this); // 1247
-// }
-// {
-// Vector angles; // 1282
-// float yaw; // 1284
-// float pitch; // 1288
-// operator-(const Vector *const this,
-// const Vector &v); // 1282
-// }
-// {
-// class HostagePathCost pathCost; // 1322
-// Compute(CNavPath *const this,
-// const Vector *start,
-// const Vector *goal,
-// class HostagePathCost &costFunc); // 1323
-// SetPath(CNavPathFollower *const this,
-// class CNavPath *path); // 1326
-// SetImprov(CNavPathFollower *const this,
-// class CImprov *improv); // 1325
-// Debug(CNavPathFollower *const this,
-// bool status); // 1328
-// }
-// IsElapsed(const class CountdownTimer *const this); // 1333
-// ResetStuck(CNavPathFollower *const this); // 1336
-// NormalizeInPlace(Vector2D *const this); // 1349
-// operator*(float fl,
-// const class Vector2D &v); // 1355
-// KeepPersonalSpace(KeepPersonalSpace *const this,
-// class CHostageImprov *improv); // 1365
-// ForEachPlayer(KeepPersonalSpace &func); // 1366
-// DrawAxes(Vector &origin,
-// int red,
-// int green,
-// int blue); // 1223
-// ForEachHostage(const class CHostageManager *const this,
-// class KeepPersonalSpace &func); // 1369
-// }
+ CNavArea *area = TheNavAreaGrid.GetNavArea(&m_hostage->pev->origin);
+
+ if (area != NULL)
+ {
+ m_lastKnownArea = area;
+ }
+
+ DrawAxes(m_moveGoal, 255, 255, 0);
+
+ if (IsJumping())
+ {
+ Vector dir;
+ const float pushSpeed = 100.0f;
+
+ if (!m_hasJumped)
+ {
+ m_hasJumped = true;
+ m_hasJumpedIntoAir = false;
+ m_hostage->pev->velocity.z += 300.0f;
+ }
+ else
+ ResetJump();
+
+ dir = m_jumpTarget - GetFeet();
+ dir.z = 0;
+
+ dir.NormalizeInPlace();
+
+ m_hostage->pev->velocity.x = dir.x * pushSpeed;
+ m_hostage->pev->velocity.y = dir.y * pushSpeed;
+
+ m_hostage->SetBoneController(0);
+ m_hostage->SetBoneController(1);
+
+ FaceTowards(m_jumpTarget, deltaT);
+ return;
+ }
+
+ if (m_isLookingAt)
+ {
+ Vector angles = UTIL_VecToAngles(m_viewGoal - GetEyes());
+ float_precision pitch = angles.x - m_hostage->pev->angles.x;
+ float_precision yaw = angles.y - m_hostage->pev->angles.y;
+
+ while (yaw > 180.0f)
+ yaw -= 360.0f;
+
+ while (yaw < -180.0f)
+ yaw += 360.0f;
+
+ while (pitch > 180.0f)
+ pitch -= 360.0f;
+
+ while (pitch < -180.0f)
+ pitch += 360.0f;
+
+ m_hostage->SetBoneController(0, yaw);
+ m_hostage->SetBoneController(1, -pitch);
+
+ if (IsAtMoveGoal() && !HasFaceTo())
+ {
+ if (yaw < -45.0f || yaw > 45.0f)
+ {
+ FaceTowards(m_viewGoal, deltaT);
+ }
+ }
+ }
+ else
+ {
+ m_hostage->SetBoneController(0);
+ m_hostage->SetBoneController(1);
+ }
+
+ if (HasFaceTo() && FaceTowards(m_faceGoal, deltaT))
+ ClearFaceTo();
+
+ if (!IsAtMoveGoal() || m_path.GetSegmentCount() > 0)
+ {
+ if (m_path.GetSegmentCount() <= 0)
+ {
+ HostagePathCost pathCost;
+ if (m_path.Compute(&GetFeet(), &m_moveGoal, pathCost))
+ {
+ m_follower.SetPath(&m_path);
+ m_follower.SetImprov(this);
+
+ m_follower.Reset();
+ m_follower.Debug(cv_hostage_debug.value > 0.0);
+ }
+ }
+
+ m_follower.Update(deltaT, m_inhibitObstacleAvoidance.IsElapsed());
+
+ if (m_moveType == Stopped)
+ {
+ m_follower.ResetStuck();
+ }
+
+ if (m_follower.IsStuck())
+ {
+ Wiggle();
+ }
+ }
+
+ const float friction = 3.0f;
+
+ m_vel.x += m_vel.x * -friction * deltaT;
+ m_vel.y += m_vel.y * -friction * deltaT;
+
+ float_precision speed = m_vel.NormalizeInPlace();
+
+ const float maxSpeed = 285.0f;
+ if (speed > maxSpeed)
+ {
+ speed = maxSpeed;
+ }
+
+ m_vel.x = m_vel.x * speed;
+ m_vel.y = m_vel.y * speed;
+
+ KeepPersonalSpace spacer(this);
+ ForEachPlayer(spacer);
+
+ if (g_pHostages != NULL)
+ {
+ g_pHostages->ForEachHostage(spacer);
+ }
+
+ m_hostage->pev->velocity.x = m_vel.x;
+ m_hostage->pev->velocity.y = m_vel.y;
+
+ m_moveFlags = 0;
}
/* <47837a> ../cstrike/dlls/hostage/hostage_improv.cpp:1384 */
-NOBODY void CHostageImprov::__MAKE_VHOOK(OnUpkeep)(float deltaT)
+void CHostageImprov::__MAKE_VHOOK(OnUpkeep)(float deltaT)
{
+ if (IsAlive())
+ {
+ UpdatePosition(deltaT);
+ }
}
/* <4749f9> ../cstrike/dlls/hostage/hostage_improv.cpp:1396 */
@@ -762,15 +1044,14 @@ bool CHostageImprov::IsTerroristNearby(void)
/* <474ae7> ../cstrike/dlls/hostage/hostage_improv.cpp:1412 */
void CHostageImprov::CheckForNearbyTerrorists(void)
{
- const float checkInterval = 2.0f;
- float range;
-
if (!m_checkNearbyTerroristTimer.IsElapsed())
return;
-
+
+ const float checkInterval = 2.0f;
m_checkNearbyTerroristTimer.Start(checkInterval);
m_isTerroristNearby = false;
+ float range;
if (GetClosestPlayerByTravelDistance(TERRORIST, &range))
{
const float nearbyTerroristRange = 2000.0f;
@@ -783,45 +1064,206 @@ void CHostageImprov::CheckForNearbyTerrorists(void)
}
/* <4753ba> ../cstrike/dlls/hostage/hostage_improv.cpp:1440 */
-NOBODY void CHostageImprov::UpdateGrenadeReactions(void)
+void CHostageImprov::UpdateGrenadeReactions(void)
{
-// IsElapsed(const class CountdownTimer *const this); // 1442
-// {
-// class CBaseEntity *entity; // 1458
-// float const watchGrenadeRadius; // 1459
-// Start(CountdownTimer *const this,
-// float duration); // 1456
-// FClassnameIs(entvars_t *pev,
-// const char *szClassname); // 1464
-// {
-// class CGrenade *grenade; // 1466
-// OnInjury(HostageIdleState *const this,
-// float amount); // 1480
-// Start(CountdownTimer *const this,
-// float duration); // 1489
-// }
-// }
-// Start(CountdownTimer *const this,
-// float duration); // 1447
+ if (m_coughTimer.IsElapsed())
+ {
+ if (TheBots->IsInsideSmokeCloud(&GetCentroid()))
+ {
+ m_coughTimer.Start(RANDOM_FLOAT(1, 3));
+ Chatter(HOSTAGE_CHATTER_COUGH);
+ Frighten(SCARED);
+ }
+ }
+
+ if (m_grenadeTimer.IsElapsed())
+ {
+ CBaseEntity *entity = NULL;
+ const float watchGrenadeRadius = 500.0f;
+
+ m_grenadeTimer.Start(RANDOM_FLOAT(0.4, 0.6));
+
+ while ((entity = UTIL_FindEntityInSphere(entity, GetCentroid(), watchGrenadeRadius)) != NULL)
+ {
+ CGrenade *grenade = static_cast(entity);
+
+ if (!FClassnameIs(grenade->pev, "grenade") || grenade->m_SGSmoke > 1)
+ continue;
+
+ if (IsVisible(grenade->Center()))
+ {
+ Chatter(HOSTAGE_CHATTER_SAW_HE_GRENADE);
+
+ if (grenade->pev->dmg > 50.0f)
+ {
+ m_idleState.OnInjury();
+ Frighten(TERRIFIED);
+ }
+ else
+ Frighten(SCARED);
+
+ m_grenadeTimer.Start(10);
+ break;
+ }
+ }
+ }
}
/* <475ce3> ../cstrike/dlls/hostage/hostage_improv.cpp:1502 */
-NOBODY void CHostageImprov::__MAKE_VHOOK(OnUpdate)(float deltaT)
+void CHostageImprov::__MAKE_VHOOK(OnUpdate)(float deltaT)
{
-// {
-// float const runSpeed; // 1553
-// float const walkSpeed; // 1554
-// float const fallVelocity; // 1560
-// float const safeTime; // 1687
-// {
-// float dot; // 1621
-// {
-// float speed; // 1632
-// }
-// }
-// }
-// OnUpdate(CHostageImprov *const this,
-// float deltaT); // 1502
+ if (!IsAlive() || cv_hostage_stop.value > 0.0f)
+ return;
+
+ if (m_blinkTimer.IsElapsed())
+ {
+ if (m_scaredTimer.IsElapsed() && m_animateState.GetPerformance() != HostageAnimateState::Afraid)
+ {
+ m_blinkTimer.Start(RANDOM_FLOAT(3, 10));
+ m_blinkCounter = RANDOM_LONG(2, 4);
+ }
+ else
+ {
+ m_blinkTimer.Start(RANDOM_FLOAT(0.5, 2.0));
+ m_blinkCounter = RANDOM_LONG(1, 2);
+
+ }
+ }
+
+ if (m_blinkCounter)
+ {
+ m_hostage->pev->body = 1;
+ --m_blinkCounter;
+ }
+ else
+ {
+ m_hostage->pev->body = 0;
+ }
+
+ UpdateGrenadeReactions();
+ UpdateDelayedChatter();
+ UpdateVision();
+
+ m_behavior.Update();
+
+ m_actualVel.x = m_hostage->pev->origin.x - m_lastPosition.x;
+ m_actualVel.y = m_hostage->pev->origin.y - m_lastPosition.y;
+
+ const float runSpeed = 289.0f;
+ const float walkSpeed = 9.0f;
+ const float fallVelocity = -1000.0f;
+ const float safeTime = 0.4f;
+
+ if (IsOnGround())
+ {
+ if (IsCrouching())
+ {
+ if (m_actualVel.LengthSquared() > 9.0f)
+ {
+ if (m_animateState.GetPerformance() != HostageAnimateState::CrouchWalk)
+ {
+ m_animateState.Reset();
+ m_animateState.SetPerformance(HostageAnimateState::CrouchWalk);
+
+ ClearLookAt();
+ if (m_scaredTimer.IsElapsed() && m_animateState.GetPerformance() != HostageAnimateState::Afraid)
+ m_animateState.AddSequence(this, ACT_CROUCH_WALK, 99.9, 2.0);
+ else
+ m_animateState.AddSequence(this, ACT_CROUCH_WALK_SCARED, 99.9, 2.0);
+ }
+ }
+ else if (m_animateState.GetPerformance() != HostageAnimateState::Crouch)
+ {
+ m_animateState.Reset();
+ m_animateState.SetPerformance(HostageAnimateState::Crouch);
+
+ if (m_scaredTimer.IsElapsed())
+ m_animateState.AddSequence(this, ACT_CROUCH_IDLE, 99.9);
+ else
+ m_animateState.AddSequence(this, ACT_CROUCH_IDLE_SCARED);
+ }
+ }
+ else
+ {
+ UTIL_MakeVectors(m_hostage->pev->angles);
+
+ float dot = DotProduct2D(gpGlobals->v_forward, m_actualVel);
+
+ if (dot < -3.0f)
+ {
+ if (m_animateState.GetPerformance() != HostageAnimateState::Walk)
+ {
+ m_animateState.Reset();
+ m_animateState.SetPerformance(HostageAnimateState::Walk);
+ ClearLookAt();
+
+ float speed;
+ if (m_actualVel.LengthSquared() > runSpeed)
+ speed = 2.0f;
+ else
+ speed = 1.0f;
+
+ m_animateState.AddSequence(this, ACT_WALK_BACK, 99.9, speed);
+ }
+ }
+ else
+ {
+ if (m_actualVel.LengthSquared() > runSpeed)
+ {
+ if (m_animateState.GetPerformance() != HostageAnimateState::Run)
+ {
+ m_animateState.Reset();
+ m_animateState.SetPerformance(HostageAnimateState::Run);
+ ClearLookAt();
+
+ if (m_scaredTimer.IsElapsed() && m_animateState.GetPerformance() != HostageAnimateState::Afraid && !m_behavior.IsState(&m_escapeState))
+ m_animateState.AddSequence(this, ACT_RUN, 99.9, 2.0);
+ else
+ m_animateState.AddSequence(this, ACT_RUN_SCARED, 99.9, 2.0);
+ }
+ }
+ else if (m_actualVel.LengthSquared() > walkSpeed)
+ {
+ if (m_animateState.GetPerformance() != HostageAnimateState::Walk)
+ {
+ m_animateState.Reset();
+ m_animateState.SetPerformance(HostageAnimateState::Walk);
+ ClearLookAt();
+
+ if (m_behavior.IsState(&m_escapeState))
+ {
+ m_animateState.AddSequence(this, ACT_WALK_SNEAKY, 99.9, 1.5);
+ }
+ else if (m_scaredTimer.IsElapsed() && m_animateState.GetPerformance() != HostageAnimateState::Afraid)
+ {
+ m_animateState.AddSequence(this, ACT_WALK, 99.9, 1.5);
+ }
+ else
+ m_animateState.AddSequence(this, ACT_WALK_SCARED, 99.9, 1.5);
+ }
+ }
+ else
+ {
+ if (m_animateState.GetPerformance() == HostageAnimateState::Walk || m_animateState.GetPerformance() == HostageAnimateState::Run)
+ m_animateState.Reset();
+
+ UpdateStationaryAnimation();
+ }
+ }
+ }
+ }
+ else if (m_hostage->pev->velocity.z < fallVelocity && m_animateState.GetPerformance() != HostageAnimateState::Fall)
+ {
+ m_animateState.Reset();
+ m_animateState.SetPerformance(HostageAnimateState::Fall);
+ m_animateState.AddSequence(this, ACT_FALL, 99.9);
+ }
+
+ if (!m_collisionTimer.HasStarted() || m_collisionTimer.IsGreaterThen(safeTime))
+ SetKnownGoodPosition(m_lastPosition);
+
+ m_lastPosition = m_hostage->pev->origin;
+ m_animateState.OnUpdate(this);
}
/* <47552a> ../cstrike/dlls/hostage/hostage_improv.cpp:1705 */
@@ -842,18 +1284,18 @@ void CHostageImprov::__MAKE_VHOOK(OnGameEvent)(GameEventType event, CBaseEntity
}
case EVENT_PLAYER_DIED:
case EVENT_HOSTAGE_KILLED:
- if (IsVisible(entity->pev->origin, true))
- {
- Frighten(TERRIFIED);
-
- if (!entity->IsPlayer() || entity->IsPlayer() && ((CBasePlayer *)entity)->m_iTeam != TERRORIST)
- {
- DelayedChatter(RANDOM_FLOAT(0.5, 0.7), HOSTAGE_CHATTER_SCARED_OF_MURDER, true);
- }
- if (!entity->IsPlayer())
- {
- m_idleState.OnInjury(0);
- }
+ if (IsVisible(entity->pev->origin, true))
+ {
+ Frighten(TERRIFIED);
+
+ if (!entity->IsPlayer() || entity->IsPlayer() && ((CBasePlayer *)entity)->m_iTeam != TERRORIST)
+ {
+ DelayedChatter(RANDOM_FLOAT(0.5, 0.7), HOSTAGE_CHATTER_SCARED_OF_MURDER, true);
+ }
+ if (!entity->IsPlayer())
+ {
+ m_idleState.OnInjury();
+ }
}
break;
case EVENT_HOSTAGE_RESCUED:
@@ -862,7 +1304,7 @@ void CHostageImprov::__MAKE_VHOOK(OnGameEvent)(GameEventType event, CBaseEntity
if (!entity)
return;
- Chatter(HOSTAGE_CHATTER_RESCUED);
+ Chatter(HOSTAGE_CHATTER_RESCUED, false);
}
break;
case EVENT_TERRORISTS_WIN:
@@ -882,7 +1324,7 @@ void CHostageImprov::__MAKE_VHOOK(OnGameEvent)(GameEventType event, CBaseEntity
float range;
PriorityType priority;
bool isHostile;
-
+
if (entity != NULL && IsGameEventAudible(event, entity, other, &range, &priority, &isHostile))
{
const float fudge = 0.4f;
@@ -934,125 +1376,126 @@ void CHostageImprov::__MAKE_VHOOK(OnGameEvent)(GameEventType event, CBaseEntity
/* <471e27> ../cstrike/dlls/hostage/hostage_improv.cpp:1854 */
void CHostageImprov::__MAKE_VHOOK(OnTouch)(CBaseEntity *other)
-{
- const char *classname;
- Vector2D to;
- const float pushForce = 20.0f;
-
- classname = STRING(other->pev->classname);
-
- if (cv_hostage_debug.value != 0.0)
- {
- CONSOLE_ECHO("%5.1f: Hostage hit '%s'\n", gpGlobals->time, classname);
- }
-
- m_collisionTimer.Start();
-
- if (FStrEq(classname, "worldspawn"))
- {
- const float lookAheadRange = 30.0f;
- float ground;
- Vector normal = Vector(0, 0, 1);
- Vector alongFloor;
- TraceResult result;
- bool isStep = false;
-
- UTIL_MakeVectors(m_hostage->pev->angles);
-
- if (!GetSimpleGroundHeightWithFloor(&GetEyes(), &ground, &normal))
- return;
-
- if (cv_hostage_debug.value < 0.0)
- {
- UTIL_DrawBeamPoints(GetFeet() + normal * 50, GetFeet(), 2, 255, 255, 0);
- }
-
- alongFloor = CrossProduct(normal, gpGlobals->v_right);
-
- Vector pos = alongFloor * lookAheadRange;
-
- for (float offset = 1.0f; offset <= 18.0f; offset += 3.0f)
- {
- Vector vecStart = GetFeet();
- vecStart.z += offset;
-
- UTIL_TraceLine(vecStart, vecStart + pos, ignore_monsters, dont_ignore_glass, m_hostage->pev->pContainingEntity, &result);
-
- if (result.flFraction < 1.0f && result.vecPlaneNormal[2] < 0.7f)
- {
- isStep = true;
- break;
- }
- }
-
- if (isStep)
- {
- float stepAheadGround = pos.z;
- Vector stepAheadNormal = Vector(0, 0, stepAheadGround);
-
- m_inhibitObstacleAvoidance.Start(0.5);
-
- for (float range = 1.0f; range <= 30.5f; range += 5.0f)
- {
- Vector stepAhead = GetFeet() + alongFloor * range;
-
- if (GetSimpleGroundHeightWithFloor(&stepAhead, &stepAheadGround, &stepAheadNormal))
- {
- float dz = stepAheadGround - GetFeet().z;
-
- if (dz > 0.0f && dz < 18.0f)
- {
- m_hostage->pev->origin.z = stepAheadGround + 3.0f;
- break;
- }
- }
- }
- }
- else if (!IsMoving() && !IsUsingLadder())
- {
- bool isSeam = false;
- const float checkSeamRange = 50.0f;
- Vector posBehind;
-
- posBehind = GetEyes() - alongFloor * checkSeamRange;
- UTIL_TraceLine(posBehind, posBehind - Vector(0, 0, 9999), ignore_monsters, dont_ignore_glass, m_hostage->pev->pContainingEntity, &result);
-
- if (result.flFraction < 1.0f && DotProduct(result.vecPlaneNormal, normal) < 1.0f)
- {
- isSeam = true;
- }
- else
- {
- Vector posAhead = GetEyes() + alongFloor * checkSeamRange;
- UTIL_TraceLine(posAhead, posAhead - Vector(0, 0, 9999), ignore_monsters, dont_ignore_glass, m_hostage->pev->pContainingEntity, &result);
-
- if (result.flFraction < 1.0f && DotProduct(result.vecPlaneNormal, normal) < 1.0f)
- isSeam = true;
- }
-
- if (isSeam)
- {
- if (cv_hostage_debug.value != 0.0)
- {
- CONSOLE_ECHO("Hostage stuck on seam.\n");
- }
-
- const float nudge = 3.0f;
- m_hostage->pev->origin.z += nudge;
- }
- }
- }
- else if (FStrEq(classname, "func_breakable"))
- {
- other->TakeDamage(m_hostage->pev, m_hostage->pev, 9999.9, DMG_BULLET);
- }
- else if (other->IsPlayer() || FClassnameIs(other->pev, "hostage_entity"))
- {
- to = (m_hostage->pev->origin - other->pev->origin).Make2D();
- to.NormalizeInPlace();
-
- m_vel.x += to.x * pushForce;
- m_vel.y += to.y * pushForce;
+{
+ const char *classname;
+ Vector2D to;
+ const float pushForce = 20.0f;
+
+ classname = STRING(other->pev->classname);
+
+ if (cv_hostage_debug.value != 0.0)
+ {
+ CONSOLE_ECHO("%5.1f: Hostage hit '%s'\n", gpGlobals->time, classname);
+ }
+
+ m_collisionTimer.Start();
+
+ if (FStrEq(classname, "worldspawn"))
+ {
+ const float lookAheadRange = 30.0f;
+ float ground;
+ Vector normal = Vector(0, 0, 1);
+ Vector alongFloor;
+ TraceResult result;
+ bool isStep = false;
+
+ UTIL_MakeVectors(m_hostage->pev->angles);
+
+ if (!GetSimpleGroundHeightWithFloor(&GetEyes(), &ground, &normal))
+ return;
+
+ if (cv_hostage_debug.value < 0.0)
+ {
+ UTIL_DrawBeamPoints(GetFeet() + normal * 50, GetFeet(), 2, 255, 255, 0);
+ }
+
+ alongFloor = CrossProduct(normal, gpGlobals->v_right);
+
+ Vector pos = alongFloor * lookAheadRange;
+
+ for (double offset = 1.0f; offset <= 18.0f; offset += 3.0f)
+ {
+ Vector vecStart = GetFeet();
+ vecStart.z += offset;
+
+ UTIL_TraceLine(vecStart, vecStart + pos, ignore_monsters, dont_ignore_glass, m_hostage->pev->pContainingEntity, &result);
+
+ if (result.flFraction < 1.0f && result.vecPlaneNormal[2] < 0.7f)
+ {
+ isStep = true;
+ break;
+ }
+ }
+
+ if (isStep)
+ {
+ float stepAheadGround = pos.z;
+ Vector stepAheadNormal = Vector(0, 0, stepAheadGround);
+
+ m_inhibitObstacleAvoidance.Start(0.5);
+
+ for (float range = 1.0f; range <= 30.5f; range += 5.0f)
+ {
+ Vector stepAhead = GetFeet() + alongFloor * range;
+ stepAhead.z = GetEyes().z;
+
+ if (GetSimpleGroundHeightWithFloor(&stepAhead, &stepAheadGround, &stepAheadNormal))
+ {
+ float dz = stepAheadGround - GetFeet().z;
+
+ if (dz > 0.0f && dz < 18.0f)
+ {
+ m_hostage->pev->origin.z = stepAheadGround + 3.0f;
+ break;
+ }
+ }
+ }
+ }
+ else if (!IsMoving() && !IsUsingLadder())
+ {
+ bool isSeam = false;
+ const float checkSeamRange = 50.0f;
+ Vector posBehind;
+
+ posBehind = GetEyes() - alongFloor * checkSeamRange;
+ UTIL_TraceLine(posBehind, posBehind - Vector(0, 0, 9999), ignore_monsters, dont_ignore_glass, m_hostage->pev->pContainingEntity, &result);
+
+ if (result.flFraction < 1.0f && DotProduct(result.vecPlaneNormal, normal) < 1.0f)
+ {
+ isSeam = true;
+ }
+ else
+ {
+ Vector posAhead = GetEyes() + alongFloor * checkSeamRange;
+ UTIL_TraceLine(posAhead, posAhead - Vector(0, 0, 9999), ignore_monsters, dont_ignore_glass, m_hostage->pev->pContainingEntity, &result);
+
+ if (result.flFraction < 1.0f && DotProduct(result.vecPlaneNormal, normal) < 1.0f)
+ isSeam = true;
+ }
+
+ if (isSeam)
+ {
+ if (cv_hostage_debug.value != 0.0)
+ {
+ CONSOLE_ECHO("Hostage stuck on seam.\n");
+ }
+
+ const float nudge = 3.0f;
+ m_hostage->pev->origin.z += nudge;
+ }
+ }
+ }
+ else if (FStrEq(classname, "func_breakable"))
+ {
+ other->TakeDamage(m_hostage->pev, m_hostage->pev, 9999.9, DMG_BULLET);
+ }
+ else if (other->IsPlayer() || FClassnameIs(other->pev, "hostage_entity"))
+ {
+ to = (m_hostage->pev->origin - other->pev->origin).Make2D();
+ to.NormalizeInPlace();
+
+ m_vel.x += to.x * pushForce;
+ m_vel.y += to.y * pushForce;
}
}
@@ -1064,13 +1507,13 @@ void CHostageImprov::ApplyForce(Vector force)
}
/* <474bd5> ../cstrike/dlls/hostage/hostage_improv.cpp:2016 */
-bool CHostageImprov::IsAtHome(void)
+bool CHostageImprov::IsAtHome(void) const
{
return m_hostage->IsAtHome();
}
/* <474c76> ../cstrike/dlls/hostage/hostage_improv.cpp:2025 */
-bool CHostageImprov::CanSeeRescueZone(void)
+bool CHostageImprov::CanSeeRescueZone(void) const
{
CCSBotManager *ctrl = TheCSBots();
@@ -1140,7 +1583,7 @@ float CHostageImprov::GetTimeSinceLastNoise(void)
}
/* <47503a> ../cstrike/dlls/hostage/hostage_improv.cpp:2117 */
-bool CHostageImprov::IsScared(void)
+bool CHostageImprov::IsScared(void) const
{
if (m_scaredTimer.IsElapsed())
{
@@ -1202,7 +1645,7 @@ void CHostageImprov::Afraid(void)
Q_sprintf(animInto, "cower_into_%d", which);
Q_sprintf(animLoop, "cower_loop_%d", which);
Q_sprintf(animExit, "cower_exit_%d", which);
-
+
m_animateState.AddSequence(this, animInto);
m_animateState.AddSequence(this, animLoop, RANDOM_FLOAT(3, 10));
m_animateState.AddSequence(this, animExit);
@@ -1264,7 +1707,7 @@ void CHostageImprov::DelayedChatter(float delayTime, HostageChatterType sayType,
}
/* <475bd4> ../cstrike/dlls/hostage/hostage_improv.cpp:2268 */
-NOXREF void CHostageImprov::UpdateDelayedChatter(void)
+void CHostageImprov::UpdateDelayedChatter(void)
{
if (!m_isDelayedChatterPending)
return;
@@ -1277,7 +1720,7 @@ NOXREF void CHostageImprov::UpdateDelayedChatter(void)
switch (m_delayedChatterType)
{
case HOSTAGE_CHATTER_SCARED_OF_GUNFIRE:
- if (RANDOM_FLOAT(0, 100) < 25)
+ if (RANDOM_FLOAT(0, 100) <= 25)
{
Chatter(m_delayedChatterType, m_delayedChatterMustSpeak);
}
@@ -1285,7 +1728,7 @@ NOXREF void CHostageImprov::UpdateDelayedChatter(void)
case HOSTAGE_CHATTER_LOOK_OUT:
case HOSTAGE_CHATTER_PLEASE_RESCUE_ME:
case HOSTAGE_CHATTER_IMPATIENT_FOR_RESCUE:
- if (RANDOM_FLOAT(0, 100) < 60)
+ if (RANDOM_FLOAT(0, 100) <= 60)
{
Chatter(m_delayedChatterType, m_delayedChatterMustSpeak);
}
@@ -1401,13 +1844,13 @@ void CHostageImprov::Wiggle(void)
default:
break;
}
-
- if (m_follower.GetStuckDuration() > minStuckJumpTime && m_wiggleJumpTimer.IsElapsed())
- {
- if (Jump())
- {
- m_wiggleJumpTimer.Start(RANDOM_FLOAT(0.75, 1.2));
- }
+
+ if (m_follower.GetStuckDuration() > minStuckJumpTime && m_wiggleJumpTimer.IsElapsed())
+ {
+ if (Jump())
+ {
+ m_wiggleJumpTimer.Start(RANDOM_FLOAT(0.75, 1.2));
+ }
}
}
@@ -1509,6 +1952,17 @@ void CHostageImprov::UpdateStationaryAnimation(void)
#ifdef HOOK_GAMEDLL
+// NavAreaBuildPath hook
+bool NavAreaBuildPath__HostagePathCost__wrapper(CNavArea *startArea, CNavArea *goalArea, const Vector *goalPos, class HostagePathCost &costFunc, CNavArea **closestArea)
+{
+ return NavAreaBuildPath(startArea, goalArea, goalPos, costFunc, closestArea);
+}
+
+// NavAreaBuildPath hook
+bool NavAreaBuildPath__ShortestPathCost__wrapper(CNavArea *startArea, CNavArea *goalArea, const Vector *goalPos, class ShortestPathCost &costFunc, CNavArea **closestArea)
+{
+ return NavAreaBuildPath(startArea, goalArea, goalPos, costFunc, closestArea);
+}
void CHostageImprov::OnMoveToFailure(const Vector &goal, MoveToFailureType reason)
{
diff --git a/regamedll/dlls/hostage/hostage_improv.h b/regamedll/dlls/hostage/hostage_improv.h
index 06143ca6..633497ee 100644
--- a/regamedll/dlls/hostage/hostage_improv.h
+++ b/regamedll/dlls/hostage/hostage_improv.h
@@ -32,6 +32,7 @@
#pragma once
#endif
+#include "hostage/hostage.h"
#include "hostage/hostage_states.h"
class CHostage;
@@ -40,478 +41,607 @@ enum HostageChatterType;
class CHostageImprov: public CImprov
{
public:
- //CHostageImprov(void) {};
CHostageImprov(CBaseEntity *entity);
- ~CHostageImprov(void)
- {
- //~HostageAnimateState(); // 49
- //~HostageFollowState(); // 49
- //~HostageRetreatState(); // 49
- //~HostageEscapeState(); // 49
- //~HostageIdleState(); // 49
- //~CImprov(); // 49
- };
+ ~CHostageImprov(void) {};
- NOBODY virtual void OnMoveToSuccess(const Vector &goal)
- {
- //if (m_behavior.IsState(NULL))
- // IImprovEvent::OnMoveToSuccess(goal);
- }
- virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason);
- NOBODY virtual void OnInjury(float amount)
+ virtual void OnMoveToSuccess(const Vector &goal)
+ {
+ m_behavior.OnMoveToSuccess(goal);
+ }
+ virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason);
+ virtual void OnInjury(float amount)
+ {
+ m_behavior.OnInjury(amount);
+
+ m_lastInjuryTimer.Start();
+ Frighten(TERRIFIED);
+ }
+ virtual bool IsAlive(void) const;
+ virtual void MoveTo(const Vector &goal);
+ virtual void LookAt(const Vector &target);
+ virtual void ClearLookAt(void);
+ virtual void FaceTo(const Vector &goal);
+ virtual void ClearFaceTo(void);
+ virtual bool IsAtMoveGoal(float error = 20.0f) const;
+ virtual bool HasLookAt(void) const
+ {
+ return m_isLookingAt;
+ }
+ virtual bool HasFaceTo(void) const
+ {
+ return m_isFacingTo;
+ }
+ virtual bool IsAtFaceGoal(void) const;
+ virtual bool IsFriendInTheWay(const Vector &goalPos) const;
+ virtual bool IsFriendInTheWay(CBaseEntity *myFriend, const Vector &goalPos) const;
+ virtual void MoveForward(void)
+ {
+ m_moveFlags |= IN_FORWARD;
+ }
+ virtual void MoveBackward(void)
+ {
+ m_moveFlags |= IN_BACK;
+ }
+ virtual void StrafeLeft(void)
+ {
+ m_moveFlags |= IN_MOVELEFT;
+ }
+ virtual void StrafeRight(void)
+ {
+ m_moveFlags |= IN_MOVERIGHT;
+ }
+
+ #define HOSTAGE_MUST_JUMP true
+ virtual bool Jump(void);
+
+ virtual void Crouch(void);
+ virtual void StandUp(void);
+ virtual void TrackPath(const Vector &pathGoal, float deltaT);
+ virtual void StartLadder(const CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos);
+ virtual bool TraverseLadder(const CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos, float deltaT);
+ virtual bool GetSimpleGroundHeightWithFloor(const Vector *pos, float *height, Vector *normal = NULL);
+ virtual void Run(void);
+ virtual void Walk(void);
+ virtual void Stop(void);
+ virtual float GetMoveAngle(void) const
+ {
+ return m_moveAngle;
+ }
+ virtual float GetFaceAngle(void) const
+ {
+ return m_moveAngle;
+ }
+ virtual const Vector &GetFeet(void) const;
+ virtual const Vector &GetCentroid(void) const;
+ virtual const Vector &GetEyes(void) const;
+ virtual bool IsRunning(void) const
+ {
+ return (m_moveType == Running);
+ }
+ virtual bool IsWalking(void) const
+ {
+ return (m_moveType == Walking);
+ }
+ virtual bool IsStopped(void) const
+ {
+ return (m_moveType == Stopped);
+ }
+ virtual bool IsCrouching(void) const
+ {
+ return m_isCrouching;
+ }
+ virtual bool IsJumping(void) const
+ {
+ return (m_jumpTimer.IsElapsed() == false);
+ }
+ virtual bool IsUsingLadder(void) const
+ {
+ return false;
+ }
+ virtual bool IsOnGround(void) const;
+ virtual bool IsMoving(void) const;
+ virtual bool CanRun(void) const
+ {
+ return true;
+ }
+ virtual bool CanCrouch(void) const
+ {
+ return true;
+ }
+ virtual bool CanJump(void) const
+ {
+ return true;
+ }
+ virtual bool IsVisible(const Vector &pos, bool testFOV = false) const;
+ virtual bool IsPlayerLookingAtMe(CBasePlayer *other, float cosTolerance = 0.95f) const;
+ virtual CBasePlayer *IsAnyPlayerLookingAtMe(int team = 0, float cosTolerance = 0.95f) const;
+ virtual CBasePlayer *GetClosestPlayerByTravelDistance(int team = 0, float *range = NULL) const;
+ virtual CNavArea *GetLastKnownArea(void) const
+ {
+ return m_lastKnownArea;
+ }
+ virtual void OnUpdate(float deltaT);
+ virtual void OnUpkeep(float deltaT);
+ virtual void OnReset(void);
+ virtual void OnGameEvent(GameEventType event, CBaseEntity *entity = NULL, CBaseEntity *other = NULL);
+ virtual void OnTouch(CBaseEntity *other);
+
+#ifdef HOOK_GAMEDLL
+
+ void OnMoveToSuccess_(const Vector &goal)
+ {
+ //if (m_behavior.IsState(NULL))
+ // IImprovEvent::OnMoveToSuccess(goal);
+ }
+ void OnMoveToFailure_(const Vector &goal, MoveToFailureType reason);
+ void OnInjury_(float amount)
{
//m_behavior.Update();
//m_lastInjuryTimer.Start();
}
- NOBODY virtual bool IsAlive(void) const;
- NOBODY virtual void MoveTo(const Vector &goal);
- NOBODY virtual void LookAt(const Vector &target);
- NOBODY virtual void ClearLookAt(void);
- NOBODY virtual void FaceTo(const Vector &goal);
- NOBODY virtual void ClearFaceTo(void);
- NOBODY virtual bool IsAtMoveGoal(float error = 20.0f) const;
- virtual bool HasLookAt(void) const
- {
- return m_isLookingAt;
- }
- virtual bool HasFaceTo(void) const
- {
- return m_isFacingTo;
- }
- NOBODY virtual bool IsAtFaceGoal(void) const;
- NOBODY virtual bool IsFriendInTheWay(const Vector &goalPos) const;
- NOBODY virtual bool IsFriendInTheWay(CBaseEntity *myFriend, const Vector &goalPos) const;
- virtual void MoveForward(void)
- {
- m_moveFlags |= IN_FORWARD;
- }
- virtual void MoveBackward(void)
- {
- m_moveFlags |= IN_BACK;
- }
- virtual void StrafeLeft(void)
- {
- m_moveFlags |= IN_MOVELEFT;
- }
- virtual void StrafeRight(void)
- {
- m_moveFlags |= IN_MOVERIGHT;
- }
-
- #define HOSTAGE_MUST_JUMP true
- virtual bool Jump(void);
-
- virtual void Crouch(void);
- virtual void StandUp(void);
- NOBODY virtual void TrackPath(const Vector &pathGoal, float deltaT);
- NOBODY virtual void StartLadder(const CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos);
- NOBODY virtual bool TraverseLadder(const CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos, float deltaT);
- NOBODY virtual bool GetSimpleGroundHeightWithFloor(const Vector *pos, float *height, Vector *normal = NULL);
- NOBODY virtual void Run(void);
- NOBODY virtual void Walk(void);
- NOBODY virtual void Stop(void);
- virtual float GetMoveAngle(void) const
- {
- return m_moveAngle;
- }
- virtual float GetFaceAngle(void) const
- {
- return m_moveAngle;
- }
- virtual const Vector &GetFeet(void) const;
- virtual const Vector &GetCentroid(void) const;
- virtual const Vector &GetEyes(void) const;
- virtual bool IsRunning(void) const
- {
- return (m_moveType == Running);
- }
- virtual bool IsWalking(void) const
- {
- return (m_moveType == Walking);
- }
- virtual bool IsStopped(void) const
- {
- return (m_moveType == Stopped);
- }
- virtual bool IsCrouching(void) const
- {
- return m_isCrouching;
- }
- virtual bool IsJumping(void) const
- {
- UNTESTED
- return (m_jumpTimer.IsElapsed() == false);
- }
- virtual bool IsUsingLadder(void) const
- {
- return false;
- }
- NOBODY virtual bool IsOnGround(void) const;
- NOBODY virtual bool IsMoving(void) const;
- virtual bool CanRun(void) const
- {
- return true;
- }
- virtual bool CanCrouch(void) const
- {
- return true;
- }
- virtual bool CanJump(void) const
- {
- return true;
- }
- NOBODY virtual bool IsVisible(const Vector &pos, bool testFOV = false) const;
- NOBODY virtual bool IsPlayerLookingAtMe(CBasePlayer *other, float cosTolerance = 0.95f) const;
- NOBODY virtual CBasePlayer *IsAnyPlayerLookingAtMe(int team = 0, float cosTolerance = 0.95f) const;
- NOBODY virtual CBasePlayer *GetClosestPlayerByTravelDistance(int team = 0, float *range = NULL) const;
- virtual CNavArea *GetLastKnownArea(void) const
- {
- return m_lastKnownArea;
- }
- NOBODY virtual void OnUpdate(float deltaT);
- NOBODY virtual void OnUpkeep(float deltaT);
- virtual void OnReset(void);
- NOBODY virtual void OnGameEvent(GameEventType event, CBaseEntity *entity = NULL, CBaseEntity *other = NULL);
- NOBODY virtual void OnTouch(CBaseEntity *other);
-
-#ifdef HOOK_GAMEDLL
-
- void OnMoveToSuccess_(const Vector &goal)
- {
- //if (m_behavior.IsState(NULL))
- // IImprovEvent::OnMoveToSuccess(goal);
- }
- void OnMoveToFailure_(const Vector &goal, MoveToFailureType reason);
- void OnInjury_(float amount)
- {
- //m_behavior.Update();
- //m_lastInjuryTimer.Start();
- }
- bool IsAlive_(void) const;
- void MoveTo_(const Vector &goal);
- void LookAt_(const Vector &target);
- void ClearLookAt_(void);
- void FaceTo_(const Vector &goal);
- void ClearFaceTo_(void);
- bool IsAtMoveGoal_(float error = 20.0f) const;
- bool IsAtFaceGoal_(void) const;
- bool IsFriendInTheWay_(const Vector &goalPos) const;
- bool IsFriendInTheWay_(CBaseEntity *myFriend, const Vector &goalPos) const;
- bool Jump_(void);
- void Crouch_(void);
- void StandUp_(void);
- void TrackPath_(const Vector &pathGoal, float deltaT);
- void StartLadder_(const CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos);
- bool TraverseLadder_(const CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos, float deltaT);
- bool GetSimpleGroundHeightWithFloor_(const Vector *pos, float *height, Vector *normal = NULL);
- void Run_(void);
- void Walk_(void);
- void Stop_(void);
- const Vector &GetFeet_(void) const;
- const Vector &GetCentroid_(void) const;
- const Vector &GetEyes_(void) const;
- bool IsOnGround_(void) const;
- bool IsMoving_(void) const;
- bool IsVisible_(const Vector &pos, bool testFOV = false) const;
- bool IsPlayerLookingAtMe_(CBasePlayer *other, float cosTolerance = 0.95f) const;
- CBasePlayer *IsAnyPlayerLookingAtMe_(int team = 0, float cosTolerance = 0.95f) const;
- CBasePlayer *GetClosestPlayerByTravelDistance_(int team = 0, float *range = NULL) const;
- void OnUpdate_(float deltaT);
- void OnUpkeep_(float deltaT);
- void OnReset_(void);
- void OnGameEvent_(GameEventType event, CBaseEntity *entity = NULL, CBaseEntity *other = NULL);
+ bool IsAlive_(void) const;
+ void MoveTo_(const Vector &goal);
+ void LookAt_(const Vector &target);
+ void ClearLookAt_(void);
+ void FaceTo_(const Vector &goal);
+ void ClearFaceTo_(void);
+ bool IsAtMoveGoal_(float error = 20.0f) const;
+ bool IsAtFaceGoal_(void) const;
+ bool IsFriendInTheWay_(const Vector &goalPos) const;
+ bool IsFriendInTheWay_(CBaseEntity *myFriend, const Vector &goalPos) const;
+ bool Jump_(void);
+ void Crouch_(void);
+ void StandUp_(void);
+ void TrackPath_(const Vector &pathGoal, float deltaT);
+ void StartLadder_(const CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos);
+ bool TraverseLadder_(const CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos, float deltaT);
+ bool GetSimpleGroundHeightWithFloor_(const Vector *pos, float *height, Vector *normal = NULL);
+ void Run_(void);
+ void Walk_(void);
+ void Stop_(void);
+ const Vector &GetFeet_(void) const;
+ const Vector &GetCentroid_(void) const;
+ const Vector &GetEyes_(void) const;
+ bool IsOnGround_(void) const;
+ bool IsMoving_(void) const;
+ bool IsVisible_(const Vector &pos, bool testFOV = false) const;
+ bool IsPlayerLookingAtMe_(CBasePlayer *other, float cosTolerance = 0.95f) const;
+ CBasePlayer *IsAnyPlayerLookingAtMe_(int team = 0, float cosTolerance = 0.95f) const;
+ CBasePlayer *GetClosestPlayerByTravelDistance_(int team = 0, float *range = NULL) const;
+ void OnUpdate_(float deltaT);
+ void OnUpkeep_(float deltaT);
+ void OnReset_(void);
+ void OnGameEvent_(GameEventType event, CBaseEntity *entity = NULL, CBaseEntity *other = NULL);
void OnTouch_(CBaseEntity *other);
#endif // HOOK_GAMEDLL
public:
-
- enum MoveType
- {
- Stopped = 0,
- Walking,
- Running,
- };
-
- enum ScareType
- {
- NERVOUS = 0,
- SCARED,
- TERRIFIED,
- };
-
- void FaceOutwards(void);
- bool IsFriendInTheWay(void);
- void SetKnownGoodPosition(const Vector &pos);
- const Vector &GetKnownGoodPosition(void);
- void ResetToKnownGoodPosition(void);
- void ResetJump(void);
- void ApplyForce(Vector force);
- const Vector GetActualVelocity(void);
- void SetMoveLimit(MoveType limit)
- {
- m_moveLimit = limit;
- }
- MoveType GetMoveLimit(void)
- {
- return m_moveLimit;
- }
- CNavPath *GetPath(void);
- CNavPathFollower *GetPathFollower(void);
- void Idle(void)
+ enum MoveType
{
- m_behavior.SetState(&m_idleState);
- }
- bool IsIdle(void)
- {
- UNTESTED
- return m_behavior.IsState(&m_idleState);
- }
- void Follow(CBasePlayer *leader)
- {
- UNTESTED
- m_followState.SetLeader(leader);
- m_behavior.SetState(&m_followState);
- }
- bool IsFollowing(const CBaseEntity *leader = NULL)
- {
- UNTESTED
- return m_behavior.IsState(&m_followState);
- }
- void Escape(void);
- bool IsEscaping(void);
- void Retreat(void);
- bool IsRetreating(void);
- bool IsAtHome(void);
- bool CanSeeRescueZone(void);
- CBaseEntity *GetFollowLeader(void)
- {
- return m_followState.GetLeader();
- }
- CBasePlayer *GetClosestVisiblePlayer(int team);
- float GetTimeSinceLastSawPlayer(int team);
- float GetTimeSinceLastInjury(void);
- float GetTimeSinceLastNoise(void);
- bool IsTerroristNearby(void);
- void Frighten(ScareType scare);
- bool IsScared(void);
- ScareType GetScareIntensity(void)
- {
- return m_scareIntensity;
- }
- bool IsIgnoringTerrorists(void);
- float GetAggression(void);
- void Chatter(HostageChatterType sayType, bool mustSpeak = true);
- void DelayedChatter(float delayTime, HostageChatterType sayType, bool mustSpeak = false);
- NOXREF void UpdateDelayedChatter(void);
- bool IsTalking(void) const
- {
- return m_talkingTimer.IsElapsed();
- }
- void UpdateGrenadeReactions(void);
- void Afraid(void);
- void Wave(void);
- void Agree(void);
- void Disagree(void);
- void CrouchDie(void);
- void Flinch(Activity activity);
- void UpdateIdleActivity(Activity activity, Activity fidget);
- void UpdateStationaryAnimation(void);
- CHostage *GetEntity(void)
- {
- return m_hostage;
- }
- void CheckForNearbyTerrorists(void);
- void UpdatePosition(float);
- void MoveTowards(const Vector &pos, float deltaT);
- bool FaceTowards(const Vector &target, float deltaT);
- float GetSpeed(void);
- void SetMoveAngle(float angle)
- {
- m_moveAngle = angle;
- }
- void Wiggle(void);
- void ClearPath(void);
-
- #define HOSTAGE_ONLY_JUMP_DOWN true
- bool DiscontinuityJump(float ground, bool onlyJumpDown = false, bool mustJump = false);
-
+ Stopped = 0,
+ Walking,
+ Running,
+ };
+
+ enum ScareType
+ {
+ NERVOUS = 0,
+ SCARED,
+ TERRIFIED,
+ };
+
+ void FaceOutwards(void);
+ bool IsFriendInTheWay(void) const;
+ void SetKnownGoodPosition(const Vector &pos);
+ const Vector &GetKnownGoodPosition(void) const
+ {
+ return m_knownGoodPos;
+ }
+ void ResetToKnownGoodPosition(void);
+ void ResetJump(void)
+ {
+ if (m_hasJumpedIntoAir)
+ {
+ if (IsOnGround())
+ {
+ m_jumpTimer.Invalidate();
+ }
+ }
+ else if (!IsOnGround())
+ {
+ m_hasJumpedIntoAir = true;
+ }
+ }
+ void ApplyForce(Vector force);
+#ifdef PLAY_GAMEDLL
+ void ApplyForce2(float_precision x, float_precision y)
+ {
+ m_vel.x += x;
+ m_vel.y += y;
+ }
+#endif // PLAY_GAMEDLL
+ const Vector GetActualVelocity(void) const
+ {
+ return m_actualVel;
+ }
+ void SetMoveLimit(MoveType limit)
+ {
+ m_moveLimit = limit;
+ }
+ MoveType GetMoveLimit(void) const
+ {
+ return m_moveLimit;
+ }
+ CNavPath *GetPath(void)
+ {
+ return &m_path;
+ }
+ CNavPathFollower *GetPathFollower(void);
+ void Idle(void)
+ {
+ m_behavior.SetState(&m_idleState);
+ }
+ bool IsIdle(void) const
+ {
+ return m_behavior.IsState(&m_idleState);
+ }
+ void Follow(CBasePlayer *leader)
+ {
+ m_followState.SetLeader(leader);
+ m_behavior.SetState(&m_followState);
+ }
+ bool IsFollowing(const CBaseEntity *leader = NULL) const
+ {
+ return m_behavior.IsState(&m_followState);
+ }
+ void Escape(void)
+ {
+ m_behavior.SetState(&m_escapeState);
+ }
+ bool IsEscaping(void) const
+ {
+ return m_behavior.IsState(&m_escapeState);
+ }
+ void Retreat(void)
+ {
+ m_behavior.SetState(&m_retreatState);
+ }
+ bool IsRetreating(void) const
+ {
+ return m_behavior.IsState(&m_retreatState);
+ }
+ bool IsAtHome(void) const;
+ bool CanSeeRescueZone(void) const;
+ CBaseEntity *GetFollowLeader(void) const
+ {
+ return m_followState.GetLeader();
+ }
+ CBasePlayer *GetClosestVisiblePlayer(int team);
+ float GetTimeSinceLastSawPlayer(int team);
+ float GetTimeSinceLastInjury(void);
+ float GetTimeSinceLastNoise(void);
+ bool IsTerroristNearby(void);
+ void Frighten(ScareType scare);
+ bool IsScared(void) const;
+ ScareType GetScareIntensity(void) const
+ {
+ return m_scareIntensity;
+ }
+ bool IsIgnoringTerrorists(void) const
+ {
+ m_ignoreTerroristTimer.IsElapsed();
+ }
+ float GetAggression(void) const
+ {
+ return m_aggression;
+ }
+ void Chatter(HostageChatterType sayType, bool mustSpeak = true);
+ void DelayedChatter(float delayTime, HostageChatterType sayType, bool mustSpeak = false);
+ NOXREF void UpdateDelayedChatter(void);
+ bool IsTalking(void) const
+ {
+ return m_talkingTimer.IsElapsed();
+ }
+ void UpdateGrenadeReactions(void);
+ void Afraid(void);
+ void Wave(void);
+ void Agree(void);
+ void Disagree(void);
+ void CrouchDie(void);
+ void Flinch(Activity activity);
+ void UpdateIdleActivity(Activity activity, Activity fidget);
+ void UpdateStationaryAnimation(void);
+ CHostage *GetEntity(void) const
+ {
+ return m_hostage;
+ }
+ void CheckForNearbyTerrorists(void);
+ void UpdatePosition(float);
+ void MoveTowards(const Vector &pos, float deltaT);
+ bool FaceTowards(const Vector &target, float deltaT);
+ float GetSpeed(void);
+ void SetMoveAngle(float angle)
+ {
+ m_moveAngle = angle;
+ }
+ void Wiggle(void);
+ void ClearPath(void);
+
+ #define HOSTAGE_ONLY_JUMP_DOWN true
+ bool DiscontinuityJump(float ground, bool onlyJumpDown = false, bool mustJump = false);
void UpdateVision(void);
+
public:
- CountdownTimer m_coughTimer;
+ CountdownTimer m_coughTimer;
CountdownTimer m_grenadeTimer;
-/*private:*/
- CHostage *m_hostage;
- CNavArea *m_lastKnownArea;
- mutable Vector m_centroid;
- mutable Vector m_eye;
- HostageStateMachine m_behavior;
- HostageIdleState m_idleState;
- HostageEscapeState m_escapeState;
- HostageRetreatState m_retreatState;
- HostageFollowState m_followState;
- HostageAnimateState m_animateState;
- bool m_didFidget;
- float m_aggression;
- IntervalTimer m_lastSawCT;
- IntervalTimer m_lastSawT;
- CountdownTimer m_checkNearbyTerroristTimer;
- bool m_isTerroristNearby;
- CountdownTimer m_nearbyTerroristTimer;
- CountdownTimer m_scaredTimer;
- ScareType m_scareIntensity;
- CountdownTimer m_ignoreTerroristTimer;
- CountdownTimer m_blinkTimer;
- char m_blinkCounter;
- IntervalTimer m_lastInjuryTimer;
- IntervalTimer m_lastNoiseTimer;
- CountdownTimer m_avoidFriendTimer;
- bool m_isFriendInTheWay;
- CountdownTimer m_chatterTimer;
- bool m_isDelayedChatterPending;
- CountdownTimer m_delayedChatterTimer;
- HostageChatterType m_delayedChatterType;
- bool m_delayedChatterMustSpeak;
- CountdownTimer m_talkingTimer;
- unsigned int m_moveFlags;
- Vector2D m_vel;
- Vector m_actualVel;
- Vector m_moveGoal;
- Vector m_knownGoodPos;
- bool m_hasKnownGoodPos;
- Vector m_priorKnownGoodPos;
- bool m_hasPriorKnownGoodPos;
- CountdownTimer m_priorKnownGoodPosTimer;
- IntervalTimer m_collisionTimer;
- Vector m_viewGoal;
- bool m_isLookingAt;
- Vector m_faceGoal;
- bool m_isFacingTo;
- CNavPath m_path;
- CNavPathFollower m_follower;
- Vector m_lastPosition;
- MoveType m_moveType;
- MoveType m_moveLimit;
- bool m_isCrouching;
- CountdownTimer m_minCrouchTimer;
- float m_moveAngle;
- NavRelativeDirType m_wiggleDirection;
- CountdownTimer m_wiggleTimer;
- CountdownTimer m_wiggleJumpTimer;
- CountdownTimer m_inhibitObstacleAvoidance;
- CountdownTimer m_jumpTimer;
- bool m_hasJumped;
- bool m_hasJumpedIntoAir;
- Vector m_jumpTarget;
- CountdownTimer m_clearPathTimer;
- bool m_traversingLadder;
- EHANDLE m_visiblePlayer[32];
- int m_visiblePlayerCount;
+private:
+ CHostage *m_hostage;
+ CNavArea *m_lastKnownArea;
+ mutable Vector m_centroid;
+ mutable Vector m_eye;
+ HostageStateMachine m_behavior;
+ HostageIdleState m_idleState;
+ HostageEscapeState m_escapeState;
+ HostageRetreatState m_retreatState;
+ HostageFollowState m_followState;
+ HostageAnimateState m_animateState;
+ bool m_didFidget;
+ float m_aggression;
+ IntervalTimer m_lastSawCT;
+ IntervalTimer m_lastSawT;
+ CountdownTimer m_checkNearbyTerroristTimer;
+ bool m_isTerroristNearby;
+ CountdownTimer m_nearbyTerroristTimer;
+ CountdownTimer m_scaredTimer;
+ ScareType m_scareIntensity;
+ CountdownTimer m_ignoreTerroristTimer;
+ CountdownTimer m_blinkTimer;
+ char m_blinkCounter;
+ IntervalTimer m_lastInjuryTimer;
+ IntervalTimer m_lastNoiseTimer;
+ mutable CountdownTimer m_avoidFriendTimer;
+ mutable bool m_isFriendInTheWay;
+ CountdownTimer m_chatterTimer;
+ bool m_isDelayedChatterPending;
+ CountdownTimer m_delayedChatterTimer;
+ HostageChatterType m_delayedChatterType;
+ bool m_delayedChatterMustSpeak;
+ CountdownTimer m_talkingTimer;
+ unsigned int m_moveFlags;
+ Vector2D m_vel;
+ Vector m_actualVel;
+ Vector m_moveGoal;
+ Vector m_knownGoodPos;
+ bool m_hasKnownGoodPos;
+ Vector m_priorKnownGoodPos;
+ bool m_hasPriorKnownGoodPos;
+ CountdownTimer m_priorKnownGoodPosTimer;
+ IntervalTimer m_collisionTimer;
+ Vector m_viewGoal;
+ bool m_isLookingAt;
+ Vector m_faceGoal;
+ bool m_isFacingTo;
+ CNavPath m_path;
+ CNavPathFollower m_follower;
+ Vector m_lastPosition;
+ MoveType m_moveType;
+ MoveType m_moveLimit;
+ bool m_isCrouching;
+ CountdownTimer m_minCrouchTimer;
+ float m_moveAngle;
+ NavRelativeDirType m_wiggleDirection;
+ CountdownTimer m_wiggleTimer;
+ CountdownTimer m_wiggleJumpTimer;
+ CountdownTimer m_inhibitObstacleAvoidance;
+ CountdownTimer m_jumpTimer;
+ bool m_hasJumped;
+ bool m_hasJumpedIntoAir;
+ Vector m_jumpTarget;
+ CountdownTimer m_clearPathTimer;
+ bool m_traversingLadder;
+ EHANDLE m_visiblePlayer[32];
+ int m_visiblePlayerCount;
CountdownTimer m_visionTimer;
};/* size: 7308, cachelines: 115, members: 70 */
/* <46fac7> ../cstrike/dlls/hostage/hostage_improv.cpp:363 */
-class CheckWayFunctor
-{
-public:
- const CHostageImprov *m_me;
- Vector m_goalPos;
- CHostage *m_blocker;
-
- /* <46fa9c> ../cstrike/dlls/hostage/hostage_improv.cpp:370 */
- NOBODY inline bool operator()(CHostage *them)
- {
- //
- }
-
+class CheckWayFunctor
+{
+public:
+ CheckWayFunctor(const CHostageImprov *me, const Vector &goalPos)
+ {
+ m_me = me;
+ m_goalPos = goalPos;
+ m_blocker = NULL;
+ }
+ /* <46fa9c> ../cstrike/dlls/hostage/hostage_improv.cpp:370 */
+ bool operator()(CHostage *them)
+ {
+ if (((CBaseMonster *)them)->IsAlive() && m_me->IsFriendInTheWay((CBaseEntity *)them, m_goalPos))
+ {
+ m_blocker = them;
+ return false;
+ }
+
+ return true;
+ }
+
+ const CHostageImprov *m_me;
+ Vector m_goalPos;
+ CHostage *m_blocker;
+
}; /* size: 20, cachelines: 1, members: 3 */
-/* <46f426> ../cstrike/dlls/hostage/hostage_improv.h:400 */
-class HostagePathCost
-{
-public:
- bool operator()(CNavArea *area, class CNavArea *fromArea, const CNavLadder *ladder)
- {
- // {
- // float dist;
- // float cost;
- // {
- // const float ladderCost = 0.0f;
- // const float crouchPenalty = 0.0f;
- // const float jumpPenalty = 0.0f;
- // }
- // }
- }
-};
+/* <46f426> ../cstrike/dlls/hostage/hostage_improv.h:400 */
+class HostagePathCost
+{
+public:
+ float operator()(CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder)
+ {
+ if (fromArea == NULL)
+ {
+ // first area in path, no cost
+ return 0.0f;
+ }
+ else
+ {
+ // compute distance travelled along path so far
+ float dist;
+
+ if (ladder != NULL)
+ {
+ const float ladderCost = 10.0f;
+ return ladder->m_length * ladderCost + fromArea->GetCostSoFar();
+ }
+
+ dist = (*area->GetCenter() - *fromArea->GetCenter()).Length();
+ float cost = fromArea->GetCostSoFar() + dist;
+
+ // if this is a "crouch" area, add penalty
+ if (area->GetAttributes() & NAV_CROUCH)
+ {
+ const float crouchPenalty = 10.0f;
+ cost += crouchPenalty * dist;
+ }
+
+ // if this is a "jump" area, add penalty
+ if (area->GetAttributes() & NAV_JUMP)
+ {
+ const float jumpPenalty = 10.0f;
+ cost += jumpPenalty * dist;
+ }
+
+ return cost;
+ }
+ }
+};
/* <4700b6> ../cstrike/dlls/hostage/hostage_improv.cpp:931 */
-class KeepPersonalSpace
-{
-public:
- /* <46f9d7> ../cstrike/dlls/hostage/hostage_improv.cpp:939 */
- bool operator()(CBaseEntity *entity)
- {
- // {
- // float const space; // 953
- // Vector to; // 955
- // float range; // 956
- // {
- // class CBasePlayer *player; // 948
- // }
- // {
- // class CBasePlayer *player; // 961
- // float const cosTolerance; // 962
- // float const spring; // 967
- // float ds; // 969
- // float const minSpace; // 971
- // float const force; // 975
- // float const damper; // 979
- // }
- // }
- }
-private:
- CHostageImprov *m_improv;
- Vector m_velDir;
- float m_speed;
-
+class KeepPersonalSpace
+{
+public:
+ /* <4700b6> ../cstrike/dlls/hostage/hostage_improv.cpp:931 */
+ KeepPersonalSpace(CHostageImprov *improv)
+ {
+ m_improv = improv;
+ m_velDir = improv->GetActualVelocity();
+ m_speed = m_velDir.NormalizeInPlace();
+ }
+ /* <46f9d7> ../cstrike/dlls/hostage/hostage_improv.cpp:939 */
+ bool operator()(CBaseEntity *entity)
+ {
+ const float space = 1.0f;
+ Vector to;
+ float range;
+
+ if (entity == reinterpret_cast(m_improv->GetEntity()))
+ return true;
+
+ if (entity->IsPlayer() && !entity->IsAlive())
+ return true;
+
+ to = entity->pev->origin - m_improv->GetCentroid();
+
+#ifdef PLAY_GAMEDLL
+ // TODO: fix test demo
+ range = to.NormalizeInPlace();
+#else
+ range = to.NormalizeInPlace();
+#endif // PLAY_GAMEDLL
+ CBasePlayer *player = static_cast(entity);
+
+ const float spring = 50.0f;
+ const float damper = 1.0f;
+
+ if (range >= spring)
+ return true;
+
+ const float cosTolerance = 0.8f;
+ if (entity->IsPlayer() && player->m_iTeam == CT && !m_improv->IsFollowing() && m_improv->IsPlayerLookingAtMe(player, cosTolerance))
+ return true;
+
+ const float minSpace = (spring - range);
+ float_precision ds = -minSpace;
+
+#ifndef PLAY_GAMEDLL
+ m_improv->ApplyForce(to * ds);
+#else
+ // TODO: fix test demo
+ m_improv->ApplyForce2(to.x * ds, to.y * ds);
+#endif // PLAY_GAMEDLL
+
+ const float force = 0.1f;
+ m_improv->ApplyForce(m_speed * -force * m_velDir);
+
+ return true;
+ }
+
+private:
+ CHostageImprov *m_improv;
+ Vector m_velDir;
+ float m_speed;
+
}; /* size: 20, cachelines: 1, members: 3 */
/* <46fbb8> ../cstrike/dlls/hostage/hostage_improv.cpp:518 */
-class CheckAhead
-{
+class CheckAhead
+{
public:
- /* <47046f> ../cstrike/dlls/hostage/hostage_improv.cpp:525 */
- bool operator()(CBaseEntity *entity)
- {
-// Vector to; // 530
-// float range; // 531
-// float const closeRange; // 533
-// float const aheadTolerance; // 537
- }
- /* <46f597> ../cstrike/dlls/hostage/hostage_improv.cpp:546 */
- bool IsBlocked(void)
- {
- return m_isBlocked;
- }
-private:
- const CHostageImprov *m_me;
- Vector m_dir;
- bool m_isBlocked;
-
-};/* size: 20, cachelines: 1, members: 3 */
+ /* <46fbb8> ../cstrike/dlls/hostage/hostage_improv.cpp:518 */
+ CheckAhead(const CHostageImprov *me)
+ {
+ m_me = me;
-NOBODY inline void DrawAxes(Vector &origin, int red, int green, int blue);
+ m_isBlocked = false;
+
+ m_dir.x = BotCOS(me->GetMoveAngle());
+ m_dir.y = BotSIN(me->GetMoveAngle());
+ m_dir.z = 0;
+ }
+ /* <47046f> ../cstrike/dlls/hostage/hostage_improv.cpp:525 */
+ bool operator()(CBaseEntity *entity)
+ {
+ Vector to;
+ float_precision range;
+ const float closeRange = 60.0f;
+ const float aheadTolerance = 0.95f;
+
+ if (entity != reinterpret_cast(m_me->GetEntity()))
+ {
+ to = (entity->Center() - m_me->GetCentroid());
+ range = to.NormalizeInPlace();
+
+ if (range <= closeRange && DotProduct(to, m_dir) >= aheadTolerance)
+ m_isBlocked = true;
+ }
+
+ return true;
+ }
+ /* <46f597> ../cstrike/dlls/hostage/hostage_improv.cpp:546 */
+ bool IsBlocked(void) const
+ {
+ return m_isBlocked;
+ }
+
+private:
+ const CHostageImprov *m_me;
+ Vector m_dir;
+ bool m_isBlocked;
+
+};/* size: 20, cachelines: 1, members: 3 */
#ifdef HOOK_GAMEDLL
+bool NavAreaBuildPath__HostagePathCost__wrapper(CNavArea *startArea, CNavArea *goalArea, const Vector *goalPos, class HostagePathCost &costFunc, CNavArea **closestArea = NULL);
+bool NavAreaBuildPath__ShortestPathCost__wrapper(CNavArea *startArea, CNavArea *goalArea, const Vector *goalPos, class ShortestPathCost &costFunc, CNavArea **closestArea = NULL);
+
typedef bool (CHostageImprov::*IS_FRIEND_IN_THE_WAY_VECTOR)(const Vector &) const;
typedef bool (CHostageImprov::*IS_FRIEND_IN_THE_WAY_CBASE)(CBaseEntity *, const Vector &) const;
+typedef bool (CHostageImprov::*IS_FRIEND_IN_THE_WAY)(void) const;
#endif // HOOK_GAMEDLL
-// refs
-extern void (*pCHostageImprov__FaceTowards)();
-
#endif // HOSTAGE_IMPROV_H
diff --git a/regamedll/dlls/hostage/hostage_localnav.cpp b/regamedll/dlls/hostage/hostage_localnav.cpp
index 2255b43e..dfe800f9 100644
--- a/regamedll/dlls/hostage/hostage_localnav.cpp
+++ b/regamedll/dlls/hostage/hostage_localnav.cpp
@@ -467,14 +467,14 @@ int CLocalNav::PathTraversable(Vector &vecSource, Vector &vecDest, int fNoMonste
{
if (flTotal >= s_flStepSize)
{
-#ifndef HOOK_GAMEDLL
+#ifndef PLAY_GAMEDLL
vecDestTmp = vecSrcTmp + (vecDir * s_flStepSize);
#else
- // fix test demo
+ // TODO: fix test demo
vecDestTmp[0] = vecSrcTmp[0] + (vecDir[0] * s_flStepSize);
vecDestTmp[1] = vecSrcTmp[1] + (float)(vecDir[1] * s_flStepSize);
vecDestTmp[2] = vecSrcTmp[2] + (vecDir[2] * s_flStepSize);
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
}
else
diff --git a/regamedll/dlls/hostage/hostage_states.h b/regamedll/dlls/hostage/hostage_states.h
index 7471af1f..1eadc644 100644
--- a/regamedll/dlls/hostage/hostage_states.h
+++ b/regamedll/dlls/hostage/hostage_states.h
@@ -49,31 +49,23 @@ class HostageStateMachine: public SimpleStateMachineOnMoveToSuccess(goal);
- }
}
virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason)
{
- if (m_state != NULL)
- {
+ if (m_state)
m_state->OnMoveToFailure(goal, reason);
- }
}
virtual void OnInjury(float amount)
{
- if (m_state != NULL)
- {
+ if (m_state)
m_state->OnInjury(amount);
- }
}
void UpdateStationaryAnimation(CHostageImprov *improv)
{
- if (m_state != NULL)
- {
+ if (m_state)
m_state->UpdateStationaryAnimation(improv);
- }
}
};/* size: 16, cachelines: 1, members: 2 */
@@ -100,7 +92,7 @@ public:
{
m_moveState = MoveFailed;
}
- virtual void OnInjury(float amount)
+ virtual void OnInjury(float amount = -1.0f)
{
m_fleeTimer.Invalidate();
m_mustFlee = true;
@@ -150,8 +142,22 @@ public:
return "Escape:ToCover";
}
virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason);
+
+#ifdef HOOK_GAMEDLL
+
+ void OnEnter_(CHostageImprov *improv);
+ void OnUpdate_(CHostageImprov *improv);
+ void OnExit_(CHostageImprov *improv);
+ void OnMoveToFailure_(const Vector &goal, MoveToFailureType reason);
+
+#endif // HOOK_GAMEDLL
+
public:
- void SetRescueGoal(const Vector &rescueGoal);
+ void SetRescueGoal(const Vector &rescueGoal)
+ {
+ m_rescueGoal = rescueGoal;
+ }
+
private:
Vector m_rescueGoal;
Vector m_spot;
@@ -173,6 +179,14 @@ public:
return "Escape:LookAround";
}
+#ifdef HOOK_GAMEDLL
+
+ void OnEnter_(CHostageImprov *improv);
+ void OnUpdate_(CHostageImprov *improv);
+ void OnExit_(CHostageImprov *improv);
+
+#endif // HOOK_GAMEDLL
+
private:
CountdownTimer m_timer;
@@ -193,13 +207,27 @@ public:
}
virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason)
{
- //TODO: i'm unsure
- if (m_behavior.IsState(this))
- IImprovEvent::OnMoveToFailure(goal, reason);
+ m_behavior.OnMoveToFailure(goal, reason);
}
+
+#ifdef HOOK_GAMEDLL
+
+ void OnEnter_(CHostageImprov *improv);
+ void OnUpdate_(CHostageImprov *improv);
+ void OnExit_(CHostageImprov *improv);
+
+#endif // HOOK_GAMEDLL
+
public:
- void ToCover(void);
- void LookAround(void);
+ void ToCover(void)
+ {
+ m_behavior.SetState(&m_toCoverState);
+ }
+ void LookAround(void)
+ {
+ m_behavior.SetState(&m_lookAroundState);
+ }
+
private:
HostageEscapeToCoverState m_toCoverState;
HostageEscapeLookAroundState m_lookAroundState;
@@ -252,17 +280,27 @@ public:
}
virtual void UpdateStationaryAnimation(CHostageImprov *improv);
+#ifdef HOOK_GAMEDLL
+
+ void OnEnter_(CHostageImprov *improv);
+ void OnUpdate_(CHostageImprov *improv);
+ void OnExit_(CHostageImprov *improv);
+ void UpdateStationaryAnimation_(CHostageImprov *improv);
+
+#endif // HOOK_GAMEDLL
+
public:
void SetLeader(CBaseEntity *leader)
{
m_leader = leader;
}
- CBaseEntity *GetLeader(void)
+ CBaseEntity *GetLeader(void) const
{
return m_leader;
}
+
private:
- EHANDLE m_leader;
+ mutable EHANDLE m_leader;
Vector m_lastLeaderPos;
bool m_isWaiting;
float m_stopRange;
@@ -329,16 +367,16 @@ public:
void AddSequence(CHostageImprov *improv, const char *seqName, float holdTime = -1.0f, float rate = 1.0f);
void AddSequence(CHostageImprov *improv, int activity, float holdTime = -1.0f, float rate = 1.0f);
- bool IsBusy(void)
+ bool IsBusy(void) const
{
return (m_sequenceCount > 0);
}
- bool IsPlaying(CHostageImprov *improv, const char *seqName);
+ NOXREF bool IsPlaying(CHostageImprov *improv, const char *seqName) const;
int GetCurrentSequenceID(void)
{
return m_currentSequence;
}
- PerformanceType GetPerformance(void)
+ PerformanceType GetPerformance(void) const
{
return m_performance;
}
diff --git a/regamedll/dlls/hostage/states/hostage_animate.cpp b/regamedll/dlls/hostage/states/hostage_animate.cpp
index 5720625b..708742c7 100644
--- a/regamedll/dlls/hostage/states/hostage_animate.cpp
+++ b/regamedll/dlls/hostage/states/hostage_animate.cpp
@@ -87,19 +87,13 @@ void HostageAnimateState::__MAKE_VHOOK(OnEnter)(CHostageImprov *improv)
;
}
-/* <410d79> ../cstrike/dlls/hostage/states/hostage_animate.cpp:139 */
-void HostageAnimateState::__MAKE_VHOOK(OnExit)(CHostageImprov *improv)
-{
- ;
-}
-
/* <410fb2> ../cstrike/dlls/hostage/states/hostage_animate.cpp:108 */
void HostageAnimateState::__MAKE_VHOOK(OnUpdate)(CHostageImprov *improv)
{
if (m_sequenceCount <= 0)
return;
- if (!improv->m_hostage->m_fSequenceFinished && m_sequence[m_currentSequence].seqID >= 0)
+ if (!improv->GetEntity()->m_fSequenceFinished && m_sequence[m_currentSequence].seqID >= 0)
return;
if (m_sequence[m_currentSequence].holdTime >= 0)
@@ -120,13 +114,24 @@ void HostageAnimateState::__MAKE_VHOOK(OnUpdate)(CHostageImprov *improv)
StartSequence(improv, &m_sequence[m_currentSequence]);
}
-/* <4112d1> ../cstrike/dlls/hostage/states/hostage_animate.cpp:147 */
-bool HostageAnimateState::IsPlaying(CHostageImprov *improv, const char *seqName)
+/* <410d79> ../cstrike/dlls/hostage/states/hostage_animate.cpp:139 */
+void HostageAnimateState::__MAKE_VHOOK(OnExit)(CHostageImprov *improv)
{
-// {
-// class CHostage *hostage; // 152
-// int id; // 154
-// }
+ ;
+}
+
+/* <4112d1> ../cstrike/dlls/hostage/states/hostage_animate.cpp:147 */
+NOXREF bool HostageAnimateState::IsPlaying(CHostageImprov *improv, const char *seqName) const
+{
+ int id = 0;
+ CHostage *hostage = improv->GetEntity();
+
+ if (m_sequenceCount > 0)
+ {
+ id = m_sequence[m_currentSequence].seqID;
+ }
+
+ return LookupSequence(hostage, seqName) == id;
}
#ifdef HOOK_GAMEDLL
diff --git a/regamedll/dlls/hostage/states/hostage_escape.cpp b/regamedll/dlls/hostage/states/hostage_escape.cpp
index 9a4c0cdd..b409fe44 100644
--- a/regamedll/dlls/hostage/states/hostage_escape.cpp
+++ b/regamedll/dlls/hostage/states/hostage_escape.cpp
@@ -1,105 +1,242 @@
#include "precompiled.h"
/* <4205b1> ../cstrike/dlls/hostage/states/hostage_escape.cpp:12 */
-void HostageEscapeToCoverState::OnEnter(CHostageImprov *improv)
+void HostageEscapeToCoverState::__MAKE_VHOOK(OnEnter)(CHostageImprov *improv)
{
-// {
-// class CNavPath path; // 18
-// class HostagePathCost pathCost; // 19
-// Invalidate(CNavPath *const this); // 14
-// CNavPath(CNavPath *const this); // 18
-// Compute(CNavPath *const this,
-// const Vector *start,
-// const Vector *goal,
-// class HostagePathCost &costFunc); // 20
-// {
-// float const moveRange; // 23
-// int idx; // 24
-// {
-// Vector pathPos; // 32
-// float const hidingRange; // 34
-// const Vector *spot; // 35
-// operator[](CNavPath *const this,
-// int i); // 32
-// Vector(Vector *const this,
-// const Vector &v); // 32
-// }
-// }
-// }
+ CNavPath path;
+ HostagePathCost pathCost;
+
+ improv->GetPath()->Invalidate();
+ m_canEscape = false;
+
+ if (!path.Compute(&improv->GetFeet(), &m_rescueGoal, pathCost))
+ return;
+
+ const float moveRange = 500.0f;
+ int idx = path.GetSegmentIndexAlongPath(moveRange);
+
+ if (idx < 0)
+ return;
+
+ if (idx < path.GetSegmentCount() - 1)
+ ++idx;
+
+ Vector pathPos = path[idx]->pos;
+ const float hidingRange = 450.0f;
+ const Vector *spot = FindNearbyHidingSpot(improv->GetEntity(), &pathPos, TheNavAreaGrid.GetNearestNavArea(&pathPos), hidingRange);
+
+ if (spot == NULL)
+ spot = &pathPos;
+
+ m_spot = *spot;
+
+ improv->Run();
+ improv->MoveTo(m_spot);
+
+ m_canEscape = true;
}
/* <41fd51> ../cstrike/dlls/hostage/states/hostage_escape.cpp:52 */
-void HostageEscapeToCoverState::OnUpdate(CHostageImprov *improv)
+void HostageEscapeToCoverState::__MAKE_VHOOK(OnUpdate)(CHostageImprov *improv)
{
-// Idle(CHostageImprov *const this); // 57
-// OnUpdate(HostageEscapeToCoverState *const this,
-// class CHostageImprov *improv); // 52
+ if (!m_canEscape)
+ {
+ improv->Idle();
+ return;
+ }
+
+ if (IsSpotOccupied(improv->GetEntity(), &m_spot))
+ {
+ const float emergencyHidingRange = 300.0f;
+ const Vector *spot = FindNearbyHidingSpot(improv->GetEntity(), &improv->GetFeet(), improv->GetLastKnownArea(), emergencyHidingRange);
+
+ if (spot == NULL)
+ {
+ HostageEscapeState *escape = (HostageEscapeState *)GetParent();
+ escape->LookAround();
+ return;
+ }
+
+ m_spot = *spot;
+ improv->MoveTo(m_spot);
+ }
+
+ if (improv->IsAtMoveGoal())
+ {
+ HostageEscapeState *escape = (HostageEscapeState *)GetParent();
+ escape->LookAround();
+ return;
+ }
}
/* <41f65f> ../cstrike/dlls/hostage/states/hostage_escape.cpp:95 */
-void HostageEscapeToCoverState::OnExit(CHostageImprov *improv)
+void HostageEscapeToCoverState::__MAKE_VHOOK(OnExit)(CHostageImprov *improv)
{
+ ;
}
/* <41faaf> ../cstrike/dlls/hostage/states/hostage_escape.cpp:100 */
-void HostageEscapeToCoverState::OnMoveToFailure(const Vector &goal, MoveToFailureType reason)
+void HostageEscapeToCoverState::__MAKE_VHOOK(OnMoveToFailure)(const Vector &goal, MoveToFailureType reason)
{
-// {
-// class HostageEscapeState *escape; // 103
-// LookAround(HostageEscapeState *const this); // 104
-// }
+#ifndef HOOK_GAMEDLL
+ HostageEscapeState *escape = (HostageEscapeState *)GetParent();
+#else
+ // TODO: why this - 1? Hacks?
+ // need investigation
+ HostageEscapeState *escape = (HostageEscapeState *)*((int *)this - 1);
+#endif // HOOK_GAMEDLL
+
+ escape->LookAround();
}
/* <41fa2f> ../cstrike/dlls/hostage/states/hostage_escape.cpp:110 */
-void HostageEscapeLookAroundState::OnEnter(CHostageImprov *improv)
+void HostageEscapeLookAroundState::__MAKE_VHOOK(OnEnter)(CHostageImprov *improv)
{
-// Start(CountdownTimer *const this,
-// float duration); // 112
+ m_timer.Start(RANDOM_FLOAT(5, 10));
+
+ improv->Stop();
+ improv->FaceOutwards();
}
/* <41fc67> ../cstrike/dlls/hostage/states/hostage_escape.cpp:119 */
-void HostageEscapeLookAroundState::OnUpdate(CHostageImprov *improv)
+void HostageEscapeLookAroundState::__MAKE_VHOOK(OnUpdate)(CHostageImprov *improv)
{
-// IsElapsed(const class CountdownTimer *const this); // 123
-// OnUpdate(HostageEscapeLookAroundState *const this,
-// class CHostageImprov *improv); // 119
+ improv->UpdateIdleActivity(ACT_IDLE_SNEAKY, ACT_IDLE_SNEAKY_FIDGET);
+
+ if (m_timer.IsElapsed())
+ {
+ HostageEscapeState *escape = (HostageEscapeState *)GetParent();
+ escape->ToCover();
+ }
}
/* <41f693> ../cstrike/dlls/hostage/states/hostage_escape.cpp:133 */
-void HostageEscapeLookAroundState::OnExit(CHostageImprov *improv)
+void HostageEscapeLookAroundState::__MAKE_VHOOK(OnExit)(CHostageImprov *improv)
{
+ improv->ClearFaceTo();
}
/* <41fb6b> ../cstrike/dlls/hostage/states/hostage_escape.cpp:145 */
-void HostageEscapeState::OnEnter(CHostageImprov *improv)
+void HostageEscapeState::__MAKE_VHOOK(OnEnter)(CHostageImprov *improv)
{
-// {
-// class CCSBotManager *ctrl; // 148
-// const class Zone *zone; // 149
-// GetRandomZone(const class CCSBotManager *const this); // 149
-// SetRescueGoal(HostageEscapeToCoverState *const this,
-// const Vector &rescueGoal); // 153
-// SetState(SimpleStateMachine *const this,
-// class HostageState *newState); // 156
-// Reset(SimpleStateMachine *const this,
-// class CHostageImprov *userData); // 155
-// }
+ CCSBotManager *ctrl = TheCSBots();
+ const CCSBotManager::Zone *zone = ctrl->GetRandomZone();
+
+ if (zone != NULL)
+ {
+ m_toCoverState.SetRescueGoal(zone->m_center);
+
+ m_behavior.Reset(improv);
+ m_behavior.SetState(&m_toCoverState);
+ }
+
+ m_canEscape = true;
}
/* <41fe8e> ../cstrike/dlls/hostage/states/hostage_escape.cpp:167 */
-void HostageEscapeState::OnUpdate(CHostageImprov *improv)
+void HostageEscapeState::__MAKE_VHOOK(OnUpdate)(CHostageImprov *improv)
{
-// {
-// class CBasePlayer *player; // 192
-// {
-// float const farRange; // 198
-// }
-// }
-// OnUpdate(HostageEscapeState *const this,
-// class CHostageImprov *improv); // 167
+ if (!m_canEscape || (improv->IsScared() && improv->GetScareIntensity() == CHostageImprov::TERRIFIED))
+ {
+ improv->Stop();
+ improv->Idle();
+ return;
+ }
+
+ if (m_runTimer.IsElapsed())
+ improv->Walk();
+ else
+ improv->Run();
+
+ CBasePlayer *player = improv->GetClosestVisiblePlayer(UNASSIGNED);
+
+ if (player != NULL)
+ {
+ if (player->m_iTeam != TERRORIST)
+ {
+ improv->Stop();
+ improv->Idle();
+ return;
+ }
+
+ const float farRange = 750.0f;
+ if ((player->pev->origin - improv->GetCentroid().IsLengthGreaterThan(farRange)))
+ {
+ improv->Frighten(CHostageImprov::NERVOUS);
+
+ m_runTimer.Start(RANDOM_FLOAT(3, 6));
+ m_behavior.SetState(&m_toCoverState);
+ }
+ else
+ {
+ improv->Frighten(CHostageImprov::SCARED);
+ improv->Stop();
+ improv->Idle();
+ return;
+ }
+ }
+ else
+ {
+ m_behavior.Update();
+ }
}
/* <41f6c7> ../cstrike/dlls/hostage/states/hostage_escape.cpp:230 */
+void HostageEscapeState::__MAKE_VHOOK(OnExit)(CHostageImprov *improv)
+{
+ improv->Run();
+}
+
+#ifdef HOOK_GAMEDLL
+
+void HostageEscapeToCoverState::OnEnter(CHostageImprov *improv)
+{
+ OnEnter_(improv);
+}
+
+void HostageEscapeToCoverState::OnUpdate(CHostageImprov *improv)
+{
+ OnUpdate_(improv);
+}
+
+void HostageEscapeToCoverState::OnExit(CHostageImprov *improv)
+{
+ OnExit_(improv);
+}
+
+void HostageEscapeToCoverState::OnMoveToFailure(const Vector &goal, MoveToFailureType reason)
+{
+ OnMoveToFailure_(goal, reason);
+}
+
+void HostageEscapeLookAroundState::OnEnter(CHostageImprov *improv)
+{
+ OnEnter_(improv);
+}
+
+void HostageEscapeLookAroundState::OnUpdate(CHostageImprov *improv)
+{
+ OnUpdate_(improv);
+}
+
+void HostageEscapeLookAroundState::OnExit(CHostageImprov *improv)
+{
+ OnExit_(improv);
+}
+
+void HostageEscapeState::OnEnter(CHostageImprov *improv)
+{
+ OnEnter_(improv);
+}
+
+void HostageEscapeState::OnUpdate(CHostageImprov *improv)
+{
+ OnUpdate_(improv);
+}
+
void HostageEscapeState::OnExit(CHostageImprov *improv)
{
+ OnExit_(improv);
}
+
+#endif // HOOK_GAMEDLL
diff --git a/regamedll/dlls/hostage/states/hostage_follow.cpp b/regamedll/dlls/hostage/states/hostage_follow.cpp
index d16fc18b..53545fae 100644
--- a/regamedll/dlls/hostage/states/hostage_follow.cpp
+++ b/regamedll/dlls/hostage/states/hostage_follow.cpp
@@ -1,59 +1,234 @@
#include "precompiled.h"
/* <42e3e3> ../cstrike/dlls/hostage/states/hostage_follow.cpp:12 */
-void HostageFollowState::OnEnter(CHostageImprov *improv)
+void HostageFollowState::__MAKE_VHOOK(OnEnter)(CHostageImprov *improv)
{
-// Invalidate(CountdownTimer *const this); // 28
-// OnEnter(HostageFollowState *const this,
-// class CHostageImprov *improv); // 12
+ improv->Chatter(HOSTAGE_CHATTER_START_FOLLOW);
+ improv->Agree();
+
+ m_isWaiting = false;
+ m_isWaitingForFriend = false;
+
+ improv->MoveTo(improv->GetFeet());
+
+ m_lastLeaderPos = Vector(999999, 999999, 999999);
+
+ m_makeWayTimer.Invalidate();
+ m_stopRange = RANDOM_FLOAT(125, 175);
+
+ if (improv->IsTerroristNearby())
+ {
+ improv->DelayedChatter(3, HOSTAGE_CHATTER_WARN_NEARBY);
+ }
}
/* <42deaf> ../cstrike/dlls/hostage/states/hostage_follow.cpp:40 */
-void HostageFollowState::OnUpdate(CHostageImprov *improv)
+void HostageFollowState::__MAKE_VHOOK(OnUpdate)(CHostageImprov *improv)
{
-// {
-// float range; // 58
-// float const giveUpRange; // 61
-// float const maxPathLength; // 62
-// float const walkRange; // 70
-// float const continueRange; // 71
-// float leaderSpeed; // 74
-// float const runThreshold; // 75
-// bool isLeaderRunning; // 76
-// float const movedRange; // 246
-// {
-// float const closeRange; // 117
-// class CBasePlayer *terrorist; // 193
-// {
-// bool makeWay; // 120
-// float const cosTolerance; // 123
-// {
-// Vector to; // 148
-// Vector cross; // 152
-// Vector lat; // 154
-// float const sideStepSize; // 168
-// Vector sideStepPos; // 169
-// float ground; // 172
-// {
-// float const push; // 178
-// }
-// }
-// }
-// }
-// {
-// bool doWait; // 206
-// }
-// }
+ // if we lost our leader, give up
+ if (m_leader == NULL)
+ {
+ improv->Idle();
+ return;
+ }
+
+ if (m_leader->pev->deadflag != DEAD_NO)
+ {
+ improv->Frighten(CHostageImprov::TERRIFIED);
+ improv->Idle();
+ return;
+ }
+
+ float_precision range = (m_leader->pev->origin - improv->GetCentroid()).Length();
+
+ const float maxPathLength = 3000.0f;
+ const float giveUpRange = 1000.0f;
+
+ if (range > giveUpRange || improv->GetPath()->GetSegmentCount() > 0 && improv->GetPath()->GetLength() > maxPathLength)
+ {
+ improv->Idle();
+ return;
+ }
+
+ const float walkRange = m_stopRange + 50.0f;
+ const float continueRange = m_stopRange + 20.0f;
+ const float runThreshold = 140.0f;
+
+ bool isLeaderRunning;
+ float leaderSpeed = m_leader->pev->velocity.Make2D().Length();
+
+ if (leaderSpeed > runThreshold)
+ {
+ isLeaderRunning = true;
+ m_isWaiting = false;
+ }
+ else
+ {
+ // track when began to run
+ isLeaderRunning = false;
+
+ if (!m_isWaiting)
+ {
+ if (range < m_stopRange)
+ {
+ m_isWaiting = true;
+ m_impatientTimer.Start(RANDOM_FLOAT(5.0, 20.0));
+ }
+ }
+ else if (range > continueRange)
+ m_isWaiting = false;
+ }
+
+ if (!m_isWaiting)
+ {
+ bool makeWay = improv->IsFriendInTheWay();
+
+ if (makeWay && !m_isWaitingForFriend)
+ {
+ m_isWaitingForFriend = true;
+ m_waitForFriendTimer.Start(15.0);
+
+ improv->Stop();
+ return;
+ }
+
+ if (makeWay && !m_waitForFriendTimer.IsElapsed())
+ {
+ improv->Stop();
+ return;
+ }
+
+ if (improv->GetPath()->GetSegmentCount() <= 0 && m_repathTimer.IsElapsed())
+ {
+ improv->MoveTo(m_leader->pev->origin);
+
+ m_lastLeaderPos = m_leader->pev->origin;
+ m_repathTimer.Start(1.0);
+ }
+
+ if (isLeaderRunning || range > walkRange)
+ improv->Run();
+ else
+ improv->Walk();
+
+ const float movedRange = 35.0f;
+ if ((m_lastLeaderPos - m_leader->pev->origin).IsLengthGreaterThan(movedRange))
+ {
+ improv->MoveTo(m_leader->pev->origin);
+ m_lastLeaderPos = m_leader->pev->origin;
+ }
+
+ return;
+ }
+
+ if (m_impatientTimer.IsElapsed() && !TheCSBots()->IsRoundOver())
+ {
+ m_impatientTimer.Start(RANDOM_FLOAT(20.0, 30.0));
+
+ if (improv->CanSeeRescueZone())
+ improv->Chatter(HOSTAGE_CHATTER_SEE_RESCUE_ZONE, false);
+ else
+ improv->Chatter(HOSTAGE_CHATTER_IMPATIENT_FOR_RESCUE, false);
+ }
+
+ const float closeRange = 200.0f;
+ if ((m_leader->pev->origin - improv->GetCentroid()).IsLengthLessThan(closeRange))
+ {
+ bool makeWay = false;
+ const float cosTolerance = 0.99f;
+
+ if (improv->IsPlayerLookingAtMe((CBasePlayer *)((CBaseEntity *)m_leader), cosTolerance))
+ {
+ if (!m_makeWayTimer.HasStarted())
+ {
+ m_makeWayTimer.Start(RANDOM_FLOAT(0.4, 0.75));
+ }
+ else if (m_makeWayTimer.IsElapsed())
+ {
+ m_impatientTimer.Invalidate();
+
+ Vector to = (m_leader->pev->origin - improv->GetCentroid());
+ to.NormalizeInPlace();
+
+ Vector cross(-to.y, -to.x, 0);
+ if (cross.x * gpGlobals->v_forward.x - cross.y * gpGlobals->v_forward.y < 0)
+ cross.y = to.x;
+ else
+ cross.x = to.y;
+
+ float ground;
+ float const sideStepSize = 15.0f;
+ Vector sideStepPos = improv->GetFeet() + cross * sideStepSize;
+
+ if (GetGroundHeight(&sideStepPos, &ground))
+ {
+ if (abs((int)(ground - improv->GetFeet().z)) < 18.0f)
+ {
+ const float push = 20.0f;
+ Vector lat = cross * push;
+
+ improv->ApplyForce(lat);
+ improv->MoveTo(sideStepPos);
+ return;
+ }
+ }
+ }
+ }
+ else
+ {
+ m_makeWayTimer.Invalidate();
+ }
+ }
+
+ improv->Stop();
+
+ CBasePlayer *terrorist = improv->GetClosestVisiblePlayer(TERRORIST);
+
+ if (terrorist != NULL)
+ {
+ improv->LookAt(terrorist->EyePosition());
+ }
+ else
+ {
+ improv->LookAt(m_leader->EyePosition());
+ }
}
/* <42e1aa> ../cstrike/dlls/hostage/states/hostage_follow.cpp:256 */
-void HostageFollowState::OnExit(CHostageImprov *improv)
+void HostageFollowState::__MAKE_VHOOK(OnExit)(CHostageImprov *improv)
{
+ improv->Stop();
}
/* <42e38f> ../cstrike/dlls/hostage/states/hostage_follow.cpp:270 */
+void HostageFollowState::__MAKE_VHOOK(UpdateStationaryAnimation)(CHostageImprov *improv)
+{
+ if (improv->IsScared())
+ improv->UpdateIdleActivity(ACT_FOLLOW_IDLE_SCARED, ACT_RESET);
+ else
+ improv->UpdateIdleActivity(ACT_FOLLOW_IDLE, ACT_FOLLOW_IDLE_FIDGET);
+}
+
+#ifdef HOOK_GAMEDLL
+
+void HostageFollowState::OnEnter(CHostageImprov *improv)
+{
+ OnEnter_(improv);
+}
+
+void HostageFollowState::OnUpdate(CHostageImprov *improv)
+{
+ OnUpdate_(improv);
+}
+
+void HostageFollowState::OnExit(CHostageImprov *improv)
+{
+ OnExit_(improv);
+}
+
void HostageFollowState::UpdateStationaryAnimation(CHostageImprov *improv)
{
-// UpdateStationaryAnimation(HostageFollowState *const this,
-// class CHostageImprov *improv); // 270
+ UpdateStationaryAnimation_(improv);
}
+
+#endif // HOOK_GAMEDLL
diff --git a/regamedll/dlls/hostage/states/hostage_idle.cpp b/regamedll/dlls/hostage/states/hostage_idle.cpp
index 8045324d..0b9a41bc 100644
--- a/regamedll/dlls/hostage/states/hostage_idle.cpp
+++ b/regamedll/dlls/hostage/states/hostage_idle.cpp
@@ -11,12 +11,231 @@ void HostageIdleState::__MAKE_VHOOK(OnEnter)(CHostageImprov *improv)
/* <43c197> ../cstrike/dlls/hostage/states/hostage_idle.cpp:23 */
void HostageIdleState::__MAKE_VHOOK(OnUpdate)(CHostageImprov *improv)
{
+ if (!UTIL_ActivePlayersInGame())
+ return;
+
+ if (m_mustFlee || (improv->IsScared() && !improv->IsTerroristNearby() && m_moveState != Moving))
+ {
+ if (!m_mustFlee && improv->GetScareIntensity() == CHostageImprov::TERRIFIED)
+ m_mustFlee = true;
+
+ if ((improv->GetScareIntensity() == CHostageImprov::TERRIFIED || m_mustFlee) || (m_fleeTimer.IsElapsed() && improv->GetScareIntensity() > CHostageImprov::NERVOUS))
+ {
+ m_fleeTimer.Start(RANDOM_FLOAT(10, 20));
+
+ const float fleeChance = 33.3f;
+ const float terroristRecentTime = 5.0f;
+
+ if (!m_mustFlee && improv->GetTimeSinceLastSawPlayer(TERRORIST) > terroristRecentTime && RANDOM_FLOAT(0, 100) < fleeChance)
+ m_mustFlee = true;
+
+ if (m_mustFlee)
+ {
+ m_mustFlee = false;
+
+ const Vector *spot = FindNearbyRetreatSpot(NULL, &improv->GetFeet(), improv->GetLastKnownArea(), 500.0, TERRORIST, false);
+
+ if (spot != NULL)
+ {
+ improv->MoveTo(*spot);
+ improv->Run();
+
+ m_moveState = Moving;
+
+ if (improv->GetScareIntensity() == CHostageImprov::TERRIFIED)
+ {
+ improv->Frighten(CHostageImprov::SCARED);
+ }
+
+ return;
+ }
+ }
+ }
+ }
+
+ if (m_moveState && improv->IsAtMoveGoal())
+ {
+ m_moveState = NotMoving;
+
+ improv->Stop();
+ improv->FaceOutwards();
+
+ const float crouchChance = 33.3f;
+ if (improv->IsScared() && !improv->IsAtHome() && RANDOM_FLOAT(0, 100) <= crouchChance)
+ {
+ improv->Crouch();
+ }
+
+ return;
+ }
+
+ if (m_moveState == Moving)
+ {
+ improv->Run();
+ return;
+ }
+
+ if (!improv->IsAtMoveGoal(75.0f))
+ {
+ improv->Walk();
+ m_moveState = Moving;
+ return;
+ }
+
+ CBasePlayer *rescuer = improv->GetClosestVisiblePlayer(CT);
+ CBasePlayer *captor = improv->GetClosestVisiblePlayer(TERRORIST);
+
+ if (rescuer != NULL)
+ {
+ improv->LookAt(rescuer->EyePosition());
+ improv->Stop();
+
+ if (captor != NULL)
+ {
+ const float attentionRange = 700.0f;
+ float rangeT = (improv->GetCentroid() - captor->pev->origin).Length();
+
+ if (rangeT < attentionRange)
+ {
+ const float cosTolerance = 0.95f;
+ if (improv->IsAnyPlayerLookingAtMe(TERRORIST, cosTolerance))
+ {
+ improv->LookAt(captor->EyePosition());
+ }
+ else
+ {
+ TraceResult result;
+ UTIL_TraceLine(rescuer->pev->origin, captor->pev->origin, ignore_monsters, ignore_glass, captor->edict(), &result);
+
+ if (result.flFraction != 1.0f && m_disagreeTimer.IsElapsed())
+ {
+ improv->Disagree();
+ m_disagreeTimer.Start(RANDOM_FLOAT(2, 4));
+ }
+ }
+
+ return;
+ }
+ }
+ else if (!TheCSBots()->IsRoundOver() && m_askTimer.IsElapsed())
+ {
+ const float closeRange = 200.0f;
+ if ((rescuer->pev->origin - improv->GetCentroid()).IsLengthLessThan(closeRange))
+ {
+ if (improv->IsPlayerLookingAtMe(rescuer, 0.99))
+ {
+ HostageChatterType say;
+ if (improv->IsTerroristNearby())
+ say = HOSTAGE_CHATTER_WARN_NEARBY;
+ else
+ say = HOSTAGE_CHATTER_PLEASE_RESCUE_ME;
+
+ improv->Chatter(say, false);
+ m_askTimer.Start(RANDOM_FLOAT(3, 10));
+ }
+ }
+ }
+
+ if (m_waveTimer.IsElapsed())
+ {
+ CHostage *hostage = improv->GetEntity();
+
+ const float waveRange = 250.0f;
+ if ((rescuer->pev->origin - hostage->pev->origin).IsLengthGreaterThan(waveRange))
+ {
+ improv->Stop();
+ improv->Wave();
+
+ improv->LookAt(rescuer->EyePosition());
+ improv->Chatter(HOSTAGE_CHATTER_CALL_TO_RESCUER, false);
+
+ m_moveState = NotMoving;
+ m_waveTimer.Start(RANDOM_FLOAT(10, 20));
+ }
+ }
+ }
+ else if (captor != NULL)
+ {
+ improv->LookAt(captor->EyePosition());
+ improv->Stop();
+
+ const float closeRange = 200.0f;
+ if ((captor->pev->origin - improv->GetCentroid()).IsLengthLessThan(closeRange) && improv->IsPlayerLookingAtMe(captor, 0.99))
+ {
+ if (!m_intimidatedTimer.HasStarted())
+ {
+ m_intimidatedTimer.Start();
+ }
+
+ if (!improv->IsScared())
+ {
+ improv->Frighten(CHostageImprov::NERVOUS);
+ }
+
+ const float minThreatenTime = 1.0f;
+ if ((!m_intimidatedTimer.HasStarted() || m_intimidatedTimer.IsGreaterThen(minThreatenTime)) && m_pleadTimer.IsElapsed())
+ {
+ improv->Chatter(HOSTAGE_CHATTER_INTIMIDATED, true);
+ m_pleadTimer.Start(RANDOM_FLOAT(10, 20));
+ }
+
+ if (!improv->IsAtHome())
+ {
+ improv->Chatter(HOSTAGE_CHATTER_RETREAT, true);
+ improv->Retreat();
+ }
+ }
+ else
+ {
+ m_intimidatedTimer.Invalidate();
+ }
+ }
+ else
+ {
+ improv->ClearLookAt();
+
+ const float pushbackRange = 60.0f;
+ if (pushbackRange - improv->GetAggression() * 5.0f < TheCSBots()->GetElapsedRoundTime() && m_escapeTimer.IsElapsed())
+ {
+ const float stayHomeDuration = 5.0f;
+ m_escapeTimer.Start(stayHomeDuration);
+
+ float sightTimeT = improv->GetTimeSinceLastSawPlayer(TERRORIST);
+ float sightTimeCT = improv->GetTimeSinceLastSawPlayer(CT);
+
+ const float waitTime = 15.0f - improv->GetAggression() * 3.0f;
+
+ if (sightTimeT > waitTime && sightTimeCT > waitTime)
+ {
+ if (improv->IsTerroristNearby())
+ {
+ if (cv_hostage_debug.value > 0.0f)
+ {
+ CONSOLE_ECHO("Hostage: I want to escape, but a T is nearby\n");
+ }
+
+ m_escapeTimer.Start(waitTime);
+ }
+ else
+ {
+ improv->Escape();
+
+ if (cv_hostage_debug.value > 0.0f)
+ {
+ CONSOLE_ECHO("Hostage: I'm escaping!\n");
+ }
+ }
+ }
+ }
+ }
}
/* <43c59b> ../cstrike/dlls/hostage/states/hostage_idle.cpp:297 */
void HostageIdleState::__MAKE_VHOOK(OnExit)(CHostageImprov *improv)
{
+ improv->StandUp();
+ improv->ClearFaceTo();
}
/* <43c783> ../cstrike/dlls/hostage/states/hostage_idle.cpp:307 */
diff --git a/regamedll/dlls/hostage/states/hostage_retreat.cpp b/regamedll/dlls/hostage/states/hostage_retreat.cpp
index 96cbb7bc..7b92f980 100644
--- a/regamedll/dlls/hostage/states/hostage_retreat.cpp
+++ b/regamedll/dlls/hostage/states/hostage_retreat.cpp
@@ -4,20 +4,39 @@
void HostageRetreatState::__MAKE_VHOOK(OnEnter)(CHostageImprov *improv)
{
improv->Walk();
- improv->MoveTo(improv->m_hostage->m_vStart);
+ improv->MoveTo(improv->GetEntity()->m_vStart);
}
/* <44a220> ../cstrike/dlls/hostage/states/hostage_retreat.cpp:20 */
void HostageRetreatState::__MAKE_VHOOK(OnUpdate)(CHostageImprov *improv)
{
-// {
-// class CBasePlayer *player; // 40
-// {
-// float const farRange; // 45
-// }
-// }
-// OnUpdate(HostageRetreatState *const this,
-// class CHostageImprov *improv); // 20
+ if (improv->IsAtHome())
+ {
+ improv->Stop();
+ improv->Idle();
+ return;
+ }
+
+ CBasePlayer *player = improv->GetClosestVisiblePlayer(UNASSIGNED);
+
+ if (player != NULL)
+ {
+ const float farRange = 400.0f;
+ if ((player->pev->origin - improv->GetCentroid()).IsLengthGreaterThan(farRange))
+ {
+ if (player->m_iTeam == CT && !improv->IsScared())
+ {
+ improv->Stop();
+ improv->Idle();
+ return;
+ }
+ }
+ }
+
+ if (improv->IsScared() && improv->GetScareIntensity() == CHostageImprov::TERRIFIED)
+ improv->Run();
+ else
+ improv->Walk();
}
/* <44a023> ../cstrike/dlls/hostage/states/hostage_retreat.cpp:79 */
diff --git a/regamedll/dlls/multiplay_gamerules.cpp b/regamedll/dlls/multiplay_gamerules.cpp
index 41582b38..c4fe0c54 100644
--- a/regamedll/dlls/multiplay_gamerules.cpp
+++ b/regamedll/dlls/multiplay_gamerules.cpp
@@ -552,7 +552,10 @@ CHalfLifeMultiplay::CHalfLifeMultiplay(void)
m_fRoundCount = 0;
m_fIntroRoundCount = 0;
+#ifndef CSTRIKE
InstallBotControl();
+#endif // CSTRIKE
+
InstallHostageManager();
m_bSkipSpawn = m_bInCareerGame;
@@ -1938,12 +1941,12 @@ void CHalfLifeMultiplay::__MAKE_VHOOK(RestartRound)(void)
}
// check if the losing team is in a losing streak & that the loser bonus hasen't maxed out.
- if(m_iNumConsecutiveTerroristLoses > 1 && m_iLoserBonus < REWARD_LOSER_BONUS_MAX)
+ if (m_iNumConsecutiveTerroristLoses > 1 && m_iLoserBonus < REWARD_LOSER_BONUS_MAX)
{
// help out the team in the losing streak
m_iLoserBonus += REWARD_LOSER_BONUS_ADD;
}
- else if(m_iNumConsecutiveCTLoses > 1 && m_iLoserBonus < REWARD_LOSER_BONUS_MAX)
+ else if (m_iNumConsecutiveCTLoses > 1 && m_iLoserBonus < REWARD_LOSER_BONUS_MAX)
{
// help out the team in the losing streak
m_iLoserBonus += REWARD_LOSER_BONUS_ADD;
diff --git a/regamedll/dlls/plats.cpp b/regamedll/dlls/plats.cpp
index 7ced4996..b943ed6e 100644
--- a/regamedll/dlls/plats.cpp
+++ b/regamedll/dlls/plats.cpp
@@ -1195,14 +1195,14 @@ void CFuncTrackTrain::Next(void)
CPathTrack *pnext = m_ppath->LookAhead(&nextPos, pev->speed * 0.1, 1);
nextPos.z += m_height;
-#if 0
+#ifndef PLAY_GAMEDLL
pev->velocity = (nextPos - pev->origin) * 10;
#else
// TODO: fix test demo
pev->velocity.x = ((float_precision)(nextPos.x - pev->origin.x) * 10.0f);
pev->velocity.y = ((float_precision)(nextPos.y - pev->origin.y) * 10.0f);
pev->velocity.z = ((nextPos.z - pev->origin.z) * 10.0f);
-#endif
+#endif // PLAY_GAMEDLL
Vector nextFront = pev->origin;
nextFront.z -= m_height;
@@ -1223,7 +1223,7 @@ void CFuncTrackTrain::Next(void)
angles.y += fixAngleY;
// !!! All of this crap has to be done to make the angles not wrap around, revisit this.
-#if 0
+#ifndef PLAY_GAMEDLL
FixupAngles(angles);
FixupAngles(pev->angles);
#else
@@ -1232,7 +1232,8 @@ void CFuncTrackTrain::Next(void)
angles.z = Fix(angles.z);
FixupAngles(pev->angles);
-#endif
+#endif // PLAY_GAMEDLL
+
if (!pnext || (delta.x == 0 && delta.y == 0))
angles = pev->angles;
diff --git a/regamedll/dlls/vector.h b/regamedll/dlls/vector.h
index 0de54539..f6204be2 100644
--- a/regamedll/dlls/vector.h
+++ b/regamedll/dlls/vector.h
@@ -51,7 +51,7 @@ public:
{
return Vector2D(x - v.x, y - v.y);
}
-#ifdef HOOK_GAMEDLL
+#ifdef PLAY_GAMEDLL
Vector2D operator*(float_precision fl) const
{
return Vector2D((vec_t)(x * fl), (vec_t)(y * fl));
@@ -77,7 +77,7 @@ public:
{
return Vector2D(x / fl, y / fl);
}
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
float_precision Length(void) const
{
return sqrt((float_precision)(x * x + y * y));
@@ -102,11 +102,11 @@ public:
flLen = 1 / flLen;
-#ifdef HOOK_GAMEDLL
+#ifdef PLAY_GAMEDLL
return Vector2D((vec_t)(x * flLen), (vec_t)(y * flLen));
#else
return Vector2D(x * flLen, y * flLen);
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
}
bool IsLengthLessThan(float length) const
{
@@ -139,7 +139,7 @@ public:
};/* size: 8, cachelines: 1, members: 2 */
-inline float DotProduct(const Vector2D &a, const Vector2D &b)
+inline float_precision DotProduct(const Vector2D &a, const Vector2D &b)
{
return (a.x * b.x + a.y * b.y);
}
@@ -193,7 +193,7 @@ public:
{
return Vector(x - v.x, y - v.y, z - v.z);
}
-#ifdef HOOK_GAMEDLL
+#ifdef PLAY_GAMEDLL
Vector operator*(float_precision fl) const
{
return Vector((vec_t)(x * fl), (vec_t)(y * fl), (vec_t)(z * fl));
@@ -219,7 +219,7 @@ public:
{
return Vector(x / fl, y / fl, z / fl);
}
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
void CopyToArray(float *rgfl) const
{
rgfl[0] = x;
@@ -236,7 +236,7 @@ public:
//return sqrt((float_precision)(x * x + y * y + z * z));
}
- float LengthSquared(void) const
+ float_precision LengthSquared(void) const
{
return (x * x + y * y + z * z);
}
@@ -248,7 +248,7 @@ public:
{
return &x;
}
-#ifndef HOOK_GAMEDLL
+#ifndef PLAY_GAMEDLL
Vector Normalize(void)
{
float flLen = Length();
@@ -268,11 +268,11 @@ public:
vec_t fTemp = (vec_t)(1 / flLen);
return Vector(x * fTemp, y * fTemp, z * fTemp);
}
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
// for out precision normalize
Vector NormalizePrecision(void)
{
-#ifndef HOOK_GAMEDLL
+#ifndef PLAY_GAMEDLL
return Normalize();
#else
float_precision flLen = Length();
@@ -281,7 +281,7 @@ public:
flLen = 1 / flLen;
return Vector((vec_t)(x * flLen), (vec_t)(y * flLen), (vec_t)(z * flLen));
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
}
Vector2D Make2D(void) const
{
@@ -302,7 +302,7 @@ public:
{
return (LengthSquared() > length * length);
}
-#ifdef HOOK_GAMEDLL
+#ifdef PLAY_GAMEDLL
float_precision NormalizeInPlace(void)
{
float_precision flLen = Length();
@@ -322,7 +322,27 @@ public:
return flLen;
}
-#else // HOOK_GAMEDLL
+ template
+ float_precision NormalizeInPlace(void)
+ {
+ T flLen = Length();
+
+ if (flLen > 0)
+ {
+ x = (vec_t)(1 / flLen * x);
+ y = (vec_t)(1 / flLen * y);
+ z = (vec_t)(1 / flLen * z);
+ }
+ else
+ {
+ x = 0;
+ y = 0;
+ z = 1;
+ }
+
+ return flLen;
+ }
+#else // PLAY_GAMEDLL
float NormalizeInPlace(void)
{
float flLen = Length();
@@ -340,7 +360,7 @@ public:
}
return flLen;
}
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
bool IsZero(float tolerance = 0.01f) const
{
return (x > -tolerance && x < tolerance &&
@@ -362,6 +382,11 @@ inline float_precision DotProduct(const Vector &a, const Vector &b)
return (a.x * b.x + a.y * b.y + a.z * b.z);
}
+inline float_precision DotProduct2D(const Vector &a, const Vector &b)
+{
+ return (a.x * b.x + a.y * b.y);
+}
+
/* <1ba548> ../cstrike/dlls/vector.h:186 */
inline Vector CrossProduct(const Vector &a, const Vector &b)
{
@@ -401,7 +426,7 @@ inline Vector NormalizeSubtract(Vector vecStart, Vector vecDest)
{
Vector dir;
-#ifdef HOOK_GAMEDLL
+#ifdef PLAY_GAMEDLL
X floatX = (vecDest.x - vecStart.x);
Y floatY = (vecDest.y - vecStart.y);
@@ -423,17 +448,13 @@ inline Vector NormalizeSubtract(Vector vecStart, Vector vecDest)
}
#else
dir = (vecDest - vecStart).Normalize();
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
return dir;
}
-#ifdef HOOK_GAMEDLL
-template<
- typename X,
- typename Y,
- typename LenType
->
+#ifdef PLAY_GAMEDLL
+template
inline Vector NormalizeMulScalar(Vector2D vec, float scalar)
{
LenType flLen;
@@ -457,6 +478,6 @@ inline Vector NormalizeMulScalar(Vector2D vec, float scalar)
return Vector((vec_t)(floatX * scalar), (vec_t)(floatY * scalar), 0);
}
-#endif // HOOK_GAMEDLL
+#endif // PLAY_GAMEDLL
#endif // VECTOR_H
diff --git a/regamedll/engine/maintypes.h b/regamedll/engine/maintypes.h
index 454d2ce2..caf0418f 100644
--- a/regamedll/engine/maintypes.h
+++ b/regamedll/engine/maintypes.h
@@ -35,7 +35,7 @@
#include "osconfig.h"
#include "mathlib.h"
-// Has no references on server side.
+// Has no references on multiplayer library CS.
#define NOXREF
// Function body is not implemented.
#define NOBODY
@@ -43,8 +43,6 @@
#define UNTESTED
// Function is doubt reversed
#define TODOBODY
-// Function is inlined in code and has no references.
-#define INLINEBODY
#define BIT(n) (1<<(n))
diff --git a/regamedll/game_shared/GameEvent.h b/regamedll/game_shared/GameEvent.h
index 6ba3ba9d..a424a58b 100644
--- a/regamedll/game_shared/GameEvent.h
+++ b/regamedll/game_shared/GameEvent.h
@@ -140,113 +140,12 @@ enum GameEventType
NUM_GAME_EVENTS,
};
-#ifdef DEFINE_EVENT_NAMES
+#ifdef HOOK_GAMEDLL
-/* size: 96 */
-const char *GameEventName[NUM_GAME_EVENTS + 1] =
-{
- "EVENT_INVALID",
- "EVENT_WEAPON_FIRED",
- "EVENT_WEAPON_FIRED_ON_EMPTY",
- "EVENT_WEAPON_RELOADED",
- "EVENT_HE_GRENADE_EXPLODED",
- "EVENT_FLASHBANG_GRENADE_EXPLODED",
- "EVENT_SMOKE_GRENADE_EXPLODED",
- "EVENT_GRENADE_BOUNCED",
- "EVENT_BEING_SHOT_AT",
- "EVENT_PLAYER_BLINDED_BY_FLASHBANG",
- "EVENT_PLAYER_FOOTSTEP",
- "EVENT_PLAYER_JUMPED",
- "EVENT_PLAYER_DIED",
- "EVENT_PLAYER_LANDED_FROM_HEIGHT",
- "EVENT_PLAYER_TOOK_DAMAGE",
- "EVENT_HOSTAGE_DAMAGED",
- "EVENT_HOSTAGE_KILLED",
- "EVENT_DOOR",
- "EVENT_BREAK_GLASS",
- "EVENT_BREAK_WOOD",
- "EVENT_BREAK_METAL",
- "EVENT_BREAK_FLESH",
- "EVENT_BREAK_CONCRETE",
- "EVENT_BOMB_PLANTED",
- "EVENT_BOMB_DROPPED",
- "EVENT_BOMB_PICKED_UP",
- "EVENT_BOMB_BEEP",
- "EVENT_BOMB_DEFUSING",
- "EVENT_BOMB_DEFUSE_ABORTED",
- "EVENT_BOMB_DEFUSED",
- "EVENT_BOMB_EXPLODED",
- "EVENT_HOSTAGE_USED",
- "EVENT_HOSTAGE_RESCUED",
- "EVENT_ALL_HOSTAGES_RESCUED",
- "EVENT_VIP_ESCAPED",
- "EVENT_VIP_ASSASSINATED",
- "EVENT_TERRORISTS_WIN",
- "EVENT_CTS_WIN",
- "EVENT_ROUND_DRAW",
- "EVENT_ROUND_WIN",
- "EVENT_ROUND_LOSS",
- "EVENT_ROUND_START",
- "EVENT_PLAYER_SPAWNED",
- "EVENT_CLIENT_CORPSE_SPAWNED",
- "EVENT_BUY_TIME_START",
- "EVENT_PLAYER_LEFT_BUY_ZONE",
- "EVENT_DEATH_CAMERA_START",
- "EVENT_KILL_ALL",
- "EVENT_ROUND_TIME",
- "EVENT_DIE",
- "EVENT_KILL",
- "EVENT_HEADSHOT",
- "EVENT_KILL_FLASHBANGED",
- "EVENT_TUTOR_BUY_MENU_OPENNED",
- "EVENT_TUTOR_AUTOBUY",
- "EVENT_PLAYER_BOUGHT_SOMETHING",
- "EVENT_TUTOR_NOT_BUYING_ANYTHING",
- "EVENT_TUTOR_NEED_TO_BUY_PRIMARY_WEAPON",
- "EVENT_TUTOR_NEED_TO_BUY_PRIMARY_AMMO",
- "EVENT_TUTOR_NEED_TO_BUY_SECONDARY_AMMO",
- "EVENT_TUTOR_NEED_TO_BUY_ARMOR",
- "EVENT_TUTOR_NEED_TO_BUY_DEFUSE_KIT",
- "EVENT_TUTOR_NEED_TO_BUY_GRENADE",
- "EVENT_CAREER_TASK_DONE",
- "EVENT_START_RADIO_1",
- "EVENT_RADIO_COVER_ME",
- "EVENT_RADIO_YOU_TAKE_THE_POINT",
- "EVENT_RADIO_HOLD_THIS_POSITION",
- "EVENT_RADIO_REGROUP_TEAM",
- "EVENT_RADIO_FOLLOW_ME",
- "EVENT_RADIO_TAKING_FIRE",
- "EVENT_START_RADIO_2",
- "EVENT_RADIO_GO_GO_GO",
- "EVENT_RADIO_TEAM_FALL_BACK",
- "EVENT_RADIO_STICK_TOGETHER_TEAM",
- "EVENT_RADIO_GET_IN_POSITION_AND_WAIT",
- "EVENT_RADIO_STORM_THE_FRONT",
- "EVENT_RADIO_REPORT_IN_TEAM",
- "EVENT_START_RADIO_3",
- "EVENT_RADIO_AFFIRMATIVE",
- "EVENT_RADIO_ENEMY_SPOTTED",
- "EVENT_RADIO_NEED_BACKUP",
- "EVENT_RADIO_SECTOR_CLEAR",
- "EVENT_RADIO_IN_POSITION",
- "EVENT_RADIO_REPORTING_IN",
- "EVENT_RADIO_GET_OUT_OF_THERE",
- "EVENT_RADIO_NEGATIVE",
- "EVENT_RADIO_ENEMY_DOWN",
- "EVENT_END_RADIO",
- "EVENT_NEW_MATCH",
- "EVENT_PLAYER_CHANGED_TEAM",
- "EVENT_BULLET_IMPACT",
- "EVENT_GAME_COMMENCE",
- "EVENT_WEAPON_ZOOMED",
- "EVENT_HOSTAGE_CALLED_FOR_HELP",
- NULL,
-};
+#define GameEventName (*pGameEventName)
-#else // DEFINE_EVENT_NAMES
+#endif // HOOK_GAMEDLL
-extern const char *GameEventName[ NUM_GAME_EVENTS ];
-
-#endif // DEFINE_EVENT_NAMES
+extern const char *GameEventName[ NUM_GAME_EVENTS + 1 ];
#endif // GAME_EVENT_H
diff --git a/regamedll/game_shared/bot/bot_manager.cpp b/regamedll/game_shared/bot/bot_manager.cpp
index 21fd767c..dcc470f0 100644
--- a/regamedll/game_shared/bot/bot_manager.cpp
+++ b/regamedll/game_shared/bot/bot_manager.cpp
@@ -1,61 +1,158 @@
#include "precompiled.h"
+/*
+* Globals initialization
+*/
+#ifndef HOOK_GAMEDLL
+
+const char *GameEventName[NUM_GAME_EVENTS + 1] =
+{
+ "EVENT_INVALID",
+ "EVENT_WEAPON_FIRED",
+ "EVENT_WEAPON_FIRED_ON_EMPTY",
+ "EVENT_WEAPON_RELOADED",
+ "EVENT_HE_GRENADE_EXPLODED",
+ "EVENT_FLASHBANG_GRENADE_EXPLODED",
+ "EVENT_SMOKE_GRENADE_EXPLODED",
+ "EVENT_GRENADE_BOUNCED",
+ "EVENT_BEING_SHOT_AT",
+ "EVENT_PLAYER_BLINDED_BY_FLASHBANG",
+ "EVENT_PLAYER_FOOTSTEP",
+ "EVENT_PLAYER_JUMPED",
+ "EVENT_PLAYER_DIED",
+ "EVENT_PLAYER_LANDED_FROM_HEIGHT",
+ "EVENT_PLAYER_TOOK_DAMAGE",
+ "EVENT_HOSTAGE_DAMAGED",
+ "EVENT_HOSTAGE_KILLED",
+ "EVENT_DOOR",
+ "EVENT_BREAK_GLASS",
+ "EVENT_BREAK_WOOD",
+ "EVENT_BREAK_METAL",
+ "EVENT_BREAK_FLESH",
+ "EVENT_BREAK_CONCRETE",
+ "EVENT_BOMB_PLANTED",
+ "EVENT_BOMB_DROPPED",
+ "EVENT_BOMB_PICKED_UP",
+ "EVENT_BOMB_BEEP",
+ "EVENT_BOMB_DEFUSING",
+ "EVENT_BOMB_DEFUSE_ABORTED",
+ "EVENT_BOMB_DEFUSED",
+ "EVENT_BOMB_EXPLODED",
+ "EVENT_HOSTAGE_USED",
+ "EVENT_HOSTAGE_RESCUED",
+ "EVENT_ALL_HOSTAGES_RESCUED",
+ "EVENT_VIP_ESCAPED",
+ "EVENT_VIP_ASSASSINATED",
+ "EVENT_TERRORISTS_WIN",
+ "EVENT_CTS_WIN",
+ "EVENT_ROUND_DRAW",
+ "EVENT_ROUND_WIN",
+ "EVENT_ROUND_LOSS",
+ "EVENT_ROUND_START",
+ "EVENT_PLAYER_SPAWNED",
+ "EVENT_CLIENT_CORPSE_SPAWNED",
+ "EVENT_BUY_TIME_START",
+ "EVENT_PLAYER_LEFT_BUY_ZONE",
+ "EVENT_DEATH_CAMERA_START",
+ "EVENT_KILL_ALL",
+ "EVENT_ROUND_TIME",
+ "EVENT_DIE",
+ "EVENT_KILL",
+ "EVENT_HEADSHOT",
+ "EVENT_KILL_FLASHBANGED",
+ "EVENT_TUTOR_BUY_MENU_OPENNED",
+ "EVENT_TUTOR_AUTOBUY",
+ "EVENT_PLAYER_BOUGHT_SOMETHING",
+ "EVENT_TUTOR_NOT_BUYING_ANYTHING",
+ "EVENT_TUTOR_NEED_TO_BUY_PRIMARY_WEAPON",
+ "EVENT_TUTOR_NEED_TO_BUY_PRIMARY_AMMO",
+ "EVENT_TUTOR_NEED_TO_BUY_SECONDARY_AMMO",
+ "EVENT_TUTOR_NEED_TO_BUY_ARMOR",
+ "EVENT_TUTOR_NEED_TO_BUY_DEFUSE_KIT",
+ "EVENT_TUTOR_NEED_TO_BUY_GRENADE",
+ "EVENT_CAREER_TASK_DONE",
+ "EVENT_START_RADIO_1",
+ "EVENT_RADIO_COVER_ME",
+ "EVENT_RADIO_YOU_TAKE_THE_POINT",
+ "EVENT_RADIO_HOLD_THIS_POSITION",
+ "EVENT_RADIO_REGROUP_TEAM",
+ "EVENT_RADIO_FOLLOW_ME",
+ "EVENT_RADIO_TAKING_FIRE",
+ "EVENT_START_RADIO_2",
+ "EVENT_RADIO_GO_GO_GO",
+ "EVENT_RADIO_TEAM_FALL_BACK",
+ "EVENT_RADIO_STICK_TOGETHER_TEAM",
+ "EVENT_RADIO_GET_IN_POSITION_AND_WAIT",
+ "EVENT_RADIO_STORM_THE_FRONT",
+ "EVENT_RADIO_REPORT_IN_TEAM",
+ "EVENT_START_RADIO_3",
+ "EVENT_RADIO_AFFIRMATIVE",
+ "EVENT_RADIO_ENEMY_SPOTTED",
+ "EVENT_RADIO_NEED_BACKUP",
+ "EVENT_RADIO_SECTOR_CLEAR",
+ "EVENT_RADIO_IN_POSITION",
+ "EVENT_RADIO_REPORTING_IN",
+ "EVENT_RADIO_GET_OUT_OF_THERE",
+ "EVENT_RADIO_NEGATIVE",
+ "EVENT_RADIO_ENEMY_DOWN",
+ "EVENT_END_RADIO",
+ "EVENT_NEW_MATCH",
+ "EVENT_PLAYER_CHANGED_TEAM",
+ "EVENT_BULLET_IMPACT",
+ "EVENT_GAME_COMMENCE",
+ "EVENT_WEAPON_ZOOMED",
+ "EVENT_HOSTAGE_CALLED_FOR_HELP",
+ NULL,
+};
+
+#else
+
+const char *GameEventName[ NUM_GAME_EVENTS + 1 ];
+
+#endif // HOOK_GAMEDLL
+
// STL uses exceptions, but we are not compiling with them - ignore warning
#pragma warning(disable : 4530)
-//#define DEFINE_EVENT_NAMES
+const float smokeRadius = 115.0f; // for smoke grenades
-/*#include "extdll.h"
-#include "util.h"
-#include "cbase.h"
-#include "weapons.h"
-#include "soundent.h"
-#include "gamerules.h"
-#include "player.h"
-#include "client.h"
-#include "game_shared/perf_counter.h"
-
-#include "bot.h"
-#include "bot_manager.h"
-#include "nav_area.h"
-#include "bot_util.h"
-#include "hostage.h"
-
-#include "tutor.h"*/
-
-//#define CHECK_PERFORMANCE
-
-const float smokeRadius = 115.0f; ///< for smoke grenades
+// Convert name to GameEventType
+// TODO: Find more appropriate place for this function
/* <49f6d7> ../game_shared/bot/bot_manager.cpp:58 */
-NOBODY GameEventType NameToGameEvent(const char *name)
+GameEventType NameToGameEvent(const char *name)
{
- /*for (int i=0; GameEventName[i]; ++i)
+ for (int i = 0; GameEventName[i] != NULL; ++i)
+ {
if (!Q_stricmp(GameEventName[i], name))
- return static_cast(i);*/
+ return static_cast(i);
+ }
return EVENT_INVALID;
}
/* <49f733> ../game_shared/bot/bot_manager.cpp:69 */
-NOBODY CBotManager::CBotManager()
+CBotManager::CBotManager()
{
- //InitBotTrig();
+ InitBotTrig();
}
+// Invoked when the round is restarting
+
/* <49f586> ../game_shared/bot/bot_manager.cpp:78 */
void CBotManager::__MAKE_VHOOK(RestartRound)(void)
{
DestroyAllGrenades();
}
+// Invoked at the start of each frame
+
+/* <49a21c> ../game_shared/bot/bot_manager.cpp:85 */
void CBotManager::__MAKE_VHOOK(StartFrame)(void)
{
// debug smoke grenade visualization
if (cv_bot_debug.value == 5)
{
- UNTESTED
-
Vector edge, lastEdge;
ActiveGrenadeList::iterator iter = m_activeGrenadeList.begin();
@@ -115,12 +212,13 @@ void CBotManager::__MAKE_VHOOK(StartFrame)(void)
if (pPlayer->IsBot() && IsEntityValid(pPlayer))
{
CBot *pBot = static_cast(pPlayer);
-
pBot->BotThink();
}
}
}
+// Return the filename for this map's "nav map" file
+
/* <49f7a6> ../game_shared/bot/bot_manager.cpp:205 */
const char *CBotManager::GetNavMapFilename(void) const
{
@@ -129,6 +227,10 @@ const char *CBotManager::GetNavMapFilename(void) const
return filename;
}
+// Invoked when given player does given event (some events have NULL player).
+// Events are propogated to all bots.
+// TODO: This has become the game-wide event dispatcher. We should restructure this.
+
/* <49f17b> ../game_shared/bot/bot_manager.cpp:219 */
void CBotManager::__MAKE_VHOOK(OnEvent)(GameEventType event, CBaseEntity *entity, CBaseEntity *other)
{
@@ -168,6 +270,8 @@ void CBotManager::__MAKE_VHOOK(OnEvent)(GameEventType event, CBaseEntity *entity
}
}
+// Add an active grenade to the bot's awareness
+
/* <49f7ff> ../game_shared/bot/bot_manager.cpp:257 */
void CBotManager::AddGrenade(int type, CGrenade *grenade)
{
@@ -176,6 +280,8 @@ void CBotManager::AddGrenade(int type, CGrenade *grenade)
m_activeGrenadeList.push_back(ag);
}
+// The grenade entity in the world is going away
+
/* <49f95a> ../game_shared/bot/bot_manager.cpp:267 */
void CBotManager::RemoveGrenade(CGrenade *grenade)
{
@@ -191,6 +297,8 @@ void CBotManager::RemoveGrenade(CGrenade *grenade)
}
}
+// Destroy any invalid active grenades
+
/* <49f9fc> ../game_shared/bot/bot_manager.cpp:285 */
NOXREF void CBotManager::ValidateActiveGrenades(void)
{
@@ -210,7 +318,7 @@ NOXREF void CBotManager::ValidateActiveGrenades(void)
}
/* <49faf3> ../game_shared/bot/bot_manager.cpp:305 */
-NOXREF void CBotManager::DestroyAllGrenades(void)
+void CBotManager::DestroyAllGrenades(void)
{
for (ActiveGrenadeList::iterator iter = m_activeGrenadeList.begin(); iter != m_activeGrenadeList.end(); iter++)
delete *iter;
@@ -218,6 +326,8 @@ NOXREF void CBotManager::DestroyAllGrenades(void)
m_activeGrenadeList.clear();
}
+// Return true if position is inside a smoke cloud
+
/* <49fc24> ../game_shared/bot/bot_manager.cpp:317 */
bool CBotManager::IsInsideSmokeCloud(const Vector *pos)
{
@@ -225,6 +335,8 @@ bool CBotManager::IsInsideSmokeCloud(const Vector *pos)
while (iter != m_activeGrenadeList.end())
{
ActiveGrenade *ag = *iter;
+
+ // lazy validation
if (!ag->IsValid())
{
delete ag;
@@ -242,9 +354,15 @@ bool CBotManager::IsInsideSmokeCloud(const Vector *pos)
return true;
}
}
+
return false;
}
+// Return true if line intersects smoke volume
+// Determine the length of the line of sight covered by each smoke cloud,
+// and sum them (overlap is additive for obstruction).
+// If the overlap exceeds the threshold, the bot can't see through.
+
/* <49fd8b> ../game_shared/bot/bot_manager.cpp:355 */
bool CBotManager::IsLineBlockedBySmoke(const Vector *from, const Vector *to)
{
@@ -262,6 +380,7 @@ bool CBotManager::IsLineBlockedBySmoke(const Vector *from, const Vector *to)
{
ActiveGrenade *ag = *iter;
+ // lazy validation
if (!ag->IsValid())
{
delete ag;
@@ -357,7 +476,10 @@ bool CBotManager::IsLineBlockedBySmoke(const Vector *from, const Vector *to)
}
}
+ // define how much smoke a bot can see thru
const float maxSmokedLength = 0.7f * smokeRadius;
+
+ // return true if the total length of smoke-covered line-of-sight is too much
return (totalSmokedLength > maxSmokedLength);
}
diff --git a/regamedll/game_shared/bot/bot_manager.h b/regamedll/game_shared/bot/bot_manager.h
index bde086d3..576c17af 100644
--- a/regamedll/game_shared/bot/bot_manager.h
+++ b/regamedll/game_shared/bot/bot_manager.h
@@ -36,19 +36,6 @@
#pragma warning(disable : 4530)
#include
-#include "game_shared/GameEvent.h"
-
-#ifndef _WIN32
-
-//#ifndef max
-//#define max(a,b) ((a) > (b) ? (a) : (b))
-//#endif // max
-
-//#ifndef min
-//#define min(a,b) ((a) < (b) ? (a) : (b))
-//#endif // min
-
-#endif // _WIN32
class CNavArea;
class CGrenade;
@@ -82,7 +69,7 @@ private:
};/* size: 24, cachelines: 1, members: 4 */
-typedef std::list ActiveGrenadeList;
+typedef std::STD_LIST ActiveGrenadeList;
class CBotManager
{
@@ -138,16 +125,11 @@ public:
private:
-#if defined(_WIN32) && defined(HOOK_GAMEDLL)
- // The member m_activeGrenadeList on Windows must be with offset +8
- // on Linux : +4
-
- int unknown_padding;
-#endif // HOOK_GAMEDLL
-
// the list of active grenades the bots are aware of
ActiveGrenadeList m_activeGrenadeList;
//
};/* size: 12, cachelines: 1, members: 2 */
+GameEventType NameToGameEvent(const char *name);
+
#endif // BOT_MANAGER_H
diff --git a/regamedll/game_shared/bot/bot_util.cpp b/regamedll/game_shared/bot/bot_util.cpp
index df1e0559..44c37e21 100644
--- a/regamedll/game_shared/bot/bot_util.cpp
+++ b/regamedll/game_shared/bot/bot_util.cpp
@@ -57,7 +57,7 @@ bool UTIL_IsNameTaken(const char *name, bool ignoreHumans)
int UTIL_ClientsInGame(void)
{
int iCount = 0;
- for (int iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++)
+ for (int iIndex = 1; iIndex <= gpGlobals->maxClients; ++iIndex)
{
CBaseEntity *pPlayer = UTIL_PlayerByIndex(iIndex);
@@ -70,8 +70,9 @@ int UTIL_ClientsInGame(void)
if (FStrEq(STRING(pPlayer->pev->netname), ""))
continue;
- iCount++;
+ ++iCount;
}
+
return iCount;
}
@@ -79,7 +80,7 @@ int UTIL_ClientsInGame(void)
int UTIL_ActivePlayersInGame(void)
{
int iCount = 0;
- for (int iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++)
+ for (int iIndex = 1; iIndex <= gpGlobals->maxClients; ++iIndex)
{
CBaseEntity *entity = UTIL_PlayerByIndex(iIndex);
@@ -101,7 +102,7 @@ int UTIL_ActivePlayersInGame(void)
if (player->m_iJoiningState != JOINED)
continue;
- iCount++;
+ ++iCount;
}
return iCount;
@@ -112,7 +113,7 @@ int UTIL_HumansInGame(bool ignoreSpectators)
{
int iCount = 0;
- for (int iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++)
+ for (int iIndex = 1; iIndex <= gpGlobals->maxClients; ++iIndex)
{
CBaseEntity *entity = UTIL_PlayerByIndex(iIndex);
@@ -136,7 +137,7 @@ int UTIL_HumansInGame(bool ignoreSpectators)
if (ignoreSpectators && player->m_iJoiningState != JOINED)
continue;
- iCount++;
+ ++iCount;
}
return iCount;
@@ -146,7 +147,7 @@ int UTIL_HumansInGame(bool ignoreSpectators)
NOBODY int UTIL_HumansOnTeam(int teamID, bool isAlive)
{
int iCount = 0;
- for (int iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++)
+ for (int iIndex = 1; iIndex <= gpGlobals->maxClients; ++iIndex)
{
CBaseEntity *entity = UTIL_PlayerByIndex(iIndex);
@@ -170,7 +171,7 @@ NOBODY int UTIL_HumansOnTeam(int teamID, bool isAlive)
if (isAlive && !player->IsAlive())
continue;
- iCount++;
+ ++iCount;
}
return iCount;
@@ -181,7 +182,7 @@ NOBODY int UTIL_BotsInGame(void)
{
int iCount = 0;
- for (int iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++)
+ for (int iIndex = 1; iIndex <= gpGlobals->maxClients; ++iIndex)
{
CBasePlayer *pPlayer = static_cast(UTIL_PlayerByIndex(iIndex));
@@ -197,7 +198,7 @@ NOBODY int UTIL_BotsInGame(void)
if (!pPlayer->IsBot())
continue;
- iCount++;
+ ++iCount;
}
return iCount;
@@ -267,7 +268,7 @@ bool UTIL_KickBotFromTeam(TeamName kickTeam)
NOBODY bool UTIL_IsTeamAllBots(int team)
{
int botCount = 0;
- for (int i=1; i <= gpGlobals->maxClients; ++i)
+ for (int i = 1; i <= gpGlobals->maxClients; ++i)
{
CBasePlayer *player = static_cast(UTIL_PlayerByIndex(i));
@@ -301,7 +302,7 @@ NOBODY bool UTIL_IsTeamAllBots(int team)
CBasePlayer *closePlayer = NULL;
float closeDistSq = 1.0e12f; // 999999999999.9f
- for (int i = 1; i <= gpGlobals->maxClients; i++)
+ for (int i = 1; i <= gpGlobals->maxClients; ++i)
{
CBasePlayer *player = static_cast(UTIL_PlayerByIndex(i));
@@ -334,7 +335,7 @@ NOBODY /*extern*/ CBasePlayer *UTIL_GetClosestPlayer(const Vector *pos, int team
CBasePlayer *closePlayer = NULL;
float closeDistSq = 1.0e12f; // 999999999999.9f
- for (int i = 1; i <= gpGlobals->maxClients; i++)
+ for (int i = 1; i <= gpGlobals->maxClients; ++i)
{
CBasePlayer *player = static_cast(UTIL_PlayerByIndex(i));
@@ -546,7 +547,7 @@ void BotPrecache(void)
/* <4ae1b1> ../game_shared/bot/bot_util.cpp:666 */
void InitBotTrig(void)
{
- for (int i = 0; i < COS_TABLE_SIZE; i++)
+ for (int i = 0; i < COS_TABLE_SIZE; ++i)
{
float_precision angle = 2.0f * M_PI * (float)i / (float)(COS_TABLE_SIZE - 1);
cosTable[i] = cos(angle);
diff --git a/regamedll/game_shared/bot/bot_util.h b/regamedll/game_shared/bot/bot_util.h
index b906ba13..805f8bca 100644
--- a/regamedll/game_shared/bot/bot_util.h
+++ b/regamedll/game_shared/bot/bot_util.h
@@ -97,7 +97,7 @@ public:
{
return (gpGlobals->time - m_timestamp > duration) ? true : false;
}
-private:
+/*private:*/
float m_timestamp;
};/* size: 4, cachelines: 1, members: 1 */
diff --git a/regamedll/game_shared/bot/nav.h b/regamedll/game_shared/bot/nav.h
index 5248ddf4..2066d1d9 100644
--- a/regamedll/game_shared/bot/nav.h
+++ b/regamedll/game_shared/bot/nav.h
@@ -400,6 +400,7 @@ inline bool IsEntityWalkable(entvars_t *entity, unsigned int flags)
}
// Check LOS, ignoring any entities that we can walk through
+
/* <38d33d> ../game_shared/bot/nav.h:330 */
inline bool IsWalkableTraceLineClear(Vector &from, Vector &to, unsigned int flags = 0)
{
diff --git a/regamedll/game_shared/bot/nav_area.cpp b/regamedll/game_shared/bot/nav_area.cpp
index 4d4b7f63..6fc860b8 100644
--- a/regamedll/game_shared/bot/nav_area.cpp
+++ b/regamedll/game_shared/bot/nav_area.cpp
@@ -2069,17 +2069,8 @@ bool CNavArea::IsCoplanar(const CNavArea *area) const
// NOTE: pos->z is not used.
/* <4c8963> ../game_shared/bot/nav_area.cpp:2114 */
-float (*pGetZ__Vector)(const Vector *pos);
-
-float __declspec(naked) CNavArea::GetZ(const Vector *pos) const
+float CNavArea::GetZ(const Vector *pos) const
{
- __asm
- {
- jmp pGetZ__Vector
- }
- UNTESTED
- // Crash
-/*
float dx = m_extent.hi.x - m_extent.lo.x;
float dy = m_extent.hi.y - m_extent.lo.y;
@@ -2105,7 +2096,6 @@ float __declspec(naked) CNavArea::GetZ(const Vector *pos) const
float southZ = m_swZ + u * (m_extent.hi.z - m_swZ);
return northZ + v * (southZ - northZ);
-*/
}
/* <4caa36> ../game_shared/bot/nav_area.cpp:2143 */
@@ -3462,10 +3452,14 @@ const Vector *FindNearbyHidingSpot(CBaseEntity *me, const Vector *pos, CNavArea
}
// select a hiding spot at random
- int which = RANDOM_LONG(0, collector.m_count-1);
+ int which = RANDOM_LONG(0, collector.m_count - 1);
return collector.m_hidingSpot[ which ];
}
+// Return true if moving from "start" to "finish" will cross a player's line of fire
+// The path from "start" to "finish" is assumed to be a straight line
+// "start" and "finish" are assumed to be points on the ground
+
/* <4c3feb> ../game_shared/bot/nav_area.cpp:3591 */
bool IsCrossingLineOfFire(const Vector &start, const Vector &finish, CBaseEntity *ignore, int ignoreTeam)
{
@@ -4925,49 +4919,43 @@ void CNavAreaGrid::RemoveNavArea(CNavArea *area)
--m_areaCount;
}
-CNavArea *(*pGetNavArea)(const Vector *pos, float beneathLimit);
-
// Given a position, return the nav area that IsOverlapping and is *immediately* beneath it
/* <4cff5e> ../game_shared/bot/nav_area.cpp:5080 */
-CNavArea __declspec(naked) *CNavAreaGrid::GetNavArea(const Vector *pos, float beneathLimit) const
+CNavArea *CNavAreaGrid::GetNavArea(const Vector *pos, float beneathLimit) const
{
- __asm
- {
- jmp pGetNavArea
- }
-
- UNTESTED
- //TODO: Crash NavAreaList::iterator iter = list->begin()
-/*
if (m_grid == NULL)
return NULL;
+ // get list in cell that contains position
int x = WorldToGridX(pos->x);
int y = WorldToGridY(pos->y);
-
NavAreaList *list = &m_grid[x + y * m_gridSizeX];
+ // search cell list to find correct area
CNavArea *use = NULL;
- float useZ = -100000000.0f;
+ float useZ = -99999999.9f;
Vector testPos = *pos + Vector(0, 0, 5);
- if (list == NULL)
- return NULL;
-
for (NavAreaList::iterator iter = list->begin(); iter != list->end(); ++iter)
{
CNavArea *area = *iter;
+ // check if position is within 2D boundaries of this area
if (area->IsOverlapping(&testPos))
{
+ // project position onto area to get Z
float z = area->GetZ(&testPos);
+
+ // if area is above us, skip it
if (z > testPos.z)
continue;
+ // if area is too far below us, skip it
if (z < pos->z - beneathLimit)
continue;
+ // if area is higher than the one we have, use this instead
if (z > useZ)
{
use = area;
@@ -4975,36 +4963,29 @@ CNavArea __declspec(naked) *CNavAreaGrid::GetNavArea(const Vector *pos, float be
}
}
}
- return use;
-*/
-}
-CNavArea *(*pGetNearestNavArea)(const Vector *pos, bool anyZ);
+ return use;
+}
// Given a position in the world, return the nav area that is closest
// and at the same height, or beneath it.
// Used to find initial area if we start off of the mesh.
/* <4d33b4> ../game_shared/bot/nav_area.cpp:5133 */
-NOBODY __declspec(naked) CNavArea *CNavAreaGrid::GetNearestNavArea(const Vector *pos, bool anyZ) const
+CNavArea *CNavAreaGrid::GetNearestNavArea(const Vector *pos, bool anyZ) const
{
- __asm
- {
- jmp pGetNearestNavArea
- }
- //TODO: UNTESTED
- // Result: Crashed TheNavAreaList.begin()
-
-/* if (m_grid == NULL)
+ if (m_grid == NULL)
return NULL;
CNavArea *close = NULL;
float closeDistSq = 100000000.0f;
+ // quick check
close = GetNavArea(pos);
if (close)
return close;
+ // ensure source position is well behaved
Vector source;
source.x = pos->x;
source.y = pos->y;
@@ -5014,6 +4995,9 @@ NOBODY __declspec(naked) CNavArea *CNavAreaGrid::GetNearestNavArea(const Vector
source.z += HalfHumanHeight;
+ // TODO: Step incrementally using grid for speed
+
+ // find closest nav area
for (NavAreaList::iterator iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter)
{
CNavArea *area = *iter;
@@ -5022,8 +5006,11 @@ NOBODY __declspec(naked) CNavArea *CNavAreaGrid::GetNearestNavArea(const Vector
area->GetClosestPointOnArea(&source, &areaPos);
float distSq = (areaPos - source).LengthSquared();
+
+ // keep the closest area
if (distSq < closeDistSq)
{
+ // check LOS to area
if (!anyZ)
{
TraceResult result;
@@ -5035,8 +5022,8 @@ NOBODY __declspec(naked) CNavArea *CNavAreaGrid::GetNearestNavArea(const Vector
close = area;
}
}
+
return close;
-*/
}
// Given an ID, return the associated area
@@ -5063,7 +5050,7 @@ Place CNavAreaGrid::GetPlace(const Vector *pos) const
{
CNavArea *area = GetNearestNavArea(pos, true);
- if (area)
+ if (area != NULL)
{
return area->GetPlace();
}
diff --git a/regamedll/game_shared/bot/nav_area.h b/regamedll/game_shared/bot/nav_area.h
index 0e7344e8..fcd3d045 100644
--- a/regamedll/game_shared/bot/nav_area.h
+++ b/regamedll/game_shared/bot/nav_area.h
@@ -63,44 +63,40 @@ enum { MAX_BLOCKED_AREAS = 256 };
#endif // HOOK_GAMEDLL
void DestroyHidingSpots(void);
-NOBODY void StripNavigationAreas(void);
-//bool SaveNavigationMap(const char *filename);
-//NavErrorType LoadNavigationMap(void);
-NOBODY void DestroyNavigationMap(void);
+void StripNavigationAreas(void);
+bool SaveNavigationMap(const char *filename);
+NavErrorType LoadNavigationMap(void);
+void DestroyNavigationMap(void);
enum NavEditCmdType
{
EDIT_NONE,
- EDIT_DELETE,
- EDIT_SPLIT,
- EDIT_MERGE,
- EDIT_JOIN,
- EDIT_BREAK,
- EDIT_MARK,
- EDIT_ATTRIB_CROUCH,
- EDIT_ATTRIB_JUMP,
- EDIT_ATTRIB_PRECISE,
- EDIT_ATTRIB_NO_JUMP,
- EDIT_BEGIN_AREA,
- EDIT_END_AREA,
- EDIT_CONNECT,
- EDIT_DISCONNECT,
- EDIT_SPLICE,
- EDIT_TOGGLE_PLACE_MODE,
- EDIT_TOGGLE_PLACE_PAINTING,
- EDIT_PLACE_FLOODFILL,
- EDIT_PLACE_PICK,
- EDIT_MARK_UNNAMED,
- EDIT_WARP_TO_MARK,
- EDIT_SELECT_CORNER,
- EDIT_RAISE_CORNER,
- EDIT_LOWER_CORNER,
+ EDIT_DELETE, // delete current area
+ EDIT_SPLIT, // split current area
+ EDIT_MERGE, // merge adjacent areas
+ EDIT_JOIN, // define connection between areas
+ EDIT_BREAK, // break connection between areas
+ EDIT_MARK, // mark an area for further operations
+ EDIT_ATTRIB_CROUCH, // toggle crouch attribute on current area
+ EDIT_ATTRIB_JUMP, // toggle jump attribute on current area
+ EDIT_ATTRIB_PRECISE, // toggle precise attribute on current area
+ EDIT_ATTRIB_NO_JUMP, // toggle inhibiting discontinuity jumping in current area
+ EDIT_BEGIN_AREA, // begin creating a new nav area
+ EDIT_END_AREA, // end creation of the new nav area
+ EDIT_CONNECT, // connect marked area to selected area
+ EDIT_DISCONNECT, // disconnect marked area from selected area
+ EDIT_SPLICE, // create new area in between marked and selected areas
+ EDIT_TOGGLE_PLACE_MODE, // switch between normal and place editing
+ EDIT_TOGGLE_PLACE_PAINTING, // switch between "painting" places onto areas
+ EDIT_PLACE_FLOODFILL, // floodfill areas out from current area
+ EDIT_PLACE_PICK, // "pick up" the place at the current area
+ EDIT_MARK_UNNAMED, // mark an unnamed area for further operations
+ EDIT_WARP_TO_MARK, // warp a spectating local player to the selected mark
+ EDIT_SELECT_CORNER, // select a corner on the current area
+ EDIT_RAISE_CORNER, // raise a corner on the current area
+ EDIT_LOWER_CORNER, // lower a corner on the current area
};
-//#define NO_CROUCH_SPOTS false
-//class CBasePlayer;
-//class CBaseEntity;
-
enum RouteType
{
FASTEST_ROUTE,
@@ -278,14 +274,16 @@ struct SpotEncounter
NavDirType fromDir;
NavConnect to;
NavDirType toDir;
- Ray path;
- SpotOrderList spotList;
+ Ray path; // the path segment
+ SpotOrderList spotList; // list of spots to look at, in order of occurrence
};/* size: 48, cachelines: 1, members: 6 */
typedef std::STD_LIST SpotEncounterList;
typedef std::STD_LIST NavAreaList;
+// A CNavArea is a rectangular region defining a walkable area in the map
+
class CNavArea
{
public:
@@ -296,8 +294,8 @@ public:
~CNavArea();
- void ConnectTo(CNavArea *area, NavDirType dir);
- void Disconnect(CNavArea *area);
+ void ConnectTo(CNavArea *area, NavDirType dir); // connect this area to given area in given direction
+ void Disconnect(CNavArea *area); // disconnect this area from given area
void Save(FILE *fp) const;
void Save(int fd, unsigned int version);
@@ -317,73 +315,74 @@ public:
{
return m_attributeFlags;
}
- void SetPlace(Place place)
+ void SetPlace(Place place) // set place descriptor
{
m_place = place;
}
- Place GetPlace(void) const
+ Place GetPlace(void) const // get place descriptor
{
return m_place;
}
- bool IsOverlapping(const Vector *pos) const;
- bool IsOverlapping(const CNavArea *area) const;
- bool IsOverlappingX(const CNavArea *area) const;
- bool IsOverlappingY(const CNavArea *area) const;
- int GetPlayerCount(int teamID = 0, CBasePlayer *ignore = NULL) const;
- float GetZ(const Vector *pos) const;
- float GetZ(float x, float y) const;
- bool Contains(const Vector *pos) const;
- bool IsCoplanar(const CNavArea *area) const;
- void GetClosestPointOnArea(const Vector *pos, Vector *close) const;
- float GetDistanceSquaredToPoint(const Vector *pos) const;
- bool IsDegenerate(void) const;
-
- bool IsEdge(NavDirType dir) const;
-
- int GetAdjacentCount(NavDirType dir) const
+ bool IsOverlapping(const Vector *pos) const; // return true if 'pos' is within 2D extents of area
+ bool IsOverlapping(const CNavArea *area) const; // return true if 'area' overlaps our 2D extents
+ bool IsOverlappingX(const CNavArea *area) const; // return true if 'area' overlaps our X extent
+ bool IsOverlappingY(const CNavArea *area) const; // return true if 'area' overlaps our Y extent
+ int GetPlayerCount(int teamID = 0, CBasePlayer *ignore = NULL) const; // return number of players with given teamID in this area (teamID == 0 means any/all)
+ float GetZ(const Vector *pos) const; // return Z of area at (x,y) of 'pos'
+ float GetZ(float x, float y) const; // return Z of area at (x,y) of 'pos'
+ bool Contains(const Vector *pos) const; // return true if given point is on or above this area, but no others
+ bool IsCoplanar(const CNavArea *area) const; // return true if this area and given area are approximately co-planar
+ void GetClosestPointOnArea(const Vector *pos, Vector *close) const; // return closest point to 'pos' on this area - returned point in 'close'
+ float GetDistanceSquaredToPoint(const Vector *pos) const; // return shortest distance between point and this area
+ bool IsDegenerate(void) const; // return true if this area is badly formed
+ bool IsEdge(NavDirType dir) const; // return true if there are no bi-directional links on the given side
+ int GetAdjacentCount(NavDirType dir) const // return number of connected areas in given direction
{
return m_connect[dir].size();
}
- CNavArea *GetAdjacentArea(NavDirType dir, int i) const;
+ CNavArea *GetAdjacentArea(NavDirType dir, int i) const; // return the i'th adjacent area in the given direction
CNavArea *GetRandomAdjacentArea(NavDirType dir) const;
-
const NavConnectList *GetAdjacentList(NavDirType dir) const
{
return &m_connect[dir];
}
- bool IsConnected(const CNavArea *area, NavDirType dir) const;
- float ComputeHeightChange(const CNavArea *area);
+ bool IsConnected(const CNavArea *area, NavDirType dir) const; // return true if given area is connected in given direction
+ float ComputeHeightChange(const CNavArea *area); // compute change in height from this area to given area
const NavLadderList *GetLadderList(LadderDirectionType dir) const
{
return &m_ladder[dir];
}
- void ComputePortal(const CNavArea *to, NavDirType dir, Vector *center, float *halfWidth) const;
- void ComputeClosestPointInPortal(const CNavArea *to, NavDirType dir, const Vector *fromPos, Vector *closePos) const;
- NavDirType ComputeDirection(Vector *point) const;
+ void ComputePortal(const CNavArea *to, NavDirType dir, Vector *center, float *halfWidth) const; // compute portal to adjacent area
+ void ComputeClosestPointInPortal(const CNavArea *to, NavDirType dir, const Vector *fromPos, Vector *closePos) const; // compute closest point within the "portal" between to adjacent areas
+ NavDirType ComputeDirection(Vector *point) const; // return direction from this area to the given point
- void SetClearedTimestamp(int teamID)
+ // for hunting algorithm
+ void SetClearedTimestamp(int teamID) // set this area's "clear" timestamp to now
{
m_clearedTimestamp[teamID] = gpGlobals->time;
}
- float GetClearedTimestamp(int teamID)
+ float GetClearedTimestamp(int teamID) // get time this area was marked "clear"
{
return m_clearedTimestamp[teamID];
}
+
+ // hiding spots
const HidingSpotList *GetHidingSpotList(void) const
{
return &m_hidingSpotList;
}
- void ComputeHidingSpots(void);
- void ComputeSniperSpots(void);
+ void ComputeHidingSpots(void); // analyze local area neighborhood to find "hiding spots" in this area - for map learning
+ void ComputeSniperSpots(void); // analyze local area neighborhood to find "sniper spots" in this area - for map learning
- SpotEncounter *GetSpotEncounter(const CNavArea *from, const CNavArea *to);
- void ComputeSpotEncounters(void);
- void IncreaseDanger(int teamID, float amount);
+ SpotEncounter *GetSpotEncounter(const CNavArea *from, const CNavArea *to); // given the areas we are moving between, return the spots we will encounter
+ void ComputeSpotEncounters(void); // compute spot encounter data - for map learning
- float GetDanger(int teamID);
+ // danger
+ void IncreaseDanger(int teamID, float amount); // increase the danger of this area for the given team
+ float GetDanger(int teamID); // return the danger of this area (decays over time)
float GetSizeX(void) const
{
return m_extent.hi.x - m_extent.lo.x;
@@ -402,12 +401,13 @@ public:
}
const Vector *GetCorner(NavCornerType corner) const;
+ // approach areas
struct ApproachInfo
{
- NavConnect here;
- NavConnect prev;
+ NavConnect here; // the approach area
+ NavConnect prev; // the area just before the approach area on the path
NavTraverseType prevToHereHow;
- NavConnect next;
+ NavConnect next; // the area just after the approach area on the path
NavTraverseType hereToNextHow;
};
@@ -419,7 +419,9 @@ public:
{
return m_approachCount;
}
- void ComputeApproachAreas(void);
+ void ComputeApproachAreas(void); // determine the set of "approach areas" - for map learning
+
+ // A* pathfinding algorithm
static void MakeNewMarker(void)
{
IMPL(m_masterMarker)++;
@@ -448,18 +450,18 @@ public:
return m_parentHow;
}
- bool IsOpen(void) const;
- void AddToOpenList(void);
- void UpdateOnOpenList(void);
+ bool IsOpen(void) const; // true if on "open list"
+ void AddToOpenList(void); // add to open list in decreasing value order
+ void UpdateOnOpenList(void); // a smaller value has been found, update this area on the open list
void RemoveFromOpenList(void);
static bool IsOpenListEmpty(void);
- static CNavArea *PopOpenList(void);
+ static CNavArea *PopOpenList(void); // remove and return the first element of the open list
- bool IsClosed(void) const;
- void AddToClosedList(void);
+ bool IsClosed(void) const; // true if on "closed list"
+ void AddToClosedList(void); // add to the closed list
void RemoveFromClosedList(void);
- static void ClearSearchLists(void);
+ static void ClearSearchLists(void); // clears the open and closed lists for a new search
void SetTotalCost(float value)
{
@@ -478,13 +480,16 @@ public:
return m_costSoFar;
}
- void Draw(byte red, byte green, byte blue, int duration = 50);
+ // editing
+ void Draw(byte red, byte green, byte blue, int duration = 50); // draw area for debugging & editing
void DrawConnectedAreas(void);
void DrawMarkedCorner(NavCornerType corner, byte red, byte green, byte blue, int duration = 50);
- bool SplitEdit(bool splitAlongX, float splitEdge, CNavArea **outAlpha = NULL, CNavArea **outBeta = NULL);
- bool MergeEdit(CNavArea *adj);
- bool SpliceEdit(CNavArea *other);
- void RaiseCorner(NavCornerType corner, int amount);
+ bool SplitEdit(bool splitAlongX, float splitEdge, CNavArea **outAlpha = NULL, CNavArea **outBeta = NULL); // split this area into two areas at the given edge
+ bool MergeEdit(CNavArea *adj); // merge this area and given adjacent area
+ bool SpliceEdit(CNavArea *other); // create a new area between this area and given area
+ void RaiseCorner(NavCornerType corner, int amount); // raise/lower a corner (or all corners if corner == NUM_CORNERS)
+
+ // ladders
void AddLadderUp(CNavLadder *ladder)
{
m_ladder[LADDER_UP].push_back(ladder);
@@ -499,16 +504,6 @@ public:
#else
private:
#endif // HOOK_GAMEDLL
- bool IsHidingSpotCollision(const Vector *pos) const;
- void AddSpotEncounters(const CNavArea *from, NavDirType fromDir, const CNavArea *to, NavDirType toDir);
- void Strip(void);
- void FinishMerge(CNavArea *adjArea);
- void MergeAdjacentConnections(CNavArea *adjArea);
- void AssignNodes(CNavArea *area);
- void FinishSplitEdit(CNavArea *newArea, NavDirType ignoreEdge);
- void OnDestroyNotify(CNavArea *dead);
- void DecayDanger(void);
-private:
friend void ConnectGeneratedAreas(void);
friend void MergeGeneratedAreas(void);
friend void MarkJumpAreas(void);
@@ -517,85 +512,75 @@ private:
friend void DestroyNavigationMap(void);
friend void DestroyHidingSpots(void);
friend void StripNavigationAreas(void);
-
friend class CNavAreaGrid;
friend class CCSBotManager;
- void Initialize(void);
+ void Initialize(void); // to keep constructors consistent
+ static bool IMPL(m_isReset); // if true, don't bother cleaning up in destructor since everything is going away
-#ifdef HOOK_GAMEDLL
-public:
-#endif // HOOK_GAMEDLL
- static bool IMPL(m_isReset);
- static unsigned int IMPL(m_nextID);
-
-#ifdef HOOK_GAMEDLL
-private:
-#endif // HOOK_GAMEDLL
-
- unsigned int m_id;
- Extent m_extent;
- Vector m_center;
- unsigned char m_attributeFlags;
- Place m_place;
+ static unsigned int IMPL(m_nextID); // used to allocate unique IDs
+ unsigned int m_id; // unique area ID
+ Extent m_extent; // extents of area in world coords (NOTE: lo.z is not necessarily the minimum Z, but corresponds to Z at point (lo.x, lo.y), etc
+ Vector m_center; // centroid of area
+ unsigned char m_attributeFlags; // set of attribute bit flags (see NavAttributeType)
+ Place m_place; // place descriptor
+ // height of the implicit corners
float m_neZ;
float m_swZ;
enum { MAX_AREA_TEAMS = 2 };
- float m_clearedTimestamp[MAX_AREA_TEAMS];
- float m_danger[MAX_AREA_TEAMS];
- float m_dangerTimestamp[MAX_AREA_TEAMS];
+ // for hunting
+ float m_clearedTimestamp[MAX_AREA_TEAMS]; // time this area was last "cleared" of enemies
+ // danger
+ float m_danger[MAX_AREA_TEAMS]; // danger of this area, allowing bots to avoid areas where they died in the past - zero is no danger
+ float m_dangerTimestamp[MAX_AREA_TEAMS]; // time when danger value was set - used for decaying
+ void DecayDanger(void);
+
+ // hiding spots
HidingSpotList m_hidingSpotList;
+ bool IsHidingSpotCollision(const Vector *pos) const; // returns true if an existing hiding spot is too close to given position
-#ifdef HOOK_GAMEDLL
-public:
-#endif // HOOK_GAMEDLL
- SpotEncounterList m_spotEncounterList;
+ // encounter spots
+ SpotEncounterList m_spotEncounterList; // list of possible ways to move thru this area, and the spots to look at as we do
+ void AddSpotEncounters(const CNavArea *from, NavDirType fromDir, const CNavArea *to, NavDirType toDir);
+ // approach areas
enum { MAX_APPROACH_AREAS = 16 };
-
- ApproachInfo m_approach[MAX_APPROACH_AREAS];//104
+ ApproachInfo m_approach[MAX_APPROACH_AREAS];
unsigned char m_approachCount;
-#ifdef HOOK_GAMEDLL
-public:
-#endif // HOOK_GAMEDLL
+ void Strip(void); // remove "analyzed" data from nav area
+
+ // A* pathfinding algorithm
static unsigned int IMPL(m_masterMarker);
+ unsigned int m_marker; // used to flag the area as visited
+ CNavArea *m_parent; // the area just prior to this on in the search path
+ NavTraverseType m_parentHow; // how we get from parent to us
+ float m_totalCost; // the distance so far plus an estimate of the distance left
+ float m_costSoFar; // distance travelled so far
-#ifdef HOOK_GAMEDLL
-private:
-#endif // HOOK_GAMEDLL
-
- unsigned int m_marker;
- CNavArea *m_parent;
- NavTraverseType m_parentHow;
- float m_totalCost;
- float m_costSoFar;
-
-#ifdef HOOK_GAMEDLL
-public:
-#endif // HOOK_GAMEDLL
static CNavArea *IMPL(m_openList);
+ CNavArea *m_nextOpen, *m_prevOpen; // only valid if m_openMarker == m_masterMarker
+ unsigned int m_openMarker; // if this equals the current marker value, we are on the open list
-#ifdef HOOK_GAMEDLL
-private:
-#endif // HOOK_GAMEDLL
+ // connections to adjacent areas
+ NavConnectList m_connect[ NUM_DIRECTIONS ]; // a list of adjacent areas for each direction
+ NavLadderList m_ladder[ NUM_LADDER_DIRECTIONS ]; // list of ladders leading up and down from this area
- CNavArea *m_nextOpen;
- CNavArea *m_prevOpen;
- unsigned int m_openMarker;
+ CNavNode *m_node[ NUM_CORNERS ]; // nav nodes at each corner of the area
- NavConnectList m_connect[ NUM_DIRECTIONS ];
- NavLadderList m_ladder[ NUM_LADDER_DIRECTIONS ];
- CNavNode *m_node[ NUM_CORNERS ];
+ void FinishMerge(CNavArea *adjArea); // recompute internal data once nodes have been adjusted during merge
+ void MergeAdjacentConnections(CNavArea *adjArea); // for merging with "adjArea" - pick up all of "adjArea"s connections
+ void AssignNodes(CNavArea *area); // assign internal nodes to the given area
+ void FinishSplitEdit(CNavArea *newArea, NavDirType ignoreEdge); // given the portion of the original area, update its internal data
- NavAreaList m_overlapList;
+ NavAreaList m_overlapList; // list of areas that overlap this area
+ void OnDestroyNotify(CNavArea *dead); // invoked when given area is going away
- CNavArea *m_prevHash;
- CNavArea *m_nextHash;
+ CNavArea *m_prevHash, *m_nextHash; // for hash table in CNavAreaGrid
};/* size: 532, cachelines: 9, members: 32 */
@@ -635,21 +620,15 @@ inline bool CNavArea::IsOpenListEmpty(void)
/* <5a1483> ../game_shared/bot/nav_area.h:445 */
inline CNavArea *CNavArea::PopOpenList(void)
{
-#ifndef HOOK_GAMEDLL
- if (m_openList)
- {
- CNavArea *area = m_openList;
- area->RemoveFromOpenList();
- return area;
- }
-#else
if (IMPL(m_openList))
{
CNavArea *area = IMPL(m_openList);
+
+ // disconnect from list
area->RemoveFromOpenList();
return area;
}
-#endif // HOOK_GAMEDLL
+
return NULL;
}
@@ -671,9 +650,13 @@ inline void CNavArea::AddToClosedList(void)
/* <5a01f8> ../game_shared/bot/nav_area.h:473 */
inline void CNavArea::RemoveFromClosedList(void)
{
-
+ // since "closed" is defined as visited (marked) and not on open list, do nothing
}
+// The CNavAreaGrid is used to efficiently access navigation areas by world position
+// Each cell of the grid contains a list of areas that overlap it
+// Given a world position, the corresponding grid cell is ( x/cellsize, y/cellsize )
+
/* <4cf943> ../game_shared/bot/nav_area.cpp:4947 */
class CNavAreaGrid
{
@@ -681,26 +664,36 @@ public:
CNavAreaGrid(void);
~CNavAreaGrid();
- void Reset(void);
- void Initialize(float minX, float maxX, float minY, float maxY);
- void AddNavArea(CNavArea *area);
- void RemoveNavArea(CNavArea *area);
- unsigned int GetNavAreaCount(void) const
+ void Reset(void); // clear the grid to empty
+ void Initialize(float minX, float maxX, float minY, float maxY); // clear and reset the grid to the given extents
+ void AddNavArea(CNavArea *area); // add an area to the grid
+ void RemoveNavArea(CNavArea *area); // remove an area from the grid
+ unsigned int GetNavAreaCount(void) const // return total number of nav areas
{
return m_areaCount;
}
- CNavArea *GetNavArea(const Vector *pos, float beneathLimt = 120.0f) const;
+ CNavArea *GetNavArea(const Vector *pos, float beneathLimt = 120.0f) const; // given a position, return the nav area that IsOverlapping and is *immediately* beneath it
CNavArea *GetNavAreaByID(unsigned int id) const;
CNavArea *GetNearestNavArea(const Vector *pos, bool anyZ = false) const;
- Place GetPlace(const Vector *pos) const;
+ Place GetPlace(const Vector *pos) const; // return radio chatter place for given coordinate
private:
+ const float m_cellSize;
+ NavAreaList *m_grid;
+ int m_gridSizeX;
+ int m_gridSizeY;
+ float m_minX;
+ float m_minY;
+ unsigned int m_areaCount; // total number of nav areas
- inline int ComputeHashKey(unsigned int id) const
+ enum { HASH_TABLE_SIZE = 256 };
+ CNavArea *m_hashTable[HASH_TABLE_SIZE]; // hash table to optimize lookup by ID
+ inline int ComputeHashKey(unsigned int id) const // returns a hash key for the given nav area ID
{
return id & 0xFF;
}
+
inline int WorldToGridX(float wx) const
{
int x = (wx - m_minX) / m_cellSize;
@@ -723,31 +716,21 @@ private:
return y;
}
-private:
- const float m_cellSize;
- NavAreaList *m_grid;
- int m_gridSizeX;
- int m_gridSizeY;
- float m_minX;
- float m_minY;
- unsigned int m_areaCount;
-
- enum { HASH_TABLE_SIZE = 256 };
- CNavArea *m_hashTable[HASH_TABLE_SIZE];
-
};/* size: 1052, cachelines: 17, members: 8 */
class ShortestPathCost
{
public:
- float operator() (CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder)
+ float operator()(CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder)
{
if (fromArea == NULL)
{
+ // first area in path, no cost
return 0.0f;
}
else
{
+ // compute distance travelled along path so far
float dist;
if (ladder)
@@ -756,20 +739,34 @@ public:
dist = (*area->GetCenter() - *fromArea->GetCenter()).Length();
float cost = dist + fromArea->GetCostSoFar();
+
+ // if this is a "crouch" area, add penalty
if (area->GetAttributes() & NAV_CROUCH)
{
const float crouchPenalty = 20.0f;
cost += crouchPenalty * dist;
}
+
+ // if this is a "jump" area, add penalty
if (area->GetAttributes() & NAV_JUMP)
{
const float jumpPenalty = 5.0f;
cost += jumpPenalty * dist;
}
+
return cost;
}
}
-};/* size: 0, cachelines: 0, members: 0 */
+};
+
+// Find path from startArea to goalArea via an A* search, using supplied cost heuristic.
+// If cost functor returns -1 for an area, that area is considered a dead end.
+// This doesn't actually build a path, but the path is defined by following parent
+// pointers back from goalArea to startArea.
+// If 'closestArea' is non-NULL, the closest area to the goal is returned (useful if the path fails).
+// If 'goalArea' is NULL, will compute a path as close as possible to 'goalPos'.
+// If 'goalPos' is NULL, will use the center of 'goalArea' as the goal position.
+// Returns true if a path exists.
/* <4c3e99> ../game_shared/bot/nav_area.h:679 */
template
@@ -781,12 +778,16 @@ bool NavAreaBuildPath(CNavArea *startArea, CNavArea *goalArea, const Vector *goa
if (startArea == NULL)
return false;
+ // If goalArea is NULL, this function will return the closest area to the goal.
+ // However, if there is also no goal, we can't do anything.
if (goalArea == NULL && goalPos == NULL)
{
return false;
}
startArea->SetParent(NULL);
+
+ // if we are already in the goal area, build trivial path
if (startArea == goalArea)
{
goalArea->SetParent(NULL);
@@ -796,25 +797,37 @@ bool NavAreaBuildPath(CNavArea *startArea, CNavArea *goalArea, const Vector *goa
return true;
}
- Vector actualGoalPos = (goalPos) ? *goalPos : *goalArea->GetCenter();
+
+ // determine actual goal position
+ Vector actualGoalPos = (goalPos != NULL) ? (*goalPos) : (*goalArea->GetCenter());
+
+ // start search
CNavArea::ClearSearchLists();
+
+ // compute estimate of path length
+ // TODO: Cost might work as "manhattan distance"
startArea->SetTotalCost((*startArea->GetCenter() - actualGoalPos).Length());
- float initCost = costFunc(startArea, NULL, NULL);
+ float_precision initCost = costFunc(startArea, NULL, NULL);
if (initCost < 0.0f)
return false;
startArea->SetCostSoFar(initCost);
-
startArea->AddToOpenList();
+ // keep track of the area we visit that is closest to the goal
if (closestArea)
*closestArea = startArea;
float closestAreaDist = startArea->GetTotalCost();
+
+ // do A* search
while (!CNavArea::IsOpenListEmpty())
{
+ // get next area to check
CNavArea *area = CNavArea::PopOpenList();
+
+ // check if we have found the goal area
if (area == goalArea)
{
if (closestArea)
@@ -823,6 +836,7 @@ bool NavAreaBuildPath(CNavArea *startArea, CNavArea *goalArea, const Vector *goa
return true;
}
+ // search adjacent areas
bool searchFloor = true;
int dir = NORTH;
const NavConnectList *floorList = area->GetAdjacentList(NORTH);
@@ -847,14 +861,17 @@ bool NavAreaBuildPath(CNavArea *startArea, CNavArea *goalArea, const Vector *goa
NavTraverseType how;
const CNavLadder *ladder = NULL;
+ // Get next adjacent area - either on floor or via ladder
if (searchFloor)
{
+ // if exhausted adjacent connections in current direction, begin checking next direction
if (floorIter == floorList->end())
{
++dir;
if (dir == NUM_DIRECTIONS)
{
+ // checked all directions on floor - check ladders next
searchFloor = false;
ladderList = area->GetLadderList(LADDER_UP);
@@ -863,7 +880,7 @@ bool NavAreaBuildPath(CNavArea *startArea, CNavArea *goalArea, const Vector *goa
}
else
{
-
+ // start next direction
floorList = area->GetAdjacentList((NavDirType)dir);
floorIter = floorList->begin();
}
@@ -874,15 +891,19 @@ bool NavAreaBuildPath(CNavArea *startArea, CNavArea *goalArea, const Vector *goa
how = (NavTraverseType)dir;
++floorIter;
}
+ // search ladders
else
{
if (ladderIter == ladderList->end())
{
if (!ladderUp)
+ {
+ // checked both ladder directions - done
break;
-
+ }
else
{
+ // check down ladders
ladderUp = false;
ladderList = area->GetLadderList(LADDER_DOWN);
ladderIter = ladderList->begin();
@@ -893,12 +914,15 @@ bool NavAreaBuildPath(CNavArea *startArea, CNavArea *goalArea, const Vector *goa
if (ladderUp)
{
ladder = (*ladderIter);
+
+ // cannot use this ladder if the ladder bottom is hanging above our head
if (ladder->m_isDangling)
{
++ladderIter;
continue;
}
+ // do not use BEHIND connection, as its very hard to get to when going up a ladder
if (ladderTopDir == AHEAD)
newArea = ladder->m_topForwardArea;
else if (ladderTopDir == LEFT)
@@ -926,19 +950,27 @@ bool NavAreaBuildPath(CNavArea *startArea, CNavArea *goalArea, const Vector *goa
continue;
}
+ // don't backtrack
if (newArea == area)
continue;
- float newCostSoFar = costFunc(newArea, area, ladder);
+ float_precision newCostSoFar = costFunc(newArea, area, ladder);
+
+ // check if cost functor says this area is a dead-end
if (newCostSoFar < 0.0f)
continue;
if ((newArea->IsOpen() || newArea->IsClosed()) && newArea->GetCostSoFar() <= newCostSoFar)
+ {
+ // this is a worse path - skip it
continue;
-
+ }
else
{
- float newCostRemaining = (*newArea->GetCenter() - actualGoalPos).Length();
+ // compute estimate of distance left to go
+ float_precision newCostRemaining = (*newArea->GetCenter() - actualGoalPos).Length();
+
+ // track closest area to goal in case path fails
if (closestArea && newCostRemaining < closestAreaDist)
{
*closestArea = newArea;
@@ -953,21 +985,27 @@ bool NavAreaBuildPath(CNavArea *startArea, CNavArea *goalArea, const Vector *goa
newArea->RemoveFromClosedList();
if (newArea->IsOpen())
+ {
+ // area already on open list, update the list order to keep costs sorted
newArea->UpdateOnOpenList();
+ }
else
newArea->AddToOpenList();
}
}
+ // we have searched this area
area->AddToClosedList();
}
return false;
}
+// Compute distance between two areas. Return -1 if can't reach 'endArea' from 'startArea'.
+
/* <3fcb64> ../game_shared/bot/nav_area.h:914 */
template
-float NavAreaTravelDistance(CNavArea *startArea, CNavArea *endArea, CostFunctor &costFunc)
+float_precision NavAreaTravelDistance(CNavArea *startArea, CNavArea *endArea, CostFunctor &costFunc)
{
if (startArea == NULL)
return -1.0f;
@@ -978,24 +1016,29 @@ float NavAreaTravelDistance(CNavArea *startArea, CNavArea *endArea, CostFunctor
if (startArea == endArea)
return 0.0f;
+ // compute path between areas using given cost heuristic
if (NavAreaBuildPath(startArea, endArea, NULL, costFunc) == false)
return -1.0f;
- float distance = 0.0f;
+ // compute distance along path
+ float_precision distance = 0.0f;
for (CNavArea *area = endArea; area->GetParent(); area = area->GetParent())
{
distance += (*area->GetCenter() - *area->GetParent()->GetCenter()).Length();
}
+
return distance;
}
-// OVERLOAD
+// Compute distance from area to position. Return -1 if can't reach position.
+
template
float NavAreaTravelDistance(const Vector *startPos, CNavArea *startArea, const Vector *goalPos, CostFunctor &costFunc)
{
if (startArea == NULL || startPos == NULL || goalPos == NULL)
return -1.0f;
+ // compute path between areas using given cost heuristic
CNavArea *goalArea = NULL;
if (NavAreaBuildPath(startArea, TheNavAreaGrid.GetNearestNavArea(goalPos), goalPos, costFunc, &goalArea) == false)
return -1.0f;
@@ -1003,9 +1046,11 @@ float NavAreaTravelDistance(const Vector *startPos, CNavArea *startArea, const V
if (goalArea == NULL)
return -1.0f;
+ // compute distance along path
if (goalArea->GetParent() == NULL)
+ {
return (*goalPos - *startPos).Length();
-
+ }
else
{
CNavArea *area = goalArea->GetParent();
@@ -1015,10 +1060,20 @@ float NavAreaTravelDistance(const Vector *startPos, CNavArea *startArea, const V
{
distance += (*area->GetCenter() - *area->GetParent()->GetCenter()).Length();
}
+
return distance;
}
}
+// Do a breadth-first search, invoking functor on each area.
+// If functor returns 'true', continue searching from this area.
+// If functor returns 'false', the area's adjacent areas are not explored (dead end).
+// If 'maxRange' is 0 or less, no range check is done (all areas will be examined).
+// NOTE: Returns all areas that overlap range, even partially
+// TODO: Use ladder connections
+
+// helper function
+
/* <2e7572> ../game_shared/bot/nav_area.h:990 */
inline void AddAreaToOpenList(CNavArea *area, CNavArea *parent, const Vector *startPos, float maxRange)
{
@@ -1033,20 +1088,26 @@ inline void AddAreaToOpenList(CNavArea *area, CNavArea *parent, const Vector *st
if (maxRange > 0.0f)
{
+ // make sure this area overlaps range
Vector closePos;
area->GetClosestPointOnArea(startPos, &closePos);
if ((closePos - *startPos).Make2D().IsLengthLessThan(maxRange))
{
+ // compute approximate distance along path to limit travel range, too
float distAlong = parent->GetCostSoFar();
distAlong += (*area->GetCenter() - *parent->GetCenter()).Length();
area->SetCostSoFar(distAlong);
+ // allow for some fudge due to large size areas
if (distAlong <= 1.5f * maxRange)
area->AddToOpenList();
}
}
else
+ {
+ // infinite range
area->AddToOpenList();
+ }
}
}
@@ -1123,6 +1184,8 @@ void SearchSurroundingAreas(CNavArea *startArea, const Vector *startPos, Functor
}
}
+// Apply the functor to all navigation areas
+
/* <4c4137> ../game_shared/bot/nav_area.h:1109 */
template
void ForAllAreas(Functor &func)
@@ -1135,6 +1198,24 @@ void ForAllAreas(Functor &func)
}
}
+// Fuctor that returns lowest cost for farthest away areas
+// For use with FindMinimumCostArea()
+
+class FarAwayFunctor NOXREF
+{
+public:
+ float operator()(CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder)
+ {
+ if (area == fromArea)
+ return 9999999.9f;
+
+ return 1.0f/(*fromArea->GetCenter() - *area->GetCenter()).Length();
+ }
+};
+
+// Fuctor that returns lowest cost for farthest away areas
+// For use with FindMinimumCostArea()
+
/* <5497fa> ../game_shared/bot/nav_area.h:1143 */
class FarAwayFromPositionFunctor
{
@@ -1151,14 +1232,18 @@ public:
private:
const Vector *m_pos;
+
};/* size: 4, cachelines: 1, members: 1 */
+// Pick a low-cost area of "decent" size
+
/* <549838> ../game_shared/bot/nav_area.h:1162 */
template
CNavArea *FindMinimumCostArea(CNavArea *startArea, CostFunctor &costFunc)
{
const float minSize = 150.0f;
+ // collect N low-cost areas of a decent size
enum { NUM_CHEAP_AREAS = 32 };
struct
{
@@ -1172,11 +1257,15 @@ CNavArea *FindMinimumCostArea(CNavArea *startArea, CostFunctor &costFunc)
for (iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter)
{
CNavArea *area = *iter;
+
+ // skip the small areas
const Extent *extent = area->GetExtent();
if (extent->hi.x - extent->lo.x < minSize || extent->hi.y - extent->lo.y < minSize)
continue;
+ // compute cost of this area
float cost = costFunc(area, startArea, NULL);
+
if (cheapAreaSetCount < NUM_CHEAP_AREAS)
{
cheapAreaSet[cheapAreaSetCount].area = area;
@@ -1184,6 +1273,7 @@ CNavArea *FindMinimumCostArea(CNavArea *startArea, CostFunctor &costFunc)
}
else
{
+ // replace most expensive cost if this is cheaper
int expensive = 0;
for (int i = 1; i < NUM_CHEAP_AREAS; i++)
if (cheapAreaSet[i].cost > cheapAreaSet[expensive].cost)
@@ -1198,12 +1288,14 @@ CNavArea *FindMinimumCostArea(CNavArea *startArea, CostFunctor &costFunc)
}
if (cheapAreaSetCount)
{
- return cheapAreaSet[RANDOM_LONG(0, cheapAreaSetCount-1)].area;
+ // pick one of the areas at random
+ return cheapAreaSet[RANDOM_LONG(0, cheapAreaSetCount - 1)].area;
}
else
{
+ // degenerate case - no decent sized areas - pick a random area
int numAreas = TheNavAreaList.size();
- int which = RANDOM_LONG(0, numAreas-1);
+ int which = RANDOM_LONG(0, numAreas - 1);
NavAreaList::iterator iter;
for (iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter)
@@ -1219,7 +1311,7 @@ CNavArea *FindMinimumCostArea(CNavArea *startArea, CostFunctor &costFunc)
typedef const Vector *(FIND_SPOT_CBASE)(CBaseEntity *, const Vector *, CNavArea *, float, int, bool);
typedef void (CNavArea::*SAVE_FD)(int fd, unsigned int version);
-typedef void (CNavArea::*SAVE_FILE)(FILE *fp);
+typedef void (CNavArea::*SAVE_FILE)(FILE *fp) const;
typedef bool (CNavArea::*OVERLAP_VECTOR)(const Vector *pos) const;
typedef bool (CNavArea::*OVERLAP_CNAV)(const CNavArea *area) const;
@@ -1256,43 +1348,43 @@ extern float editTimestamp;
extern unsigned int BlockedID[ MAX_BLOCKED_AREAS ];
extern int BlockedIDCount;
-NOBODY bool IsHidingSpotInCover(const Vector *spot);
-NOBODY void ClassifySniperSpot(HidingSpot *spot);
-NOBODY void DestroyHidingSpots(void);
-NOBODY void EditNavAreas(NavEditCmdType cmd);
+bool IsHidingSpotInCover(const Vector *spot);
+void ClassifySniperSpot(HidingSpot *spot);
+void DestroyHidingSpots(void);
+void EditNavAreas(NavEditCmdType cmd);
bool GetGroundHeight(const Vector *pos, float *height, Vector *normal = NULL);
bool GetSimpleGroundHeight(const Vector *pos, float *height, Vector *normal = NULL);
-NOBODY inline bool IsAreaVisible(const Vector *pos, const CNavArea *area);
-NOBODY CNavArea *GetMarkedArea(void);
+CNavArea *GetMarkedArea(void);
void EditNavAreasReset(void);
-NOBODY void DrawHidingSpots(const CNavArea *area);
-NOBODY void IncreaseDangerNearby(int teamID, float amount, CNavArea *startArea, const Vector *pos, float maxRadius);
-NOBODY void DrawDanger(void);
-bool IsSpotOccupied(CBaseEntity *me, const Vector *pos);
-NOBODY const Vector *FindNearbyHidingSpot(CBaseEntity *me, const Vector *pos, CNavArea *startArea, float maxRange = 1000.0f, bool isSniper = false, bool useNearest = false);
-NOBODY const Vector *FindNearbyRetreatSpot(CBaseEntity *me, const Vector *start, CNavArea *startArea, float maxRange = 1000.0f, int avoidTeam = 0, bool useCrouchAreas = true);
-NOBODY bool IsCrossingLineOfFire(const Vector &start, const Vector &finish, CBaseEntity *ignore = NULL, int ignoreTeam = 0);
-NOBODY const Vector *FindRandomHidingSpot(CBaseEntity *me, Place place, bool isSniper = false);
-NOBODY HidingSpot *GetHidingSpotByID(unsigned int id);
+void DrawHidingSpots(const CNavArea *area);
+void IncreaseDangerNearby(int teamID, float amount, CNavArea *startArea, const Vector *pos, float maxRadius);
+void DrawDanger(void);
+bool IsSpotOccupied(CBaseEntity *me, const Vector *pos); // if a player is at the given spot, return true
+const Vector *FindNearbyHidingSpot(CBaseEntity *me, const Vector *pos, CNavArea *startArea, float maxRange = 1000.0f, bool isSniper = false, bool useNearest = false);
+const Vector *FindNearbyRetreatSpot(CBaseEntity *me, const Vector *start, CNavArea *startArea, float maxRange = 1000.0f, int avoidTeam = 0, bool useCrouchAreas = true);
+
+// return true if moving from "start" to "finish" will cross a player's line of fire
+bool IsCrossingLineOfFire(const Vector &start, const Vector &finish, CBaseEntity *ignore = NULL, int ignoreTeam = 0);
+const Vector *FindRandomHidingSpot(CBaseEntity *me, Place place, bool isSniper = false);
+HidingSpot *GetHidingSpotByID(unsigned int id);
void ApproachAreaAnalysisPrep(void);
void CleanupApproachAreaAnalysisPrep(void);
void DestroyLadders(void);
-NOBODY void DestroyNavigationMap(void);
-NOBODY void StripNavigationAreas(void);
-inline CNavArea *FindFirstAreaInDirection(const Vector *start, NavDirType dir, float range, float beneathLimit, CBaseEntity *traceIgnore, Vector *closePos);
-NOBODY inline bool testJumpDown(const Vector *fromPos, const Vector *toPos);
-NOBODY inline CNavArea *findJumpDownArea(const Vector *fromPos, NavDirType dir);
-NOBODY void ConnectGeneratedAreas(void);
-NOBODY void MergeGeneratedAreas(void);
-NOBODY inline bool IsAreaRoughlySquare(const CNavArea *area);
-NOBODY void SplitX(CNavArea *area);
-NOBODY void SplitY(CNavArea *area);
-NOBODY void SquareUpAreas(void);
-NOBODY bool TestArea(CNavNode *node, int width, int height);
-NOBODY int BuildArea(CNavNode *node, int width, int height);
-NOBODY void BuildLadders(void);
-NOBODY void MarkJumpAreas(void);
-NOBODY void GenerateNavigationAreaMesh(void);
+void DestroyNavigationMap(void);
+void StripNavigationAreas(void);
+CNavArea *FindFirstAreaInDirection(const Vector *start, NavDirType dir, float range, float beneathLimit, CBaseEntity *traceIgnore, Vector *closePos);
+bool testJumpDown(const Vector *fromPos, const Vector *toPos);
+void ConnectGeneratedAreas(void);
+void MergeGeneratedAreas(void);
+bool IsAreaRoughlySquare(const CNavArea *area);
+void SplitX(CNavArea *area);
+void SplitY(CNavArea *area);
+void SquareUpAreas(void);
+bool TestArea(CNavNode *node, int width, int height);
+int BuildArea(CNavNode *node, int width, int height);
+void BuildLadders(void);
+void MarkJumpAreas(void);
+void GenerateNavigationAreaMesh(void);
//refs
extern float (*pGetZ__Vector)(const Vector *pos);
diff --git a/regamedll/game_shared/bot/nav_file.cpp b/regamedll/game_shared/bot/nav_file.cpp
index 195b9af8..3b30de1f 100644
--- a/regamedll/game_shared/bot/nav_file.cpp
+++ b/regamedll/game_shared/bot/nav_file.cpp
@@ -142,7 +142,6 @@ void PlaceDirectory::Load(SteamFile *file)
char *GetBspFilename(const char *navFilename)
{
static char bspFilename[256];
-
Q_sprintf(bspFilename, "maps\\%s.bsp", STRING(gpGlobals->mapname));
int len = Q_strlen(bspFilename);
@@ -174,7 +173,7 @@ void CNavArea::Save(FILE *fp) const
}
/* <4f09b8> ../game_shared/bot/nav_file.cpp:212 */
-NOBODY void CNavArea::Save(int fd, unsigned int version)
+void CNavArea::Save(int fd, unsigned int version)
{
// save ID
Q_write(fd, &m_id, sizeof(unsigned int));
@@ -235,8 +234,11 @@ NOBODY void CNavArea::Save(int fd, unsigned int version)
// Save the approach areas for this area
// save number of approach areas
Q_write(fd, &m_approachCount, sizeof(unsigned char));
+
if (cv_bot_debug.value > 0.0f)
+ {
CONSOLE_ECHO(" m_approachCount = %d\n", m_approachCount);
+ }
// save approach area info
unsigned char type;
@@ -333,7 +335,7 @@ NOBODY void CNavArea::Save(int fd, unsigned int version)
}
/* <4ee669> ../game_shared/bot/nav_file.cpp:379 */
-NOBODY void CNavArea::Load(SteamFile *file, unsigned int version)
+void CNavArea::Load(SteamFile *file, unsigned int version)
{
// load ID
file->Read(&m_id, sizeof(unsigned int));
@@ -395,7 +397,7 @@ NOBODY void CNavArea::Load(SteamFile *file, unsigned int version)
else
{
// load HidingSpot objects for this area
- for (int h=0; h ../game_shared/bot/nav_file.cpp:562 */
-NOBODY NavErrorType CNavArea::PostLoad(void)
+NavErrorType CNavArea::PostLoad(void)
{
NavErrorType error = NAV_OK;
@@ -611,9 +613,10 @@ NOBODY NavErrorType CNavArea::PostLoad(void)
return error;
}
+// Changes all '/' characters into '\' characters, in place.
/* <4edbe0> ../game_shared/bot/nav_file.cpp:680 */
-void COM_FixSlashes(char *pname)
+inline void COM_FixSlashes(char *pname)
{
#ifdef _WIN32
while (*pname)
@@ -632,8 +635,10 @@ void COM_FixSlashes(char *pname)
#endif // _WIN32
}
+// Store AI navigation data to a file
+
/* <4f3e47> ../game_shared/bot/nav_file.cpp:702 */
-NOBODY bool SaveNavigationMap(const char *filename)
+bool SaveNavigationMap(const char *filename)
{
if (filename == NULL)
return false;
@@ -723,8 +728,11 @@ NOBODY bool SaveNavigationMap(const char *filename)
return true;
}
+// Load place map
+// This is legacy code - Places are stored directly in the nav file now
+
/* <4f169d> ../game_shared/bot/nav_file.cpp:811 */
-NOBODY void LoadLocationFile(const char *filename)
+void LoadLocationFile(const char *filename)
{
char locFilename[256];
Q_strcpy(locFilename, filename);
@@ -783,8 +791,10 @@ NOBODY void LoadLocationFile(const char *filename)
}
}
+// Performs a lightweight sanity-check of the specified map's nav mesh
+
/* <4f05c5> ../game_shared/bot/nav_file.cpp:876 */
-NOBODY void SanityCheckNavigationMap(const char *mapName)
+void SanityCheckNavigationMap(const char *mapName)
{
if (!mapName)
{
@@ -849,19 +859,13 @@ NOBODY void SanityCheckNavigationMap(const char *mapName)
return;
}
}
+
CONSOLE_ECHO("navigation file %s passes the sanity check.\n", navFilename);
}
-void (*pLoadNavigationMap)(void);
-
/* <4f19c7> ../game_shared/bot/nav_file.cpp:947 */
-NOBODY NavErrorType __declspec(naked) LoadNavigationMap(void)
+NavErrorType LoadNavigationMap(void)
{
- __asm
- {
- jmp pLoadNavigationMap
- }
-/*
// since the navigation map is destroyed on map change,
// if it exists it has already been loaded for this map
if (!TheNavAreaList.empty())
@@ -992,5 +996,4 @@ NOBODY NavErrorType __declspec(naked) LoadNavigationMap(void)
BuildLadders();
return NAV_OK;
-*/
}
diff --git a/regamedll/game_shared/bot/nav_file.h b/regamedll/game_shared/bot/nav_file.h
index 0facee2d..3bc04741 100644
--- a/regamedll/game_shared/bot/nav_file.h
+++ b/regamedll/game_shared/bot/nav_file.h
@@ -60,21 +60,12 @@ private:
std::vector m_directory;
};
-#ifdef HOOK_GAMEDLL
-
-#define placeDirectory (*pplaceDirectory)
-
-#endif // HOOK_GAMEDLL
-
extern PlaceDirectory placeDirectory;
-NOBODY char *GetBspFilename(const char *navFilename);
-NOBODY void COM_FixSlashes(char *pname);
-NOBODY bool SaveNavigationMap(const char *filename);
-NOBODY void LoadLocationFile(const char *filename);
-NOBODY void SanityCheckNavigationMap(const char *mapName);
-NOBODY NavErrorType LoadNavigationMap(void);
-
-extern void (*pLoadNavigationMap)(void);
+char *GetBspFilename(const char *navFilename);
+bool SaveNavigationMap(const char *filename);
+void LoadLocationFile(const char *filename);
+void SanityCheckNavigationMap(const char *mapName); // Performs a lightweight sanity-check of the specified map's nav mesh
+NavErrorType LoadNavigationMap(void);
#endif // NAV_FILE_H
diff --git a/regamedll/game_shared/bot/nav_node.cpp b/regamedll/game_shared/bot/nav_node.cpp
index a0a75221..358bdef3 100644
--- a/regamedll/game_shared/bot/nav_node.cpp
+++ b/regamedll/game_shared/bot/nav_node.cpp
@@ -5,70 +5,97 @@
*/
#ifndef HOOK_GAMEDLL
-//NavDirType Opposite[ NUM_DIRECTIONS ] = { SOUTH, WEST, NORTH, EAST };
+NavDirType Opposite[ NUM_DIRECTIONS ] = { SOUTH, WEST, NORTH, EAST };
CNavNode *CNavNode::m_list = NULL;
unsigned int CNavNode::m_listLength = 0;
-//Extent NodeMapExtent;
-
#else // HOOK_GAMEDLL
-//NavDirType Opposite[ NUM_DIRECTIONS ];
+NavDirType Opposite[ NUM_DIRECTIONS ];
CNavNode *IMPL_CLASS(CNavNode, m_list);
unsigned int IMPL_CLASS(CNavNode, m_listLength);
-//Extent NodeMapExtent;
-
#endif // HOOK_GAMEDLL
+//NOXREF Extent NodeMapExtent;
+
/* <4f79dc> ../game_shared/bot/nav_node.cpp:23 */
-CNavNode::CNavNode(const Vector *pos, const Vector *normal, class CNavNode *parent)
+CNavNode::CNavNode(const Vector *pos, const Vector *normal, CNavNode *parent)
{
-// {
-// unsigned int nextID; // 28
-// {
-// int i; // 31
-// }
-// }
+ m_pos = *pos;
+ m_normal = *normal;
+
+ static unsigned int nextID = 1;
+ m_id = nextID++;
+
+ for (int i = 0; i < NUM_DIRECTIONS; ++i)
+ m_to[i] = NULL;
+
+ m_visited = 0;
+ m_parent = parent;
+
+ m_next = IMPL(m_list);
+ IMPL(m_list) = this;
+ IMPL(m_listLength)++;
+
+ m_isCovered = FALSE;
+ m_area = NULL;
+
+ m_attributeFlags = 0;
}
+// Create a connection FROM this node TO the given node, in the given direction
+
/* <4f7a31> ../game_shared/bot/nav_node.cpp:54 */
void CNavNode::ConnectTo(CNavNode *node, NavDirType dir)
{
+ m_to[ dir ] = node;
}
+// Return node at given position
+// TODO: Need a hash table to make this lookup fast
+
/* <4f7a75> ../game_shared/bot/nav_node.cpp:64 */
const CNavNode *CNavNode::GetNode(const Vector *pos)
{
-// {
-// float const tolerance; // 66
-// {
-// const class CNavNode *node; // 68
-// {
-// float dx; // 70
-// float dy; // 71
-// float dz; // 72
-// }
-// }
-// }
+ const float tolerance = 0.45f * GenerationStepSize;
+
+ for (const CNavNode *node = IMPL(m_list); node != NULL; node = node->m_next)
+ {
+ float dx = ABS(node->m_pos.x - pos->x);
+ float dy = ABS(node->m_pos.y - pos->y);
+ float dz = ABS(node->m_pos.z - pos->z);
+
+ if (dx < tolerance && dy < tolerance && dz < tolerance)
+ return node;
+ }
+
+ return NULL;
}
+// Return true if this node is bidirectionally linked to
+// another node in the given direction
+
/* <4f7af2> ../game_shared/bot/nav_node.cpp:86 */
BOOL CNavNode::IsBiLinked(NavDirType dir) const
{
+ if (m_to[ dir ] && m_to[ dir ]->m_to[ Opposite[dir] ] == this)
+ return true;
+
+ return false;
}
+// Return true if this node is the NW corner of a quad of nodes
+// that are all bidirectionally linked
+
/* <4f7b1c> ../game_shared/bot/nav_node.cpp:100 */
BOOL CNavNode::IsClosedCell(void) const
{
-// IsBiLinked(const class CNavNode *const this,
-// enum NavDirType dir); // 102
-// IsBiLinked(const class CNavNode *const this,
-// enum NavDirType dir); // 103
-// IsBiLinked(const class CNavNode *const this,
-// enum NavDirType dir); // 104
-// IsBiLinked(const class CNavNode *const this,
-// enum NavDirType dir); // 105
+ if (IsBiLinked( SOUTH ) && IsBiLinked( EAST ) && m_to[ EAST ]->IsBiLinked( SOUTH ) && m_to[ SOUTH ]->IsBiLinked( EAST )
+ && m_to[ EAST ]->m_to[ SOUTH ] == m_to[ SOUTH ]->m_to[ EAST ])
+ return true;
+
+ return false;
}
diff --git a/regamedll/game_shared/bot/nav_node.h b/regamedll/game_shared/bot/nav_node.h
index b2416326..c89329e6 100644
--- a/regamedll/game_shared/bot/nav_node.h
+++ b/regamedll/game_shared/bot/nav_node.h
@@ -34,14 +34,11 @@
#ifdef HOOK_GAMEDLL
-//#define Opposite (*pOpposite)
-//#define m_list (*pm_list)
-//#define NodeMapExtent (*pNodeMapExtent)
+#define Opposite (*pOpposite)
#endif // HOOK_GAMEDLL
-//extern NavDirType Opposite[ NUM_DIRECTIONS ];
-//extern Extent NodeMapExtent;
+extern NavDirType Opposite[ NUM_DIRECTIONS ];
class CNavNode
{
diff --git a/regamedll/game_shared/bot/nav_path.cpp b/regamedll/game_shared/bot/nav_path.cpp
index 3743473e..f1a37acd 100644
--- a/regamedll/game_shared/bot/nav_path.cpp
+++ b/regamedll/game_shared/bot/nav_path.cpp
@@ -1,152 +1,276 @@
#include "precompiled.h"
+// Determine actual path positions
+
/* <505025> ../game_shared/bot/nav_path.cpp:24 */
-NOBODY bool CNavPath::ComputePathPositions(void)
+bool CNavPath::ComputePathPositions(void)
{
-// {
-// int i; // 34
-// {
-// const class PathSegment *from; // 36
-// class PathSegment *to; // 37
-// {
-// const NavLadderList *list; // 118
-// const_iterator iter; // 119
-// {
-// class CNavLadder *ladder; // 122
-// AddDirectionVector(Vector *v,
-// enum NavDirType dir,
-// float amount); // 128
-// }
-// end(const class list> *const this); // 120
-// operator++(_List_const_iterator *const this); // 120
-// }
-// {
-// const NavLadderList *list; // 91
-// const_iterator iter; // 92
-// end(const class list> *const this); // 93
-// {
-// class CNavLadder *ladder; // 95
-// AddDirectionVector(Vector *v,
-// enum NavDirType dir,
-// float amount); // 104
-// }
-// operator++(_List_const_iterator *const this); // 93
-// }
-// {
-// float const stepInDist; // 47
-// AddDirectionVector(Vector *v,
-// enum NavDirType dir,
-// float amount); // 48
-// {
-// class Vector2D dir; // 59
-// float const pushDist; // 63
-// DirectionToVector2D(NavDirType dir,
-// class Vector2D *v); // 60
-// {
-// int j; // 71
-// }
-// }
-// }
-// }
-// }
+ if (m_segmentCount == 0)
+ return false;
+
+ // start in first area's center
+ m_path[0].pos = *m_path[0].area->GetCenter();
+ m_path[0].ladder = NULL;
+ m_path[0].how = NUM_TRAVERSE_TYPES;
+
+ for (int i = 1; i < m_segmentCount; ++i)
+ {
+ const PathSegment *from = &m_path[i - 1];
+ PathSegment *to = &m_path[ i ];
+
+ // walk along the floor to the next area
+ if (to->how <= GO_WEST)
+ {
+ to->ladder = NULL;
+
+ // compute next point, keeping path as straight as possible
+ from->area->ComputeClosestPointInPortal(to->area, (NavDirType)to->how, &from->pos, &to->pos);
+
+ // move goal position into the goal area a bit
+ // how far to "step into" an area - must be less than min area size
+ const float stepInDist = 5.0f;
+ AddDirectionVector(&to->pos, (NavDirType)to->how, stepInDist);
+
+ // we need to walk out of "from" area, so keep Z where we can reach it
+ to->pos.z = from->area->GetZ(&to->pos);
+
+ // if this is a "jump down" connection, we must insert an additional point on the path
+ if (to->area->IsConnected(from->area, NUM_DIRECTIONS) == false)
+ {
+ // this is a "jump down" link
+ // compute direction of path just prior to "jump down"
+ Vector2D dir;
+ DirectionToVector2D((NavDirType)to->how, &dir);
+
+ // shift top of "jump down" out a bit to "get over the ledge"
+ const float pushDist = 25.0f;
+ to->pos.x += pushDist * dir.x;
+ to->pos.y += pushDist * dir.y;
+
+ // insert a duplicate node to represent the bottom of the fall
+ if (m_segmentCount < MAX_PATH_SEGMENTS - 1)
+ {
+ // copy nodes down
+ for (int j = m_segmentCount; j > i; --j)
+ m_path[j] = m_path[j - 1];
+
+ // path is one node longer
+ ++m_segmentCount;
+
+ // move index ahead into the new node we just duplicated
+ ++i;
+
+ m_path[i].pos.x = to->pos.x + pushDist * dir.x;
+ m_path[i].pos.y = to->pos.y + pushDist * dir.y;
+
+ // put this one at the bottom of the fall
+ m_path[i].pos.z = to->area->GetZ(&m_path[i].pos);
+ }
+ }
+ }
+ // to get to next area, must go up a ladder
+ else if (to->how == GO_LADDER_UP)
+ {
+ // find our ladder
+ const NavLadderList *list = from->area->GetLadderList(LADDER_UP);
+ NavLadderList::const_iterator iter;
+ for (iter = list->begin(); iter != list->end(); ++iter)
+ {
+ CNavLadder *ladder = *iter;
+
+ // can't use "behind" area when ascending...
+ if (ladder->m_topForwardArea == to->area || ladder->m_topLeftArea == to->area || ladder->m_topRightArea == to->area)
+ {
+ to->ladder = ladder;
+ to->pos = ladder->m_bottom;
+ AddDirectionVector(&to->pos, ladder->m_dir, 2.0f * HalfHumanWidth);
+ break;
+ }
+ }
+
+ if (iter == list->end())
+ {
+ //PrintIfWatched( "ERROR: Can't find ladder in path\n" );
+ return false;
+ }
+ }
+ // to get to next area, must go down a ladder
+ else if (to->how == GO_LADDER_DOWN)
+ {
+ // find our ladder
+ const NavLadderList *list = from->area->GetLadderList(LADDER_DOWN);
+ NavLadderList::const_iterator iter;
+ for (iter = list->begin(); iter != list->end(); ++iter)
+ {
+ CNavLadder *ladder = *iter;
+
+ if (ladder->m_bottomArea == to->area)
+ {
+ to->ladder = ladder;
+ to->pos = ladder->m_top;
+ AddDirectionVector(&to->pos, OppositeDirection(ladder->m_dir), 2.0f * HalfHumanWidth);
+ break;
+ }
+ }
+ if (iter == list->end())
+ {
+ //PrintIfWatched( "ERROR: Can't find ladder in path\n" );
+ return false;
+ }
+ }
+ }
+
+ return true;
}
+// Return true if position is at the end of the path
+
/* <50525f> ../game_shared/bot/nav_path.cpp:148 */
-NOBODY bool CNavPath::IsAtEnd(const Vector &pos) const
+bool CNavPath::IsAtEnd(const Vector &pos) const
{
-// {
-// float const epsilon; // 153
-// operator-(const Vector *const this,
-// const Vector &v); // 154
-// IsLengthLessThan(const Vector *const this,
-// float length); // 154
-// }
+ if (!IsValid())
+ return false;
+
+ const float epsilon = 20.0f;
+ return (pos - GetEndpoint()).IsLengthLessThan(epsilon);
}
+// Return length of path from start to finish
+
/* <5052f6> ../game_shared/bot/nav_path.cpp:161 */
-NOBODY float CNavPath::GetLength(void) const
+float CNavPath::GetLength(void) const
{
-// {
-// float length; // 163
-// {
-// int i; // 164
-// operator-(const Vector *const this,
-// const Vector &v); // 166
-// Length(const Vector *const this); // 166
-// }
-// }
+ float length = 0.0f;
+ for (int i = 1; i < GetSegmentCount(); ++i)
+ {
+ length += (m_path[i].pos - m_path[i - 1].pos).Length();
+ }
+
+ return length;
}
+// Return point a given distance along the path - if distance is out of path bounds, point is clamped to start/end
+// TODO: Be careful of returning "positions" along one-way drops, ladders, etc.
+
/* <50537f> ../game_shared/bot/nav_path.cpp:177 */
-NOBODY bool CNavPath::GetPointAlongPath(float distAlong, Vector *pointOnPath) const
+NOXREF bool CNavPath::GetPointAlongPath(float distAlong, Vector *pointOnPath) const
{
-// {
-// float lengthSoFar; // 188
-// float segmentLength; // 189
-// Vector dir; // 190
-// {
-// int i; // 191
-// operator-(const Vector *const this,
-// const Vector &v); // 193
-// Length(const Vector *const this); // 194
-// {
-// float delta; // 199
-// float t; // 200
-// operator*(float fl,
-// const Vector &v); // 202
-// operator+(const Vector *const this,
-// const Vector &v); // 202
-// }
-// }
-// }
+ if (!IsValid() || pointOnPath == NULL)
+ return false;
+
+ if (distAlong <= 0.0f)
+ {
+ *pointOnPath = m_path[0].pos;
+ return true;
+ }
+
+ float lengthSoFar = 0.0f;
+ float segmentLength;
+ Vector dir;
+ for (int i = 1; i < GetSegmentCount(); ++i)
+ {
+ dir = m_path[i].pos - m_path[i - 1].pos;
+ segmentLength = dir.Length();
+
+ if (segmentLength + lengthSoFar >= distAlong)
+ {
+ // desired point is on this segment of the path
+ float delta = distAlong - lengthSoFar;
+ float t = delta / segmentLength;
+
+ *pointOnPath = m_path[i].pos + t * dir;
+
+ return true;
+ }
+
+ lengthSoFar += segmentLength;
+ }
+
+ *pointOnPath = m_path[ GetSegmentCount() - 1 ].pos;
+ return true;
}
+// Return the node index closest to the given distance along the path without going over - returns (-1) if error
+
/* <5054da> ../game_shared/bot/nav_path.cpp:218 */
-NOBODY int CNavPath::GetSegmentIndexAlongPath(float distAlong) const
+int CNavPath::GetSegmentIndexAlongPath(float distAlong) const
{
-// {
-// float lengthSoFar; // 228
-// Vector dir; // 229
-// {
-// int i; // 230
-// operator-(const Vector *const this,
-// const Vector &v); // 232
-// Length(const Vector *const this); // 232
-// }
-// }
+ if (!IsValid())
+ return -1;
+
+ if (distAlong <= 0.0f)
+ {
+ return 0;
+ }
+
+ float lengthSoFar = 0.0f;
+ Vector dir;
+ for (int i = 1; i < GetSegmentCount(); ++i)
+ {
+ lengthSoFar += (m_path[i].pos - m_path[i - 1].pos).Length();
+
+ if (lengthSoFar > distAlong)
+ {
+ return i - 1;
+ }
+ }
+
+ return GetSegmentCount() - 1;
}
+// Compute closest point on path to given point
+// NOTE: This does not do line-of-sight tests, so closest point may be thru the floor, etc
+
/* <50557e> ../game_shared/bot/nav_path.cpp:250 */
-NOBODY bool CNavPath::FindClosestPointOnPath(const Vector *worldPos, int startIndex, int endIndex, Vector *close) const
+NOXREF bool CNavPath::FindClosestPointOnPath(const Vector *worldPos, int startIndex, int endIndex, Vector *close) const
{
-// {
-// Vector along; // 255
-// Vector toWorldPos; // 255
-// Vector pos; // 256
-// const Vector *from; // 257
-// const Vector *to; // 257
-// float length; // 258
-// float closeLength; // 259
-// float closeDistSq; // 260
-// float distSq; // 261
-// {
-// int i; // 263
-// NormalizeInPlace(Vector *const this); // 272
-// operator-(const Vector *const this,
-// const Vector &v); // 275
-// DotProduct(Vector &a,
-// const Vector &b); // 278
-// operator-(const Vector *const this,
-// const Vector &v); // 288
-// LengthSquared(const Vector *const this); // 288
-// operator-(const Vector *const this,
-// const Vector &v); // 269
-// operator*(float fl,
-// const Vector &v); // 286
-// operator+(const Vector *const this,
-// const Vector &v); // 286
-// }
-// }
+ if (!IsValid() || close == NULL)
+ return false;
+
+ Vector along, toWorldPos;
+ Vector pos;
+ const Vector *from, *to;
+ float length;
+ float closeLength;
+ float closeDistSq = 9999999999.9;
+ float distSq;
+
+ for (int i = startIndex; i <= endIndex; ++i)
+ {
+ from = &m_path[i - 1].pos;
+ to = &m_path[i].pos;
+
+ // compute ray along this path segment
+ along = *to - *from;
+
+ // make it a unit vector along the path
+ length = along.NormalizeInPlace();
+
+ // compute vector from start of segment to our point
+ toWorldPos = *worldPos - *from;
+
+ // find distance of closest point on ray
+ closeLength = DotProduct(toWorldPos, along);
+
+ // constrain point to be on path segment
+ if (closeLength <= 0.0f)
+ pos = *from;
+ else if (closeLength >= length)
+ pos = *to;
+ else
+ pos = *from + closeLength * along;
+
+ distSq = (pos - *worldPos).LengthSquared();
+
+ // keep the closest point so far
+ if (distSq < closeDistSq)
+ {
+ closeDistSq = distSq;
+ *close = pos;
+ }
+ }
+
+ return true;
}
// Build trivial path when start and goal are in the same nav area
@@ -183,456 +307,827 @@ bool CNavPath::BuildTrivialPath(const Vector *start, const Vector *goal)
return true;
}
+// Draw the path for debugging
+
/* <505853> ../game_shared/bot/nav_path.cpp:340 */
-NOBODY void CNavPath::Draw(void)
+void CNavPath::Draw(void)
{
-// {
-// int i; // 345
-// operator+(const Vector *const this,
-// const Vector &v); // 347
-// operator+(const Vector *const this,
-// const Vector &v); // 347
-// }
+ if (!IsValid())
+ return;
+
+ for (int i = 1; i < m_segmentCount; ++i)
+ {
+ UTIL_DrawBeamPoints(m_path[i - 1].pos + Vector(0, 0, HalfHumanHeight), m_path[i].pos + Vector(0, 0, HalfHumanHeight), 2, 255, 75, 0);
+ }
}
+// Check line of sight from 'anchor' node on path to subsequent nodes until
+// we find a node that can't been seen from 'anchor'
+
/* <505931> ../game_shared/bot/nav_path.cpp:357 */
-NOBODY int CNavPath::FindNextOccludedNode(int anchor)
+int CNavPath::FindNextOccludedNode(int anchor_)
{
-// {
-// int lastVisible; // 359
-// {
-// int i; // 360
-// {
-// Vector anchorPlusHalf; // 372
-// Vector iPlusHalf; // 373
-// Vector anchorPlusFull; // 380
-// Vector iPlusFull; // 381
-// IsWalkableTraceLineClear(Vector &from,
-// Vector &to,
-// unsigned int flags); // 366
-// operator+(const Vector *const this,
-// const Vector &v); // 372
-// IsWalkableTraceLineClear(Vector &from,
-// Vector &to,
-// unsigned int flags); // 374
-// operator+(const Vector *const this,
-// const Vector &v); // 373
-// operator+(const Vector *const this,
-// const Vector &v); // 380
-// IsWalkableTraceLineClear(Vector &from,
-// Vector &to,
-// unsigned int flags); // 382
-// operator+(const Vector *const this,
-// const Vector &v); // 381
-// }
-// }
-// }
+ int lastVisible = anchor_;
+ for (int i = anchor_ + 1; i < m_segmentCount; ++i)
+ {
+ // don't remove ladder nodes
+ if (m_path[i].ladder)
+ return i;
+
+ if (!IsWalkableTraceLineClear(m_path[ anchor_ ].pos, m_path[ i ].pos))
+ {
+ // cant see this node from anchor node
+ return i;
+ }
+
+ Vector anchorPlusHalf = m_path[ anchor_ ].pos + Vector(0, 0, HalfHumanHeight);
+ Vector iPlusHalf = m_path[ i ].pos + Vector(0, 0, HalfHumanHeight);
+ if (!IsWalkableTraceLineClear(anchorPlusHalf, iPlusHalf))
+ {
+ // cant see this node from anchor node
+ return i;
+ }
+
+ Vector anchorPlusFull = m_path[ anchor_ ].pos + Vector(0, 0, HumanHeight);
+ Vector iPlusFull = m_path[ i ].pos + Vector(0, 0, HumanHeight);
+ if (!IsWalkableTraceLineClear(anchorPlusFull, iPlusFull))
+ {
+ // cant see this node from anchor node
+ return i;
+ }
+ }
+
+ return m_segmentCount;
}
+// Smooth out path, removing redundant nodes
+
/* <505c26> ../game_shared/bot/nav_path.cpp:396 */
-NOBODY void CNavPath::Optimize(void)
+void CNavPath::Optimize(void)
{
+ // DONT USE THIS: Optimizing the path results in cutting thru obstacles
+#if 0
+ if (m_segmentCount < 3)
+ return;
+
+ int anchor_ = 0;
+ while (anchor_ < m_segmentCount)
+ {
+ int occluded = FindNextOccludedNode(anchor_);
+ int nextAnchor = occluded - 1;
+
+ if (nextAnchor > anchor_)
+ {
+ // remove redundant nodes between anchor and nextAnchor
+ int removeCount = nextAnchor - anchor_ - 1;
+ if (removeCount > 0)
+ {
+ for (int i = nextAnchor; i < m_segmentCount; ++i)
+ {
+ m_path[i - removeCount] = m_path[i];
+ }
+ m_segmentCount -= removeCount;
+ }
+ }
+
+ ++anchor_;
+ }
+#endif
}
/* <505c6d> ../game_shared/bot/nav_path.cpp:436 */
-NOBODY CNavPathFollower::CNavPathFollower(void)
+CNavPathFollower::CNavPathFollower(void)
{
-// CStuckMonitor(CStuckMonitor *const this); // 436
+ m_improv = NULL;
+ m_path = NULL;
+
+ m_segmentIndex = 0;
+ m_isLadderStarted = false;
+
+ m_isDebug = false;
}
/* <505cce> ../game_shared/bot/nav_path.cpp:447 */
-NOBODY void CNavPathFollower::Reset(void)
+void CNavPathFollower::Reset(void)
{
-// Reset(CStuckMonitor *const this); // 452
+ m_segmentIndex = 1;
+ m_isLadderStarted = false;
+
+ m_stuckMonitor.Reset();
}
+// Move improv along path
+
/* <507c31> ../game_shared/bot/nav_path.cpp:459 */
-NOBODY void CNavPathFollower::Update(float deltaT, bool avoidObstacles)
+void CNavPathFollower::Update(float deltaT, bool avoidObstacles)
{
-// {
-// const class PathSegment *node; // 464
-// float const closeRange; // 507
-// float const aheadRange; // 523
-// bool isApproachingJumpArea; // 529
-// float const giveUpTime; // 596
-// operator[](CNavPath *const this,
-// int i); // 464
-// Invalidate(CNavPath *const this); // 600
-// {
-// const Vector *approachPos; // 476
-// const Vector *departPos; // 477
-// operator[](CNavPath *const this,
-// int i); // 480
-// operator[](CNavPath *const this,
-// int i); // 483
-// }
-// operator-(const Vector *const this,
-// const Vector &v); // 508
-// IsLengthLessThan(const Vector *const this,
-// float length); // 508
-// FindPathPoint(CNavPathFollower *const this,
-// float aheadRange,
-// Vector *point,
-// int *prevIndex); // 524
-// {
-// float const crouchRange; // 547
-// bool didCrouch; // 548
-// {
-// int i; // 549
-// {
-// const class CNavArea *to; // 551
-// Vector close; // 560
-// operator-(const Vector *const this,
-// const Vector &v); // 563
-// IsLengthGreaterThan(const class Vector2D *const this,
-// float length); // 563
-// operator[](CNavPath *const this,
-// int i); // 551
-// }
-// }
-// }
-// GetDuration(const class CStuckMonitor *const this); // 597
-// GetEndpoint(const class CNavPath *const this); // 599
-// {
-// float const closeRange; // 608
-// class Vector2D to; // 609
-// IsLengthLessThan(const class Vector2D *const this,
-// float length); // 610
-// {
-// const class PathSegment *nextNode; // 614
-// operator[](CNavPath *const this,
-// int i); // 614
-// GetEndpoint(const class CNavPath *const this); // 620
-// Invalidate(CNavPath *const this); // 621
-// Invalidate(CNavPath *const this); // 629
-// }
-// }
-// operator+(const Vector *const this,
-// const Vector &v); // 587
-// Vector(Vector *const this,
-// const Vector &v); // 587
-// operator+(const Vector *const this,
-// const Vector &v); // 588
-// Vector(Vector *const this,
-// const Vector &v); // 588
-// Invalidate(CNavPath *const this); // 515
-// }
+ if (m_path == NULL || m_path->IsValid() == false)
+ return;
+
+ const CNavPath::PathSegment *node = (*m_path)[m_segmentIndex];
+
+ if (node == NULL)
+ {
+ m_improv->OnMoveToFailure(m_path->GetEndpoint(), IImprovEvent::FAIL_INVALID_PATH);
+ m_path->Invalidate();
+ return;
+ }
+
+ // handle ladders
+ if (node->ladder)
+ {
+ const Vector *approachPos = NULL;
+ const Vector *departPos = NULL;
+
+ if (m_segmentIndex)
+ approachPos = &(*m_path)[m_segmentIndex - 1]->pos;
+
+ if (m_segmentIndex < m_path->GetSegmentCount() - 1)
+ departPos = &(*m_path)[m_segmentIndex + 1]->pos;
+
+ if (!m_isLadderStarted)
+ {
+ // set up ladder movement
+ m_improv->StartLadder(node->ladder, node->how, approachPos, departPos);
+ m_isLadderStarted = true;
+ }
+
+ // move improv along ladder
+ if (m_improv->TraverseLadder(node->ladder, node->how, approachPos, departPos, deltaT))
+ {
+ // completed ladder
+ ++m_segmentIndex;
+ }
+
+ return;
+ }
+
+ // reset ladder init flag
+ m_isLadderStarted = false;
+
+ // Check if we reached the end of the path
+ const float closeRange = 20.0f;
+ if ((m_improv->GetFeet() - node->pos).IsLengthLessThan(closeRange))
+ {
+ ++m_segmentIndex;
+
+ if (m_segmentIndex >= m_path->GetSegmentCount())
+ {
+ m_improv->OnMoveToSuccess(m_path->GetEndpoint());
+ m_path->Invalidate();
+ return;
+ }
+ }
+
+ m_goal = node->pos;
+
+ const float aheadRange = 300.0f;
+ m_segmentIndex = FindPathPoint(aheadRange, &m_goal, &m_behindIndex);
+ if (m_segmentIndex >= m_path->GetSegmentCount())
+ m_segmentIndex = m_path->GetSegmentCount() - 1;
+
+ bool isApproachingJumpArea = false;
+
+ // Crouching
+ if (!m_improv->IsUsingLadder())
+ {
+ // because hostage crouching is not really supported by the engine,
+ // if we are standing in a crouch area, we must crouch to avoid collisions
+ if (m_improv->GetLastKnownArea() && (m_improv->GetLastKnownArea()->GetAttributes() & NAV_CROUCH) && !(m_improv->GetLastKnownArea()->GetAttributes() & NAV_JUMP))
+ {
+ m_improv->Crouch();
+ }
+
+ // if we are approaching a crouch area, crouch
+ // if there are no crouch areas coming up, stand
+ const float crouchRange = 50.0f;
+ bool didCrouch = false;
+ for (int i = m_segmentIndex; i < m_path->GetSegmentCount(); ++i)
+ {
+ const CNavArea *to = (*m_path)[i]->area;
+
+ // if there is a jump area on the way to the crouch area, don't crouch as it messes up the jump
+ if (to->GetAttributes() & NAV_JUMP)
+ {
+ isApproachingJumpArea = true;
+ break;
+ }
+
+ Vector close;
+ to->GetClosestPointOnArea(&m_improv->GetCentroid(), &close);
+
+ if ((close - m_improv->GetFeet()).Make2D().IsLengthGreaterThan(crouchRange))
+ break;
+
+ if (to->GetAttributes() & NAV_CROUCH)
+ {
+ m_improv->Crouch();
+ didCrouch = true;
+ break;
+ }
+ }
+
+ if (!didCrouch && !m_improv->IsJumping())
+ {
+ // no crouch areas coming up
+ m_improv->StandUp();
+ }
+ } // end crouching logic
+
+ if (m_isDebug)
+ {
+ m_path->Draw();
+ UTIL_DrawBeamPoints(m_improv->GetCentroid(), m_goal + Vector(0, 0, StepHeight), 1, 255, 0, 255);
+ UTIL_DrawBeamPoints(m_goal + Vector(0, 0, StepHeight), m_improv->GetCentroid(), 1, 255, 0, 255);
+ }
+
+ // check if improv becomes stuck
+ m_stuckMonitor.Update(m_improv);
+
+ // if improv has been stuck for too long, give up
+ const float giveUpTime = 2.0f;
+ if (m_stuckMonitor.GetDuration() > giveUpTime)
+ {
+ m_improv->OnMoveToFailure(m_path->GetEndpoint(), IImprovEvent::FAIL_STUCK);
+ m_path->Invalidate();
+ return;
+ }
+
+ // if our goal is high above us, we must have fallen
+ if (m_goal.z - m_improv->GetFeet().z > JumpCrouchHeight)
+ {
+ const float closeRange = 75.0f;
+ Vector2D to(m_improv->GetFeet().x - m_goal.x, m_improv->GetFeet().y - m_goal.y);
+
+ if (to.IsLengthLessThan(closeRange))
+ {
+ // we can't reach the goal position
+ // check if we can reach the next node, in case this was a "jump down" situation
+ const CNavPath::PathSegment *nextNode = (*m_path)[m_behindIndex + 1];
+ if (m_behindIndex >= 0 && nextNode)
+ {
+ if (nextNode->pos.z - m_improv->GetFeet().z > JumpCrouchHeight)
+ {
+ // the next node is too high, too - we really did fall of the path
+ m_improv->OnMoveToFailure(m_path->GetEndpoint(), IImprovEvent::FAIL_FELL_OFF);
+ m_path->Invalidate();
+ return;
+ }
+ }
+ else
+ {
+ // fell trying to get to the last node in the path
+ m_improv->OnMoveToFailure(m_path->GetEndpoint(), IImprovEvent::FAIL_FELL_OFF);
+ m_path->Invalidate();
+ return;
+ }
+ }
+ }
+
+ // avoid small obstacles
+ if (avoidObstacles && !isApproachingJumpArea && !m_improv->IsJumping() && m_segmentIndex < m_path->GetSegmentCount() - 1)
+ {
+ FeelerReflexAdjustment(&m_goal);
+
+ // currently, this is only used for hostages, and their collision physics stinks
+ // do more feeler checks to avoid short obstacles
+ /*
+ const float inc = 0.25f;
+ for (float t = 0.5f; t < 1.0f; t += inc)
+ {
+ FeelerReflexAdjustment(&m_goal, t * StepHeight);
+ }
+ */
+ }
+
+ // move improv along path
+ m_improv->TrackPath(m_goal, deltaT);
}
+// Return the closest point to our current position on our current path
+// If "local" is true, only check the portion of the path surrounding m_pathIndex
+
/* <505d18> ../game_shared/bot/nav_path.cpp:662 */
-NOBODY int CNavPathFollower::FindOurPositionOnPath(Vector *close, bool local) const
+int CNavPathFollower::FindOurPositionOnPath(Vector *close, bool local) const
{
-// {
-// Vector along; // 667
-// Vector toFeet; // 667
-// Vector feet; // 668
-// Vector eyes; // 669
-// Vector pos; // 670
-// const Vector *from; // 671
-// const Vector *to; // 671
-// float length; // 672
-// float closeLength; // 673
-// float closeDistSq; // 674
-// int closeIndex; // 675
-// float distSq; // 676
-// int start; // 678
-// int end; // 678
-// Vector(Vector *const this,
-// const Vector &v); // 668
-// Vector(Vector *const this,
-// const Vector &v); // 669
-// {
-// int i; // 696
-// NormalizeInPlace(Vector *const this); // 705
-// operator-(const Vector *const this,
-// const Vector &v); // 708
-// DotProduct(Vector &a,
-// const Vector &b); // 711
-// operator-(const Vector *const this,
-// const Vector &v); // 721
-// LengthSquared(const Vector *const this); // 721
-// {
-// Vector probe; // 727
-// operator+(const Vector *const this,
-// const Vector &v); // 727
-// IsWalkableTraceLineClear(Vector &from,
-// Vector &to,
-// unsigned int flags); // 728
-// }
-// operator[](CNavPath *const this,
-// int i); // 698
-// operator[](CNavPath *const this,
-// int i); // 699
-// operator-(const Vector *const this,
-// const Vector &v); // 702
-// operator*(float fl,
-// const Vector &v); // 719
-// operator+(const Vector *const this,
-// const Vector &v); // 719
-// }
-// }
+ Vector along, toFeet;
+ Vector feet = m_improv->GetFeet();
+ Vector eyes = m_improv->GetEyes();
+ Vector pos;
+ const Vector *from, *to;
+ float_precision length;
+ float closeLength;
+ float closeDistSq = 1.0e10;
+ int closeIndex = -1;
+ float_precision distSq;
+ int start, end;
+
+ if (!m_path->IsValid())
+ return -1;
+
+ if (local)
+ {
+ start = m_segmentIndex - 3;
+ if (start < 1)
+ start = 1;
+
+ end = m_segmentIndex + 3;
+ if (end > m_path->GetSegmentCount())
+ end = m_path->GetSegmentCount();
+ }
+ else
+ {
+ start = 1;
+ end = m_path->GetSegmentCount();
+ }
+
+ for (int i = start; i < end; ++i)
+ {
+ from = &(*m_path)[i - 1]->pos;
+ to = &(*m_path)[i]->pos;
+
+ // compute ray along this path segment
+ along = *to - *from;
+
+ // make it a unit vector along the path
+ length = along.NormalizeInPlace();
+
+ // compute vector from start of segment to our point
+ toFeet = feet - *from;
+
+ // find distance of closest point on ray
+ closeLength = DotProduct(toFeet, along);
+
+ // constrain point to be on path segment
+ if (closeLength <= 0.0f)
+ pos = *from;
+ else if (closeLength >= length)
+ pos = *to;
+ else
+ pos = *from + closeLength * along;
+
+ distSq = (pos - feet).LengthSquared();
+
+ // keep the closest point so far
+ if (distSq < closeDistSq)
+ {
+ // don't use points we cant see
+ Vector probe = pos + Vector(0, 0, HalfHumanHeight);
+ if (!IsWalkableTraceLineClear(eyes, probe, WALK_THRU_DOORS | WALK_THRU_BREAKABLES))
+ continue;
+
+ // don't use points we cant reach
+ //if (!IsStraightLinePathWalkable(&pos))
+ // continue;
+
+ closeDistSq = distSq;
+ if (close)
+ *close = pos;
+ closeIndex = i - 1;
+ }
+ }
+
+ return closeIndex;
}
+// Compute a point a fixed distance ahead along our path
+// Returns path index just after point
+
/* <506248> ../game_shared/bot/nav_path.cpp:750 */
-NOBODY int CNavPathFollower::FindPathPoint(float aheadRange, Vector *point, int *prevIndex)
+int CNavPathFollower::FindPathPoint(float aheadRange, Vector *point, int *prevIndex)
{
-// {
-// int afterIndex; // 753
-// Vector close; // 756
-// int startIndex; // 757
-// Vector initDir; // 838
-// Vector feet; // 841
-// Vector eyes; // 842
-// float rangeSoFar; // 843
-// bool visible; // 846
-// Vector prevDir; // 848
-// bool isCorner; // 851
-// int i; // 852
-// {
-// int index; // 774
-// float const closeEpsilon; // 782
-// operator[](CNavPath *const this,
-// int i); // 778
-// operator-(const Vector *const this,
-// const Vector &v); // 783
-// IsLengthLessThan(const class Vector2D *const this,
-// float length); // 783
-// operator[](CNavPath *const this,
-// int i); // 793
-// }
-// {
-// Vector pos; // 802
-// float const closeEpsilon; // 805
-// operator-(const Vector *const this,
-// const Vector &v); // 806
-// operator[](CNavPath *const this,
-// int i); // 802
-// IsLengthLessThan(const class Vector2D *const this,
-// float length); // 806
-// }
-// operator[](CNavPath *const this,
-// int i); // 818
-// operator[](CNavPath *const this,
-// int i); // 820
-// operator[](CNavPath *const this,
-// int i); // 818
-// operator[](CNavPath *const this,
-// int i); // 831
-// operator[](CNavPath *const this,
-// int i); // 833
-// operator[](CNavPath *const this,
-// int i); // 831
-// operator[](CNavPath *const this,
-// int i); // 838
-// operator[](CNavPath *const this,
-// int i); // 838
-// operator-(const Vector *const this,
-// const Vector &v); // 838
-// NormalizeInPlace(Vector *const this); // 839
-// Vector(Vector *const this,
-// const Vector &v); // 841
-// {
-// Vector pos; // 855
-// Vector to; // 856
-// Vector dir; // 857
-// Vector probe; // 876
-// Vector along; // 897
-// operator[](CNavPath *const this,
-// int i); // 855
-// Vector(Vector *const this,
-// const Vector &v); // 855
-// operator[](CNavPath *const this,
-// int i); // 856
-// operator-(const Vector *const this,
-// const Vector &v); // 856
-// Normalize(const Vector *const this); // 857
-// DotProduct(Vector &a,
-// const Vector &b); // 860
-// DotProduct(Vector &a,
-// const Vector &b); // 867
-// operator+(const Vector *const this,
-// const Vector &v); // 876
-// IsWalkableTraceLineClear(Vector &from,
-// Vector &to,
-// unsigned int flags); // 877
-// operator[](CNavPath *const this,
-// int i); // 886
-// operator[](CNavPath *const this,
-// int i); // 886
-// operator[](CNavPath *const this,
-// int i); // 897
-// operator-(const Vector *const this,
-// const Vector &v); // 897
-// Length2D(const Vector *const this); // 898
-// operator-(const Vector *const this,
-// const Vector &v); // 897
-// }
-// Vector(Vector *const this,
-// const Vector &v); // 842
-// operator[](CNavPath *const this,
-// int i); // 916
-// {
-// const Vector *afterPoint; // 921
-// const Vector *beforePoint; // 922
-// Vector to; // 924
-// float length; // 925
-// float t; // 927
-// operator[](CNavPath *const this,
-// int i); // 921
-// operator[](CNavPath *const this,
-// int i); // 922
-// operator-(const Vector *const this,
-// const Vector &v); // 924
-// Length2D(const Vector *const this); // 925
-// operator*(float fl,
-// const Vector &v); // 934
-// {
-// float const sightStepSize; // 939
-// float dt; // 940
-// Vector probe; // 942
-// operator+(const Vector *const this,
-// const Vector &v); // 942
-// IsWalkableTraceLineClear(Vector &from,
-// Vector &to,
-// unsigned int flags); // 943
-// operator+(const Vector *const this,
-// const Vector &v); // 946
-// operator*(float fl,
-// const Vector &v); // 946
-// }
-// operator+(const Vector *const this,
-// const Vector &v); // 934
-// }
-// {
-// float const epsilon; // 957
-// class Vector2D toPoint; // 958
-// class Vector2D centroid; // 959
-// DotProduct(const class Vector2D &a,
-// const class Vector2D &b); // 964
-// IsLengthLessThan(const class Vector2D *const this,
-// float length); // 964
-// {
-// int i; // 966
-// operator[](CNavPath *const this,
-// int i); // 969
-// operator[](CNavPath *const this,
-// int i); // 973
-// operator[](CNavPath *const this,
-// int i); // 971
-// IsLengthGreaterThan(const class Vector2D *const this,
-// float length); // 971
-// }
-// }
-// }
+ // find path index just past aheadRange
+ int afterIndex;
+
+ // finds the closest point on local area of path, and returns the path index just prior to it
+ Vector close;
+ int startIndex = FindOurPositionOnPath(&close, true);
+
+ if (prevIndex)
+ *prevIndex = startIndex;
+
+ if (startIndex <= 0)
+ {
+ // went off the end of the path
+ // or next point in path is unwalkable (ie: jump-down)
+ // keep same point
+ return m_segmentIndex;
+ }
+
+ // if we are crouching, just follow the path exactly
+ if (m_improv->IsCrouching())
+ {
+ // we want to move to the immediately next point along the path from where we are now
+ int index = startIndex + 1;
+ if (index >= m_path->GetSegmentCount())
+ index = m_path->GetSegmentCount() - 1;
+
+ *point = (*m_path)[index]->pos;
+
+ // if we are very close to the next point in the path, skip ahead to the next one to avoid wiggling
+ // we must do a 2D check here, in case the goal point is floating in space due to jump down, etc
+ const float closeEpsilon = 20.0f;
+ while ((*point - close).Make2D().IsLengthLessThan(closeEpsilon))
+ {
+ ++index;
+
+ if (index >= m_path->GetSegmentCount())
+ {
+ index = m_path->GetSegmentCount() - 1;
+ break;
+ }
+
+ *point = (*m_path)[index]->pos;
+ }
+
+ return index;
+ }
+
+ // make sure we use a node a minimum distance ahead of us, to avoid wiggling
+ while (startIndex < m_path->GetSegmentCount() - 1)
+ {
+ Vector pos = (*m_path)[startIndex + 1]->pos;
+
+ // we must do a 2D check here, in case the goal point is floating in space due to jump down, etc
+ const float closeEpsilon = 20.0f;
+ if ((pos - close).Make2D().IsLengthLessThan(closeEpsilon))
+ {
+ ++startIndex;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // if we hit a ladder or jump area, must stop (dont use ladder behind us)
+ if (startIndex > m_segmentIndex && startIndex < m_path->GetSegmentCount() && ((*m_path)[startIndex]->ladder || ((*m_path)[startIndex]->area->GetAttributes() & NAV_JUMP)))
+ {
+ *point = (*m_path)[startIndex]->pos;
+ return startIndex;
+ }
+
+ // we need the point just *ahead* of us
+ ++startIndex;
+ if (startIndex >= m_path->GetSegmentCount())
+ startIndex = m_path->GetSegmentCount() - 1;
+
+ // if we hit a ladder or jump area, must stop
+ if (startIndex < m_path->GetSegmentCount() && ((*m_path)[startIndex]->ladder || ((*m_path)[startIndex]->area->GetAttributes() & NAV_JUMP)))
+ {
+ *point = (*m_path)[startIndex]->pos;
+ return startIndex;
+ }
+
+ // note direction of path segment we are standing on
+ Vector initDir = (*m_path)[startIndex]->pos - (*m_path)[startIndex - 1]->pos;
+ initDir.NormalizeInPlace();
+
+ Vector feet = m_improv->GetFeet();
+ Vector eyes = m_improv->GetEyes();
+ float rangeSoFar = 0;
+
+ // this flag is true if our ahead point is visible
+ bool visible = true;
+
+ Vector prevDir = initDir;
+
+ // step along the path until we pass aheadRange
+ bool isCorner = false;
+ int i;
+ for (i = startIndex; i < m_path->GetSegmentCount(); ++i)
+ {
+ Vector pos = (*m_path)[i]->pos;
+ Vector to = pos - (*m_path)[i - 1]->pos;
+ Vector dir = to.Normalize();
+
+ // don't allow path to double-back from our starting direction (going upstairs, down curved passages, etc)
+ if (DotProduct(dir, initDir) < 0.0f) // -0.25f
+ {
+ --i;
+ break;
+ }
+
+ // if the path turns a corner, we want to move towards the corner, not into the wall/stairs/etc
+ if (DotProduct(dir, prevDir) < 0.5f)
+ {
+ isCorner = true;
+ --i;
+ break;
+ }
+ prevDir = dir;
+
+ // don't use points we cant see
+ Vector probe = pos + Vector(0, 0, HalfHumanHeight);
+ if (!IsWalkableTraceLineClear(eyes, probe, WALK_THRU_BREAKABLES))
+ {
+ // presumably, the previous point is visible, so we will interpolate
+ visible = false;
+ break;
+ }
+
+ // if we encounter a ladder or jump area, we must stop
+ if (i < m_path->GetSegmentCount() && ((*m_path)[i]->ladder || (*m_path)[i]->area->GetAttributes() & NAV_JUMP))
+ break;
+
+ // Check straight-line path from our current position to this position
+ // Test for un-jumpable height change, or unrecoverable fall
+ //if (!IsStraightLinePathWalkable(&pos))
+ //{
+ // --i;
+ // break;
+ //}
+
+ Vector along = (i == startIndex) ? (pos - feet) : (pos - (*m_path)[i - 1]->pos);
+ rangeSoFar += along.Length2D();
+
+ // stop if we have gone farther than aheadRange
+ if (rangeSoFar >= aheadRange)
+ break;
+ }
+
+ if (i < startIndex)
+ afterIndex = startIndex;
+ else if (i < m_path->GetSegmentCount())
+ afterIndex = i;
+ else
+ afterIndex = m_path->GetSegmentCount() - 1;
+
+ // compute point on the path at aheadRange
+ if (afterIndex == 0)
+ {
+ *point = (*m_path)[0]->pos;
+ }
+ else
+ {
+ // interpolate point along path segment
+ const Vector *afterPoint = &(*m_path)[afterIndex]->pos;
+ const Vector *beforePoint = &(*m_path)[afterIndex - 1]->pos;
+
+ Vector to = *afterPoint - *beforePoint;
+ float length = to.Length2D();
+
+ float t = 1.0f - ((rangeSoFar - aheadRange) / length);
+
+ if (t < 0.0f)
+ t = 0.0f;
+ else if (t > 1.0f)
+ t = 1.0f;
+
+ *point = *beforePoint + t * to;
+
+ // if afterPoint wasn't visible, slide point backwards towards beforePoint until it is
+ if (!visible)
+ {
+ const float sightStepSize = 25.0f;
+ float dt = sightStepSize / length;
+
+ Vector probe = *point + Vector(0, 0, HalfHumanHeight);
+ while (t > 0.0f && !IsWalkableTraceLineClear(eyes, probe, WALK_THRU_BREAKABLES))
+ {
+ t -= dt;
+ *point = *beforePoint + t * to;
+ }
+
+ if (t <= 0.0f)
+ *point = *beforePoint;
+ }
+ }
+
+ // if position found is too close to us, or behind us, force it farther down the path so we don't stop and wiggle
+ if (!isCorner)
+ {
+ const float epsilon = 50.0f;
+ Vector2D toPoint;
+ Vector2D centroid(m_improv->GetCentroid().x, m_improv->GetCentroid().y);
+
+ toPoint.x = point->x - centroid.x;
+ toPoint.y = point->y - centroid.y;
+
+ if (DotProduct(toPoint, initDir.Make2D()) < 0.0f || toPoint.IsLengthLessThan(epsilon))
+ {
+ int i;
+ for (i = startIndex; i < m_path->GetSegmentCount(); ++i)
+ {
+ toPoint.x = (*m_path)[i]->pos.x - centroid.x;
+ toPoint.y = (*m_path)[i]->pos.y - centroid.y;
+ if ((*m_path)[i]->ladder || ((*m_path)[i]->area->GetAttributes() & NAV_JUMP) || toPoint.IsLengthGreaterThan(epsilon))
+ {
+ *point = (*m_path)[i]->pos;
+ startIndex = i;
+ break;
+ }
+ }
+
+ if (i == m_path->GetSegmentCount())
+ {
+ *point = m_path->GetEndpoint();
+ startIndex = m_path->GetSegmentCount() - 1;
+ }
+ }
+ }
+
+ // m_pathIndex should always be the next point on the path, even if we're not moving directly towards it
+ if (startIndex < m_path->GetSegmentCount())
+ return startIndex;
+
+ return m_path->GetSegmentCount() - 1;
}
+// Do reflex avoidance movements if our "feelers" are touched
+// TODO: Parameterize feeler spacing
+
/* <507004> ../game_shared/bot/nav_path.cpp:1000 */
-NOBODY void CNavPathFollower::FeelerReflexAdjustment(Vector *goalPosition, float height)
+void CNavPathFollower::FeelerReflexAdjustment(Vector *goalPosition, float height)
{
-// {
-// Vector dir; // 1006
-// Vector lat; // 1010
-// float const feelerOffset; // 1012
-// float const feelerLengthRun; // 1013
-// float const feelerLengthWalk; // 1014
-// float const feelerHeight; // 1016
-// float feelerLength; // 1018
-// float ground; // 1025
-// Vector normal; // 1026
-// Vector feet; // 1037
-// Vector from; // 1040
-// Vector to; // 1041
-// bool leftClear; // 1043
-// bool rightClear; // 1057
-// float const avoidRange; // 1070
-// NormalizeInPlace(Vector *const this); // 1008
-// CrossProduct(Vector &a,
-// const Vector &b); // 1031
-// IsWalkableTraceLineClear(Vector &from,
-// Vector &to,
-// unsigned int flags); // 1043
-// CrossProduct(Vector &a,
-// const Vector &b); // 1034
-// Vector(Vector *const this,
-// const Vector &v); // 1037
-// operator*(float fl,
-// const Vector &v); // 1040
-// operator+(const Vector *const this,
-// const Vector &v); // 1040
-// operator*(float fl,
-// const Vector &v); // 1041
-// operator+(const Vector *const this,
-// const Vector &v); // 1041
-// Vector(Vector *const this,
-// const Vector &v); // 1049
-// Vector(Vector *const this,
-// const Vector &v); // 1049
-// operator-(const Vector *const this,
-// const Vector &v); // 1054
-// IsWalkableTraceLineClear(Vector &from,
-// Vector &to,
-// unsigned int flags); // 1057
-// operator+(const Vector *const this,
-// const Vector &v); // 1055
-// Vector(Vector *const this,
-// const Vector &v); // 1063
-// Vector(Vector *const this,
-// const Vector &v); // 1063
-// operator*(float fl,
-// const Vector &v); // 1077
-// operator+(const Vector *const this,
-// const Vector &v); // 1077
-// operator*(float fl,
-// const Vector &v); // 1086
-// operator-(const Vector *const this,
-// const Vector &v); // 1086
-// Vector(Vector *const this,
-// const Vector &v); // 1065
-// Vector(Vector *const this,
-// const Vector &v); // 1065
-// Vector(Vector *const this,
-// const Vector &v); // 1051
-// Vector(Vector *const this,
-// const Vector &v); // 1051
-// }
+ // if we are in a "precise" area, do not do feeler adjustments
+ if (m_improv->GetLastKnownArea() && (m_improv->GetLastKnownArea()->GetAttributes() & NAV_PRECISE))
+ return;
+
+ Vector dir(BotCOS(m_improv->GetMoveAngle()), BotSIN(m_improv->GetMoveAngle()), 0.0f);
+ dir.z = 0.0f;
+
+#ifndef PLAY_GAMEDLL
+ dir.NormalizeInPlace();
+#else
+ // TODO: fix test demo
+ float_precision flLen = dir.Length();
+
+ if (flLen > 0)
+ dir = dir * (float)(1 / flLen);
+ else
+ dir = Vector(0, 0, 0);
+#endif // PLAY_GAMEDLL
+
+ Vector lat(-dir.y, dir.x, 0.0f);
+
+ const float feelerOffset = (m_improv->IsCrouching()) ? 20.0f : 25.0f; // 15, 20
+ const float feelerLengthRun = 50.0f; // 100 - too long for tight hallways (cs_747)
+ const float feelerLengthWalk = 30.0f;
+
+ // if obstacle is lower than StepHeight, we'll walk right over it
+ const float feelerHeight = (height > 0.0f) ? height : StepHeight + 0.1f;
+ float feelerLength = (m_improv->IsRunning()) ? feelerLengthRun : feelerLengthWalk;
+
+ feelerLength = (m_improv->IsCrouching()) ? 20.0f : feelerLength;
+
+ // Feelers must follow floor slope
+ float ground;
+ Vector normal;
+ if (m_improv->GetSimpleGroundHeightWithFloor(&m_improv->GetEyes(), &ground, &normal) == false)
+ return;
+
+ // get forward vector along floor
+ dir = CrossProduct(lat, normal);
+
+ // correct the sideways vector
+ lat = CrossProduct(dir, normal);
+
+ Vector feet = m_improv->GetFeet();
+ feet.z += feelerHeight;
+
+ Vector from = feet + feelerOffset * lat;
+ Vector to = from + feelerLength * dir;
+
+ bool leftClear = IsWalkableTraceLineClear(from, to, WALK_THRU_DOORS | WALK_THRU_BREAKABLES);
+
+ // draw debug beams
+ if (m_isDebug)
+ {
+ if (leftClear)
+ UTIL_DrawBeamPoints(from, to, 1, 0, 255, 0);
+ else
+ UTIL_DrawBeamPoints(from, to, 1, 255, 0, 0);
+ }
+
+ from = feet - feelerOffset * lat;
+ to = from + feelerLength * dir;
+
+ bool rightClear = IsWalkableTraceLineClear(from, to, WALK_THRU_DOORS | WALK_THRU_BREAKABLES);
+
+ // draw debug beams
+ if (m_isDebug)
+ {
+ if (rightClear)
+ UTIL_DrawBeamPoints(from, to, 1, 0, 255, 0);
+ else
+ UTIL_DrawBeamPoints(from, to, 1, 255, 0, 0);
+ }
+
+ const float_precision avoidRange = (m_improv->IsCrouching()) ? 150.0f : 300.0f;
+
+ if (!rightClear)
+ {
+ if (leftClear)
+ {
+ // right hit, left clear - veer left
+ *goalPosition = *goalPosition + avoidRange * lat;
+ //*goalPosition = m_improv->GetFeet() + avoidRange * lat;
+ //m_improv->StrafeLeft();
+ }
+ }
+ else if (!leftClear)
+ {
+ // right clear, left hit - veer right
+ *goalPosition = *goalPosition - avoidRange * lat;
+ //*goalPosition = m_improv->GetFeet() - avoidRange * lat;
+ //m_improv->StrafeRight();
+ }
}
+// Reset the stuck-checker
+
/* <507a31> ../game_shared/bot/nav_path.cpp:1098 */
-NOBODY CStuckMonitor::CStuckMonitor(void)
+CStuckMonitor::CStuckMonitor(void)
{
-// IntervalTimer(IntervalTimer *const this); // 1098
+ m_isStuck = false;
+ m_avgVelIndex = 0;
+ m_avgVelCount = 0;
}
+// Reset the stuck-checker
+
/* <507a73> ../game_shared/bot/nav_path.cpp:1108 */
-NOBODY void CStuckMonitor::Reset(void)
+void CStuckMonitor::Reset(void)
{
+ m_isStuck = false;
+ m_avgVelIndex = 0;
+ m_avgVelCount = 0;
}
+// Test if the improv has become stuck
+
/* <507a96> ../game_shared/bot/nav_path.cpp:1119 */
-NOBODY void CStuckMonitor::Update(CImprov *improv)
+void CStuckMonitor::Update(CImprov *improv)
{
-// {
-// float const unstuckRange; // 1124
-// operator-(const Vector *const this,
-// const Vector &v); // 1125
-// IsLengthGreaterThan(const Vector *const this,
-// float length); // 1125
-// Reset(CStuckMonitor *const this); // 1128
-// }
-// {
-// Vector vel; // 1137
-// float moveDist; // 1148
-// float deltaT; // 1150
-// operator-(const Vector *const this,
-// const Vector &v); // 1137
-// Length(const Vector *const this); // 1148
-// {
-// float avgVel; // 1170
-// float stuckVel; // 1177
-// {
-// int t; // 1171
-// }
-// Start(IntervalTimer *const this); // 1182
-// }
-// }
+ if (m_isStuck)
+ {
+ // improv is stuck - see if it has moved far enough to be considered unstuck
+ const float unstuckRange = 75.0f;
+ if ((improv->GetCentroid() - m_stuckSpot).IsLengthGreaterThan(unstuckRange))
+ {
+ // no longer stuck
+ Reset();
+ //PrintIfWatched( "UN-STUCK\n" );
+ }
+ }
+ else
+ {
+ // check if improv has become stuck
+
+ // compute average velocity over a short period (for stuck check)
+ Vector vel = improv->GetCentroid() - m_lastCentroid;
+
+ // if we are jumping, ignore Z
+ //if (improv->IsJumping())
+ // vel.z = 0.0f;
+
+ // ignore Z unless we are on a ladder (which is only Z)
+ if (!improv->IsUsingLadder())
+ vel.z = 0.0f;
+
+ // cannot be Length2D, or will break ladder movement (they are only Z)
+ float moveDist = vel.Length();
+
+ float deltaT = gpGlobals->time - m_lastTime;
+ if (deltaT <= 0.0f)
+ return;
+
+ m_lastTime = gpGlobals->time;
+
+ // compute current velocity
+ m_avgVel[m_avgVelIndex++] = moveDist / deltaT;
+
+ if (m_avgVelIndex == MAX_VEL_SAMPLES)
+ m_avgVelIndex = 0;
+
+ if (m_avgVelCount < MAX_VEL_SAMPLES)
+ {
+ ++m_avgVelCount;
+ }
+ else
+ {
+ // we have enough samples to know if we're stuck
+
+ float avgVel = 0.0f;
+ for (int t = 0; t < m_avgVelCount; ++t)
+ avgVel += m_avgVel[t];
+
+ avgVel /= m_avgVelCount;
+
+ // cannot make this velocity too high, or actors will get "stuck" when going down ladders
+ float stuckVel = (improv->IsUsingLadder()) ? 10.0f : 20.0f;
+
+ if (avgVel < stuckVel)
+ {
+ // note when and where we initially become stuck
+ m_stuckTimer.Start();
+ m_stuckSpot = improv->GetCentroid();
+ m_isStuck = true;
+ }
+ }
+ }
+
+ // always need to track this
+ m_lastCentroid = improv->GetCentroid();
}
diff --git a/regamedll/game_shared/bot/nav_path.h b/regamedll/game_shared/bot/nav_path.h
index 6b539694..49bb27bf 100644
--- a/regamedll/game_shared/bot/nav_path.h
+++ b/regamedll/game_shared/bot/nav_path.h
@@ -66,9 +66,9 @@ public:
return m_path[ m_segmentCount - 1 ].pos;
}
- bool IsAtEnd(const Vector &pos) const; // return true if position is at the end of the path
- float GetLength(void) const; // return length of path from start to finish
- bool GetPointAlongPath(float distAlong, Vector *pointOnPath) const; // return point a given distance along the path - if distance is out of path bounds, point is clamped to start/end
+ bool IsAtEnd(const Vector &pos) const; // return true if position is at the end of the path
+ float GetLength(void) const; // return length of path from start to finish
+ NOXREF bool GetPointAlongPath(float distAlong, Vector *pointOnPath) const; // return point a given distance along the path - if distance is out of path bounds, point is clamped to start/end
/// return the node index closest to the given distance along the path without going over - returns (-1) if error
int GetSegmentIndexAlongPath(float distAlong) const;
@@ -86,7 +86,7 @@ public:
void Draw(void);
/// compute closest point on path to given point
- bool FindClosestPointOnPath(const Vector *worldPos, int startIndex, int endIndex, Vector *close) const;
+ NOXREF bool FindClosestPointOnPath(const Vector *worldPos, int startIndex, int endIndex, Vector *close) const;
void Optimize(void);
@@ -176,16 +176,16 @@ private:
PathSegment m_path[ MAX_PATH_SEGMENTS ];
int m_segmentCount;
- // determine actual path positions
- bool ComputePathPositions(void);
#ifdef HOOK_GAMEDLL
public:
#endif // HOOK_GAMEDLL
+ // determine actual path positions
+ bool ComputePathPositions(void);
// utility function for when start and goal are in the same area
bool BuildTrivialPath(const Vector *start, const Vector *goal);
// used by Optimize()
- int FindNextOccludedNode(int anchor);
+ int FindNextOccludedNode(int anchor_);
};/* size: 6148, cachelines: 97, members: 2 */
@@ -263,7 +263,11 @@ public:
// adjust goal position if "feelers" are touched
void FeelerReflexAdjustment(Vector *goalPosition, float height = -1.0f);
+#ifdef HOOK_GAMEDLL
+public:
+#else
private:
+#endif // HOOK_GAMEDLL
int FindOurPositionOnPath(Vector *close, bool local) const; // return the closest point to our current position on current path
int FindPathPoint(float aheadRange, Vector *point, int *prevIndex); // compute a point a fixed distance ahead along our path.
diff --git a/regamedll/game_shared/bot/simple_state_machine.h b/regamedll/game_shared/bot/simple_state_machine.h
index 1e764f2e..e085a59c 100644
--- a/regamedll/game_shared/bot/simple_state_machine.h
+++ b/regamedll/game_shared/bot/simple_state_machine.h
@@ -33,8 +33,9 @@
#endif
// Encapsulation of a finite-state-machine state
-template
+
/* <5c4388> ../game_shared/bot/simple_state_machine.h:21 */
+template
class SimpleState
{
public:
@@ -57,14 +58,16 @@ public:
{
return m_parent;
}
+
private:
// the parent state that contains this state
SimpleState *m_parent;
};
// Encapsulation of a finite state machine
-template
+
/* <5c4bab> ../game_shared/bot/simple_state_machine.h:68 */
+template
class SimpleStateMachine
{
public:
diff --git a/regamedll/hookers/6153_hooker.cpp b/regamedll/hookers/6153_hooker.cpp
index 3f7becd4..b3db85fe 100644
--- a/regamedll/hookers/6153_hooker.cpp
+++ b/regamedll/hookers/6153_hooker.cpp
@@ -248,7 +248,7 @@ FunctionHook g_FunctionHooks[] =
{ 0x01D59250, "_ZN8CAirtank4SaveER5CSave", mfunc_ptr_cast(&CAirtank::Save_) },
{ 0x01D59280, "_ZN8CAirtank7RestoreER8CRestore", mfunc_ptr_cast(&CAirtank::Restore_) },
{ 0x01D593C0, "_ZN8CAirtank6KilledEP9entvars_si", mfunc_ptr_cast(&CAirtank::Killed_) },
- { 0x01D59240, "_ZN8CAirtank10BloodColorEv", mfunc_ptr_cast(&CAirtank::BloodColor_) },
+ //{ 0x01D59240, "_ZN8CAirtank10BloodColorEv", mfunc_ptr_cast(&CAirtank::BloodColor_) }, // DEFAULT
//non-virtual func
{ 0x01D59410, "_ZN8CAirtank9TankThinkEv", mfunc_ptr_cast(&CAirtank::TankThink) },
{ 0x01D59430, "_ZN8CAirtank9TankTouchEP11CBaseEntity", mfunc_ptr_cast(&CAirtank::TankTouch) },
@@ -840,7 +840,7 @@ FunctionHook g_FunctionHooks[] =
{ 0x01DA08D0, "_ZN8CWShield5SpawnEv", mfunc_ptr_cast(&CWShield::Spawn_) },
{ 0x01DA0920, "_ZN8CWShield5TouchEP11CBaseEntity", mfunc_ptr_cast(&CWShield::Touch_) },
//non-virtual func
- //{ 0x0, "_ZN8CWShield23SetCantBePickedUpByUserEP11CBaseEntityf", mfunc_ptr_cast(&CWShield::SetCantBePickedUpByUser) } // NOXREF INLINEBODY
+ //{ 0x0, "_ZN8CWShield23SetCantBePickedUpByUserEP11CBaseEntityf", mfunc_ptr_cast(&CWShield::SetCantBePickedUpByUser) } // NOXREF
//CSprayCan
//virtual func
@@ -3104,7 +3104,7 @@ FunctionHook g_FunctionHooks[] =
{ 0x01D03120, "_ZN3CC411GetItemInfoEP8ItemInfo", mfunc_ptr_cast(&CC4::GetItemInfo_) },
{ 0x01D03190, "_ZN3CC46DeployEv", mfunc_ptr_cast(&CC4::Deploy_) },
{ 0x01D03200, "_ZN3CC47HolsterEi", mfunc_ptr_cast(&CC4::Holster_) },
- //{ 0x01D03A80, "_ZN3CC411GetMaxSpeedEv", mfunc_ptr_cast(&CC4::GetMaxSpeed_) }, // DEFAULT
+ { 0x01D03A80, "_ZN3CC411GetMaxSpeedEv", mfunc_ptr_cast(&CC4::GetMaxSpeed_) },
//{ 0x01D03A70, "_ZN3CC49iItemSlotEv", mfunc_ptr_cast(&CC4::iItemSlot_) }, // DEFAULT
{ 0x01D03280, "_ZN3CC413PrimaryAttackEv", mfunc_ptr_cast(&CC4::PrimaryAttack_) },
{ 0x01D03750, "_ZN3CC410WeaponIdleEv", mfunc_ptr_cast(&CC4::WeaponIdle_) },
@@ -3665,7 +3665,7 @@ FunctionHook g_FunctionHooks[] =
{ 0x01D34210, "_ZN11CBotManager10StartFrameEv", mfunc_ptr_cast(&CBotManager::StartFrame_) },
{ 0x01D34540, "_ZN11CBotManager7OnEventE13GameEventTypeP11CBaseEntityS2_", mfunc_ptr_cast(&CBotManager::OnEvent_) },
//non-virtual func
- ////{ 0x0, "", mfunc_ptr_cast(&CBotManager::CBotManager) },
+ //{ 0x01D34170, "", mfunc_ptr_cast(&CBotManager::CBotManager) },
{ 0x01D34510, "_ZNK11CBotManager17GetNavMapFilenameEv", mfunc_ptr_cast(&CBotManager::GetNavMapFilename) },
{ 0x01D34650, "_ZN11CBotManager10AddGrenadeEiP8CGrenade", mfunc_ptr_cast(&CBotManager::AddGrenade) },
{ 0x01D346C0, "_ZN11CBotManager13RemoveGrenadeEP8CGrenade", mfunc_ptr_cast(&CBotManager::RemoveGrenade) },
@@ -3674,9 +3674,10 @@ FunctionHook g_FunctionHooks[] =
{ 0x01D347A0, "_ZN11CBotManager18IsInsideSmokeCloudEPK6Vector", mfunc_ptr_cast(&CBotManager::IsInsideSmokeCloud) }, // FIXME!!
{ 0x01D34850, "_ZN11CBotManager20IsLineBlockedBySmokeEPK6VectorS2_", mfunc_ptr_cast(&CBotManager::IsLineBlockedBySmoke) },
//non-class func
- //{ 0x0, "_Z15NameToGameEventPKc", (size_t)&NameToGameEvent },
+ { 0x01D34120, "_Z15NameToGameEventPKc", (size_t)&NameToGameEvent },
//CCSBotManager
//virtual func
+ //{ 0x01D22D60, "", mfunc_ptr_cast(&CCSBotManager::CCSBotManager) },
{ 0x01D23770, "_ZN13CCSBotManager16ClientDisconnectEP11CBasePlayer", mfunc_ptr_cast(&CCSBotManager::ClientDisconnect_) },
{ 0x01D24880, "_ZN13CCSBotManager13ClientCommandEP11CBasePlayerPKc", mfunc_ptr_cast(&CCSBotManager::ClientCommand_) },
{ 0x01D234D0, "_ZN13CCSBotManager14ServerActivateEv", mfunc_ptr_cast(&CCSBotManager::ServerActivate_) },
@@ -3951,7 +3952,7 @@ FunctionHook g_FunctionHooks[] =
//{ 0x0, "_ZNK6CCSBot13IsPistolEmptyEv", mfunc_ptr_cast(&CCSBot::IsPistolEmpty) },
//{ 0x0, "_ZNK6CCSBot21GetHostageEscortCountEv", mfunc_ptr_cast(&CCSBot::GetHostageEscortCount) },
//{ 0x0, "_ZN6CCSBot26IncreaseHostageEscortCountEv", mfunc_ptr_cast(&CCSBot::IncreaseHostageEscortCount) },
- //{ 0x0, "_ZNK6CCSBot33GetRangeToFarthestEscortedHostageEv", mfunc_ptr_cast(&CCSBot::GetRangeToFarthestEscortedHostage) },
+ { 0x01D18B10, "_ZNK6CCSBot33GetRangeToFarthestEscortedHostageEv", mfunc_ptr_cast(&CCSBot::GetRangeToFarthestEscortedHostage) },
//{ 0x0, "_ZN6CCSBot27ResetWaitForHostagePatienceEv", mfunc_ptr_cast(&CCSBot::ResetWaitForHostagePatience) },
//{ 0x01D20AE0, "_ZN6CCSBot11ResetValuesEv", mfunc_ptr_cast(&CCSBot::ResetValues) },
//{ 0x01D17950, "_ZN6CCSBot13BotDeathThinkEv", mfunc_ptr_cast(&CCSBot::BotDeathThink) }, // PURE
@@ -4191,8 +4192,8 @@ FunctionHook g_FunctionHooks[] =
//{ 0x0, "_ZN4CBot8SpawnBotEv", mfunc_ptr_cast(&CBot::SpawnBot) },
//{ 0x0, "_ZN4CBot6UpkeepEv", mfunc_ptr_cast(&CBot::Upkeep) },
//{ 0x0, "_ZN4CBot6UpdateEv", mfunc_ptr_cast(&CBot::Update) },
- //{ 0x0, "_ZN4CBot3RunEv", mfunc_ptr_cast(&CBot::Run) },
- //{ 0x0, "_ZN4CBot4WalkEv", mfunc_ptr_cast(&CBot::Walk) },
+ //{ 0x01D21110, "_ZN4CBot3RunEv", mfunc_ptr_cast(&CBot::Run) }, // DEFAULT
+ //{ 0x01D34110, "_ZN4CBot4WalkEv", mfunc_ptr_cast(&CBot::Walk) }, // DEFAULT
//{ 0x0, "_ZN4CBot6CrouchEv", mfunc_ptr_cast(&CBot::Crouch_) },
//{ 0x0, "_ZN4CBot7StandUpEv", mfunc_ptr_cast(&CBot::StandUp_) },
//{ 0x0, "_ZN4CBot11MoveForwardEv", mfunc_ptr_cast(&CBot::MoveForward_) },
@@ -4790,6 +4791,7 @@ FunctionHook g_FunctionHooks[] =
{ 0x01D4EA30, "", mfunc_ptr_cast(&Vector::Normalize) },
{ 0x01DCB800, "", mfunc_ptr_cast(&Vector::operator==) },
{ 0x01D130D0, "", mfunc_ptr_cast(&Vector::IsLengthLessThan) },
+ { 0x01D34D90, "", mfunc_ptr_cast(&DotProduct) },
#endif // _WIN32
@@ -4798,12 +4800,12 @@ FunctionHook g_FunctionHooks[] =
#ifndef Nav_Region
//Nav_File
- //{ 0x0, "_Z14GetBspFilenamePKc", (size_t)&GetBspFilename },
- //{ 0x0, "", (size_t)&COM_FixSlashes }, // NOXREF
- //{ 0x01D45CF0, "_Z17SaveNavigationMapPKc", (size_t)&SaveNavigationMap },
- //{ 0x01D45F80, "_Z16LoadLocationFilePKc", (size_t)&LoadLocationFile },
- //{ 0x01D46170, "_Z24SanityCheckNavigationMapPKc", (size_t)&SanityCheckNavigationMap },
- //{ 0x01D46310, "_Z17LoadNavigationMapv", (size_t)&LoadNavigationMap },
+ //{ 0x01D44E00, "_Z14GetBspFilenamePKc", (size_t)&GetBspFilename }, // NOXREF
+ //{ 0x0, "", (size_t)&COM_FixSlashes }, // NOXREF
+ { 0x01D45CF0, "_Z17SaveNavigationMapPKc", (size_t)&SaveNavigationMap },
+ { 0x01D45F80, "_Z16LoadLocationFilePKc", (size_t)&LoadLocationFile },
+ { 0x01D46170, "_Z24SanityCheckNavigationMapPKc", (size_t)&SanityCheckNavigationMap },
+ { 0x01D46310, "_Z17LoadNavigationMapv", (size_t)&LoadNavigationMap },
//IImprovEvent
//virtual func
//{ 0x0, "_ZN12IImprovEvent15OnMoveToSuccessERK6Vector", mfunc_ptr_cast(&IImprovEvent::OnMoveToSuccess) },
@@ -4864,8 +4866,8 @@ FunctionHook g_FunctionHooks[] =
//{ 0x0, "_ZN7CImprov11OnGameEventE13GameEventTypeP11CBaseEntityS2_", mfunc_ptr_cast(&CImprov::OnGameEvent) },
//{ 0x0, "_ZN7CImprov7OnTouchEP11CBaseEntity", mfunc_ptr_cast(&CImprov::OnTouch) },
//CNavNode
- //{ 0x0, "", mfunc_ptr_cast(&CNavNode::CNavNode) },
- //{ 0x0, "_ZN8CNavNode7GetNodeEPK6Vector", mfunc_ptr_cast(&CNavNode::GetNode) },
+ //{ 0x01D46F60, "_ZN8CNavNodeC2EPK6VectorS2_PS_", mfunc_ptr_cast(&CNavNode::CNavNode) },
+ { 0x01D47000, "_ZN8CNavNode7GetNodeEPK6Vector", mfunc_ptr_cast(&CNavNode::GetNode) },
//{ 0x0, "_ZNK8CNavNode16GetConnectedNodeE10NavDirType", mfunc_ptr_cast(&CNavNode::GetConnectedNode) },
//{ 0x0, "_ZNK8CNavNode11GetPositionEv", mfunc_ptr_cast(&CNavNode::GetPosition) },
//{ 0x0, "_ZNK8CNavNode9GetNormalEv", mfunc_ptr_cast(&CNavNode::GetNormal) },
@@ -4873,12 +4875,12 @@ FunctionHook g_FunctionHooks[] =
//{ 0x0, "_ZN8CNavNode8GetFirstEv", mfunc_ptr_cast(&CNavNode::GetFirst) },
//{ 0x0, "_ZN8CNavNode13GetListLengthEv", mfunc_ptr_cast(&CNavNode::GetListLength) },
//{ 0x0, "_ZN8CNavNode7GetNextEv", mfunc_ptr_cast(&CNavNode::GetNext) },
- //{ 0x0, "_ZN8CNavNode9ConnectToEPS_10NavDirType", mfunc_ptr_cast(&CNavNode::ConnectTo) },
+ { 0x01D46FF0, "_ZN8CNavNode9ConnectToEPS_10NavDirType", mfunc_ptr_cast(&CNavNode::ConnectTo) },
//{ 0x0, "_ZNK8CNavNode9GetParentEv", mfunc_ptr_cast(&CNavNode::GetParent) },
//{ 0x0, "_ZN8CNavNode13MarkAsVisitedE10NavDirType", mfunc_ptr_cast(&CNavNode::MarkAsVisited) },
//{ 0x0, "_ZN8CNavNode10HasVisitedE10NavDirType", mfunc_ptr_cast(&CNavNode::HasVisited) },
- //{ 0x0, "_ZNK8CNavNode10IsBiLinkedE10NavDirType", mfunc_ptr_cast(&CNavNode::IsBiLinked) },
- //{ 0x0, "_ZNK8CNavNode12IsClosedCellEv", mfunc_ptr_cast(&CNavNode::IsClosedCell) },
+ //{ 0x01D470E0, "_ZNK8CNavNode10IsBiLinkedE10NavDirType", mfunc_ptr_cast(&CNavNode::IsBiLinked) }, // NOXREF
+ { 0x01D47110, "_ZNK8CNavNode12IsClosedCellEv", mfunc_ptr_cast(&CNavNode::IsClosedCell) },
//{ 0x0, "_ZN8CNavNode5CoverEv", mfunc_ptr_cast(&CNavNode::Cover) },
//{ 0x0, "_ZNK8CNavNode9IsCoveredEv", mfunc_ptr_cast(&CNavNode::IsCovered) },
//{ 0x0, "_ZN8CNavNode10AssignAreaEP8CNavArea", mfunc_ptr_cast(&CNavNode::AssignArea) },
@@ -4890,54 +4892,61 @@ FunctionHook g_FunctionHooks[] =
//{ 0x0, "_ZN8CNavPathixEi", mfunc_ptr_cast(&CNavPath::operator[]) },
//{ 0x0, "_ZNK8CNavPath15GetSegmentCountEv", mfunc_ptr_cast(&CNavPath::GetSegmentCount) },
//{ 0x0, "_ZNK8CNavPath11GetEndpointEv", mfunc_ptr_cast(&CNavPath::GetEndpoint) },
- //{ 0x0, "_ZNK8CNavPath7IsAtEndERK6Vector", mfunc_ptr_cast(&CNavPath::IsAtEnd) },
- //{ 0x0, "_ZNK8CNavPath9GetLengthEv", mfunc_ptr_cast(&CNavPath::GetLength) },
- //{ 0x0, "_ZNK8CNavPath17GetPointAlongPathEfP6Vector", mfunc_ptr_cast(&CNavPath::GetPointAlongPath) },
- //{ 0x0, "_ZNK8CNavPath24GetSegmentIndexAlongPathEf", mfunc_ptr_cast(&CNavPath::GetSegmentIndexAlongPath) },
+ { 0x01D47570, "_ZNK8CNavPath7IsAtEndERK6Vector", mfunc_ptr_cast(&CNavPath::IsAtEnd) },
+ { 0x01D475D0, "_ZNK8CNavPath9GetLengthEv", mfunc_ptr_cast(&CNavPath::GetLength) },
+ //{ 0x01D47620, "_ZNK8CNavPath17GetPointAlongPathEfP6Vector", mfunc_ptr_cast(&CNavPath::GetPointAlongPath) }, // NOXREF
+ { 0x01D47760, "_ZNK8CNavPath24GetSegmentIndexAlongPathEf", mfunc_ptr_cast(&CNavPath::GetSegmentIndexAlongPath) },
//{ 0x0, "_ZNK8CNavPath7IsValidEv", mfunc_ptr_cast(&CNavPath::IsValid) },
//{ 0x0, "_ZN8CNavPath10InvalidateEv", mfunc_ptr_cast(&CNavPath::Invalidate) },
- //{ 0x0, "_ZN8CNavPath4DrawEv", mfunc_ptr_cast(&CNavPath::Draw) },
- //{ 0x0, "_ZNK8CNavPath22FindClosestPointOnPathEPK6VectoriiPS0_", mfunc_ptr_cast(&CNavPath::FindClosestPointOnPath) },
- //{ 0x0, "_ZN8CNavPath8OptimizeEv", mfunc_ptr_cast(&CNavPath::Optimize) },
- //{ 0x0, "_ZN8CNavPath20ComputePathPositionsEv", mfunc_ptr_cast(&CNavPath::ComputePathPositions) },
+ //{ 0x01D47AB0, "_ZN8CNavPath4DrawEv", mfunc_ptr_cast(&CNavPath::Draw) }, // NOXREF
+ //{ 0x01D477F0, "_ZNK8CNavPath22FindClosestPointOnPathEPK6VectoriiPS0_", mfunc_ptr_cast(&CNavPath::FindClosestPointOnPath) }, // NOXREF
+ { 0x01D47E20, "_ZN8CNavPath8OptimizeEv", mfunc_ptr_cast(&CNavPath::Optimize) }, // PURE
+ { 0x01D47170, "_ZN8CNavPath20ComputePathPositionsEv", mfunc_ptr_cast(&CNavPath::ComputePathPositions) },
{ 0x01D47A00, "_ZN8CNavPath16BuildTrivialPathEPK6VectorS2_", mfunc_ptr_cast(&CNavPath::BuildTrivialPath) },
- //{ 0x0, "_ZN8CNavPath20FindNextOccludedNodeEi", mfunc_ptr_cast(&CNavPath::FindNextOccludedNode) },
-
+ //{ 0x01D47B40, "_ZN8CNavPath20FindNextOccludedNodeEi", mfunc_ptr_cast(&CNavPath::FindNextOccludedNode) }, // NOXREF
//CStuckMonitor
- //{ 0x0, "", mfunc_ptr_cast(&CStuckMonitor::CStuckMonitor) },
- //{ 0x0, "_ZN13CStuckMonitor5ResetEv", mfunc_ptr_cast(&CStuckMonitor::Reset) },
- //{ 0x0, "_ZN13CStuckMonitor6UpdateEP7CImprov", mfunc_ptr_cast(&CStuckMonitor::Update) },
+ //{ 0x01D49B70, "", mfunc_ptr_cast(&CStuckMonitor::CStuckMonitor) },
+ { 0x01D49B90, "_ZN13CStuckMonitor5ResetEv", mfunc_ptr_cast(&CStuckMonitor::Reset) },
+ { 0x01D49BA0, "_ZN13CStuckMonitor6UpdateEP7CImprov", mfunc_ptr_cast(&CStuckMonitor::Update) },
//{ 0x0, "_ZNK13CStuckMonitor7IsStuckEv", mfunc_ptr_cast(&CStuckMonitor::IsStuck) },
//{ 0x0, "_ZNK13CStuckMonitor11GetDurationEv", mfunc_ptr_cast(&CStuckMonitor::GetDuration) },
//CNavPathFollower
- //{ 0x0, "", mfunc_ptr_cast(&CNavPathFollower::CNavPathFollower) },
+ //{ 0x01D47E30, "", mfunc_ptr_cast(&CNavPathFollower::CNavPathFollower) },
//{ 0x0, "_ZN16CNavPathFollower9SetImprovEP7CImprov", mfunc_ptr_cast(&CNavPathFollower::SetImprov) },
//{ 0x0, "_ZN16CNavPathFollower7SetPathEP8CNavPath", mfunc_ptr_cast(&CNavPathFollower::SetPath) },
- //{ 0x0, "_ZN16CNavPathFollower5ResetEv", mfunc_ptr_cast(&CNavPathFollower::Reset) },
- //{ 0x0, "_ZN16CNavPathFollower6UpdateEfb", mfunc_ptr_cast(&CNavPathFollower::Update) },
+ { 0x01D47E60, "_ZN16CNavPathFollower5ResetEv", mfunc_ptr_cast(&CNavPathFollower::Reset) },
+ { 0x01D47E80, "_ZN16CNavPathFollower6UpdateEfb", mfunc_ptr_cast(&CNavPathFollower::Update) },
//{ 0x0, "_ZN16CNavPathFollower5DebugEb", mfunc_ptr_cast(&CNavPathFollower::Debug) },
//{ 0x0, "_ZNK16CNavPathFollower7IsStuckEv", mfunc_ptr_cast(&CNavPathFollower::IsStuck) },
//{ 0x0, "_ZN16CNavPathFollower10ResetStuckEv", mfunc_ptr_cast(&CNavPathFollower::ResetStuck) },
//{ 0x0, "_ZNK16CNavPathFollower16GetStuckDurationEv", mfunc_ptr_cast(&CNavPathFollower::GetStuckDuration) },
- //{ 0x0, "_ZN16CNavPathFollower22FeelerReflexAdjustmentEP6Vectorf", mfunc_ptr_cast(&CNavPathFollower::FeelerReflexAdjustment) },
- //{ 0x0, "_ZNK16CNavPathFollower21FindOurPositionOnPathEP6Vectorb", mfunc_ptr_cast(&CNavPathFollower::FindOurPositionOnPath) },
- //{ 0x0, "_ZN16CNavPathFollower13FindPathPointEfP6VectorPi", mfunc_ptr_cast(&CNavPathFollower::FindPathPoint) },
+ { 0x01D49460, "_ZN16CNavPathFollower22FeelerReflexAdjustmentEP6Vectorf", mfunc_ptr_cast(&CNavPathFollower::FeelerReflexAdjustment) },
+ { 0x01D48450, "_ZNK16CNavPathFollower21FindOurPositionOnPathEP6Vectorb", mfunc_ptr_cast(&CNavPathFollower::FindOurPositionOnPath) },
+ { 0x01D487B0, "_ZN16CNavPathFollower13FindPathPointEfP6VectorPi", mfunc_ptr_cast(&CNavPathFollower::FindPathPoint) },
//HidingSpot
//{ 0x01D37DB0, "", mfunc_ptr_cast(&HidingSpot::HidingSpot) },
//{ 0x01D37E40, "", mfunc_ptr_cast(&HidingSpot::HidingSpot) },
{ 0x01D37EC0, "_ZNK10HidingSpot4SaveEij", mfunc_ptr_cast(&HidingSpot::Save) },
{ 0x01D37F00, "_ZN10HidingSpot4LoadEP9SteamFilej", mfunc_ptr_cast(&HidingSpot::Load) },
+//SteamFile
+ //{ 0x0, "", mfunc_ptr_cast(&SteamFile::SteamFile) },
+ //{ 0x0, "", mfunc_ptr_cast(&SteamFile::~SteamFile) },
+ //{ 0x0, "_ZNK9SteamFile7IsValidEv", mfunc_ptr_cast(&SteamFile::IsValid) },
+ { 0x01D46F00, "_ZN9SteamFile4ReadEPvi", mfunc_ptr_cast(&SteamFile::Read) },
//CNavArea
- //{ 0x01D44F80, "_ZN8CNavArea4SaveEij", mfunc_ptr_cast(&CNavArea::Save) },
- //{ 0x0, "_ZNK8CNavArea4SaveEP8_IO_FILE", mfunc_ptr_cast(&CNavArea::Save) },
+ //{ 0x01D45A50, "_ZNK14PlaceDirectory12EntryToPlaceEt", mfunc_ptr_cast(&PlaceDirectory::EntryToPlace) }, // NOTE: need hook LoadNavigationMap
+ { 0x01D44F80, "_ZN8CNavArea4SaveEij", mfunc_ptr_cast(&CNavArea::Save) },
+ { 0x01D44E60, "_ZNK8CNavArea4SaveEP8_IO_FILE", mfunc_ptr_cast(&CNavArea::Save) },
+ { 0x01D45330, "_ZN8CNavArea4LoadEP9SteamFilej", mfunc_ptr_cast(&CNavArea::Load) },
+ { 0x01D45AA0, "_ZN8CNavArea8PostLoadEv", mfunc_ptr_cast(&CNavArea::PostLoad) },
//{ 0x01D38040, "", mfunc_ptr_cast(&CNavArea::CNavArea) },
//{ 0x0, "", mfunc_ptr_cast(&CNavArea::CNavArea) },
//{ 0x0, "", mfunc_ptr_cast(&CNavArea::CNavArea) },
//{ 0x0, "", mfunc_ptr_cast(&CNavArea::CNavArea) },
//{ 0x01D386A0, "", mfunc_ptr_cast(&CNavArea::~CNavArea) },
- //{ 0x01D37FE0, "_ZN8CNavArea10InitializeEv", mfunc_ptr_cast(&CNavArea::Initialize) }, // PRIVATE
+ { 0x01D37FE0, "_ZN8CNavArea10InitializeEv", mfunc_ptr_cast(&CNavArea::Initialize) }, // PRIVATE
//{ 0x01D388A0, "_ZN8CNavArea15OnDestroyNotifyEPS_", mfunc_ptr_cast(&CNavArea::OnDestroyNotify) }, // NOXREF
- //{ 0x01D38960, "_ZN8CNavArea9ConnectToEPS_10NavDirType", mfunc_ptr_cast(&CNavArea::ConnectTo) },
+ { 0x01D38960, "_ZN8CNavArea9ConnectToEPS_10NavDirType", mfunc_ptr_cast(&CNavArea::ConnectTo) },
//{ 0x01D389D0, "_ZN8CNavArea10DisconnectEPS_", mfunc_ptr_cast(&CNavArea::Disconnect) }, // NOXREF
{ 0x01D38A40, "_ZN8CNavArea11FinishMergeEPS_", mfunc_ptr_cast(&CNavArea::FinishMerge) },
{ 0x01D38B60, "_ZN8CNavArea24MergeAdjacentConnectionsEPS_", mfunc_ptr_cast(&CNavArea::MergeAdjacentConnections) },
@@ -4955,7 +4964,7 @@ FunctionHook g_FunctionHooks[] =
//{ 0x01D3C790, "_ZNK8CNavArea14IsOverlappingYEPKS_", mfunc_ptr_cast(&CNavArea::IsOverlappingY) }, // NOXREF
{ 0x01D3C7C0, "_ZNK8CNavArea8ContainsEPK6Vector", mfunc_ptr_cast(&CNavArea::Contains) },
{ 0x01D3C8B0, "_ZNK8CNavArea10IsCoplanarEPKS_", mfunc_ptr_cast(&CNavArea::IsCoplanar) },
- //!@{ 0x01D3CA60, "_ZNK8CNavArea4GetZEPK6Vector", mfunc_ptr_cast(&CNavArea::GetZ) }, // Used refs
+ { 0x01D3CA60, "_ZNK8CNavArea4GetZEPK6Vector", mfunc_ptr_cast(&CNavArea::GetZ) }, // NOTE: definitely need to hook CNavAreaGrid::GetNavArea!!
//{ 0x01D3CB50, "_ZNK8CNavArea4GetZEff", mfunc_ptr_cast(&CNavArea::GetZ) }, // NOXREF
{ 0x01D3CB80, "_ZNK8CNavArea21GetClosestPointOnAreaEPK6VectorPS0_", mfunc_ptr_cast(&CNavArea::GetClosestPointOnArea) },
//{ 0x01D3CCD0, "_ZNK8CNavArea25GetDistanceSquaredToPointEPK6Vector", mfunc_ptr_cast(&CNavArea::GetDistanceSquaredToPoint) }, // NOXREF
@@ -4993,9 +5002,9 @@ FunctionHook g_FunctionHooks[] =
{ 0x01D43360, "_ZN12CNavAreaGrid10InitializeEffff", mfunc_ptr_cast(&CNavAreaGrid::Initialize) },
{ 0x01D43390, "_ZN12CNavAreaGrid10AddNavAreaEP8CNavArea", mfunc_ptr_cast(&CNavAreaGrid::AddNavArea) },
{ 0x01D43560, "_ZN12CNavAreaGrid13RemoveNavAreaEP8CNavArea", mfunc_ptr_cast(&CNavAreaGrid::RemoveNavArea) },
- //!@{ 0x01D43710, "_ZNK12CNavAreaGrid10GetNavAreaEPK6Vectorf", mfunc_ptr_cast(&CNavAreaGrid::GetNavArea) }, // Used refs
- //!@{ 0x01D43860, "_ZNK12CNavAreaGrid17GetNearestNavAreaEPK6Vectorb", mfunc_ptr_cast(&CNavAreaGrid::GetNearestNavArea) }, // Used refs
- //{ 0x0, "_ZNK12CNavAreaGrid14GetNavAreaByIDEj", mfunc_ptr_cast(&CNavAreaGrid::GetNavAreaByID) },
+ { 0x01D43710, "_ZNK12CNavAreaGrid10GetNavAreaEPK6Vectorf", mfunc_ptr_cast(&CNavAreaGrid::GetNavArea) }, // Used refs
+ { 0x01D43860, "_ZNK12CNavAreaGrid17GetNearestNavAreaEPK6Vectorb", mfunc_ptr_cast(&CNavAreaGrid::GetNearestNavArea) },
+ { 0x01D439C0, "_ZNK12CNavAreaGrid14GetNavAreaByIDEj", mfunc_ptr_cast(&CNavAreaGrid::GetNavAreaByID) },
{ 0x01D439F0, "_ZNK12CNavAreaGrid8GetPlaceEPK6Vector", mfunc_ptr_cast(&CNavAreaGrid::GetPlace) },
{ 0x01D3E4F0, "_Z18ClassifySniperSpotP10HidingSpot", (size_t)&ClassifySniperSpot },
//{ 0x0, "", (size_t)&buildGoodSizedList }, // NOXREF
@@ -5011,8 +5020,9 @@ FunctionHook g_FunctionHooks[] =
{ 0x01D3F020, "_Z10DrawDangerv", (size_t)&DrawDanger },
{ 0x01D3F1C0, "_Z14IsSpotOccupiedP11CBaseEntityPK6Vector", (size_t)&IsSpotOccupied },
{ 0x01D3F2A0, "_Z20FindNearbyHidingSpotP11CBaseEntityPK6VectorP8CNavAreafbb", (size_t)&FindNearbyHidingSpot },
+ //{ 0x01D3F650, "_ZN25CollectHidingSpotsFunctorclEP8CNavArea", mfunc_ptr_cast(&CollectHidingSpotsFunctor::operator()) },
{ 0x01D3FDE0, "_Z21FindNearbyRetreatSpotP11CBaseEntityPK6VectorP8CNavAreafib", mfunc_ptr_cast(&FindNearbyRetreatSpot) },
- //{ 0x0, "_Z20IsCrossingLineOfFireRK6VectorS1_P11CBaseEntityi", (size_t)&IsCrossingLineOfFire },
+ { 0x01D3FAD0, "_Z20IsCrossingLineOfFireRK6VectorS1_P11CBaseEntityi", (size_t)&IsCrossingLineOfFire },
{ 0x01D3F850, "_Z20FindRandomHidingSpotP11CBaseEntityjb", (size_t)&FindRandomHidingSpot },
{ 0x01D37FB0, "_Z17GetHidingSpotByIDj", (size_t)&GetHidingSpotByID },
{ 0x01D39F30, "_Z24ApproachAreaAnalysisPrepv", (size_t)&ApproachAreaAnalysisPrep },
@@ -5020,23 +5030,25 @@ FunctionHook g_FunctionHooks[] =
//{ 0x01D3A010, "_Z14DestroyLaddersv", (size_t)&DestroyLadders }, // NOXREF
{ 0x01D3A060, "_Z20DestroyNavigationMapv", (size_t)&DestroyNavigationMap },
{ 0x01D3A210, "_Z20StripNavigationAreasv", (size_t)&StripNavigationAreas },
+
#ifdef _WIN32
{ 0x01D3A870, "", (size_t)&FindFirstAreaInDirection },
- { 0x01D3A9E0, "", (size_t)&testJumpDown }, // NOXREF
- { 0x01D3AD20, "", (size_t)&IsAreaRoughlySquare }, // NOXREF
+ { 0x01D3AD20, "", (size_t)&IsAreaRoughlySquare },
+ { 0x01D2B030, "", (size_t)&IsEntityWalkable },
+ { 0x01D2B0B0, "", (size_t)&IsWalkableTraceLineClear },
+ { 0x01D3A9E0, "", (size_t)&testJumpDown },
#endif // _WIN32
- //{ 0x0, "", (size_t)&findJumpDownArea }, // NOXREF
+ //{ 0x0, "", (size_t)&findJumpDownArea }, // NOXREF
{ 0x01D3A330, "_Z21ConnectGeneratedAreasv", (size_t)&ConnectGeneratedAreas },
{ 0x01D3AAF0, "_Z19MergeGeneratedAreasv", (size_t)&MergeGeneratedAreas },
- //{ 0x0, "_Z6SplitXP8CNavArea", (size_t)&SplitX },
- //{ 0x0, "_Z6SplitYP8CNavArea", (size_t)&SplitY },
- //{ 0x0, "_Z13SquareUpAreasv", (size_t)&SquareUpAreas },
+ { 0x01D3AE00, "_Z6SplitXP8CNavArea", (size_t)&SplitX },
+ //{ 0x0, "_Z6SplitYP8CNavArea", (size_t)&SplitY }, // NOXREF
+ { 0x01D3AEE0, "_Z13SquareUpAreasv", (size_t)&SquareUpAreas },
{ 0x01D3B100, "_Z8TestAreaP8CNavNodeii", (size_t)&TestArea },
{ 0x01D3B2E0, "_Z9BuildAreaP8CNavNodeii", (size_t)&BuildArea },
{ 0x01D3B3F0, "_Z12BuildLaddersv", (size_t)&BuildLadders },
{ 0x01D3C1B0, "_Z13MarkJumpAreasv", (size_t)&MarkJumpAreas },
{ 0x01D3C280, "_Z26GenerateNavigationAreaMeshv", (size_t)&GenerateNavigationAreaMesh },
-
#endif // Nav_Region
#ifndef Hostage_Region
@@ -5053,25 +5065,25 @@ FunctionHook g_FunctionHooks[] =
{ 0x01D51270, "_ZN14CHostageImprov11ClearLookAtEv", mfunc_ptr_cast(&CHostageImprov::ClearLookAt_) },
{ 0x01D51280, "_ZN14CHostageImprov6FaceToERK6Vector", mfunc_ptr_cast(&CHostageImprov::FaceTo_) },
{ 0x01D512B0, "_ZN14CHostageImprov11ClearFaceToEv", mfunc_ptr_cast(&CHostageImprov::ClearFaceTo_) },
- //{ 0x0, "_ZNK14CHostageImprov12IsAtMoveGoalEf", mfunc_ptr_cast(&CHostageImprov::IsAtMoveGoal_) },
+ { 0x01D51AC0, "_ZNK14CHostageImprov12IsAtMoveGoalEf", mfunc_ptr_cast(&CHostageImprov::IsAtMoveGoal_) },
//{ 0x0, "_ZNK14CHostageImprov9HasLookAtEv", mfunc_ptr_cast(&CHostageImprov::HasLookAt_) }, // DEFAULT
//{ 0x0, "_ZNK14CHostageImprov9HasFaceToEv", mfunc_ptr_cast(&CHostageImprov::HasFaceTo_) }, // DEFAULT
- //{ 0x0, "_ZNK14CHostageImprov12IsAtFaceGoalEv", mfunc_ptr_cast(&CHostageImprov::IsAtFaceGoal_) },
- //{ 0x0, "_ZNK14CHostageImprov16IsFriendInTheWayERK6Vector", mfunc_ptr_cast(&CHostageImprov::IsFriendInTheWay_) },
- //{ 0x0, "_ZNK14CHostageImprov16IsFriendInTheWayEP11CBaseEntityRK6Vector", mfunc_ptr_cast(&CHostageImprov::IsFriendInTheWay_) },
+ { 0x01D51B20, "_ZNK14CHostageImprov12IsAtFaceGoalEv", mfunc_ptr_cast(&CHostageImprov::IsAtFaceGoal_) },
+ { 0x01D51B30, "_ZNK14CHostageImprov16IsFriendInTheWayERK6Vector", mfunc_ptr_cast(&CHostageImprov::IsFriendInTheWay_) },
+ { 0x01D51CB0, "_ZNK14CHostageImprov16IsFriendInTheWayEP11CBaseEntityRK6Vector", mfunc_ptr_cast(&CHostageImprov::IsFriendInTheWay_) },
//{ 0x0, "_ZN14CHostageImprov11MoveForwardEv", mfunc_ptr_cast(&CHostageImprov::MoveForward_) }, // DEFAULT
//{ 0x0, "_ZN14CHostageImprov12MoveBackwardEv", mfunc_ptr_cast(&CHostageImprov::MoveBackward_) }, // DEFAULT
//{ 0x0, "_ZN14CHostageImprov10StrafeLeftEv", mfunc_ptr_cast(&CHostageImprov::StrafeLeft_) }, // DEFAULT
//{ 0x0, "_ZN14CHostageImprov11StrafeRightEv", mfunc_ptr_cast(&CHostageImprov::StrafeRight_) },
- //{ 0x0, "_ZN14CHostageImprov4JumpEv", mfunc_ptr_cast(&CHostageImprov::Jump_) },
+ { 0x01D52260, "_ZN14CHostageImprov4JumpEv", mfunc_ptr_cast(&CHostageImprov::Jump_) },
{ 0x01D56710, "_ZN14CHostageImprov6CrouchEv", mfunc_ptr_cast(&CHostageImprov::Crouch_) },
{ 0x01D567A0, "_ZN14CHostageImprov7StandUpEv", mfunc_ptr_cast(&CHostageImprov::StandUp_) },
- //{ 0x0, "_ZN14CHostageImprov9TrackPathERK6Vectorf", mfunc_ptr_cast(&CHostageImprov::TrackPath_) },
+ { 0x01D52D80, "_ZN14CHostageImprov9TrackPathERK6Vectorf", mfunc_ptr_cast(&CHostageImprov::TrackPath_) },
{ 0x01D530D0, "_ZN14CHostageImprov11StartLadderEPK10CNavLadder15NavTraverseTypePK6VectorS6_", mfunc_ptr_cast(&CHostageImprov::StartLadder_) },
- //{ 0x01D530E0, "_ZN14CHostageImprov14TraverseLadderEPK10CNavLadder15NavTraverseTypePK6VectorS6_f", mfunc_ptr_cast(&CHostageImprov::TraverseLadder_) },
+ { 0x01D530E0, "_ZN14CHostageImprov14TraverseLadderEPK10CNavLadder15NavTraverseTypePK6VectorS6_f", mfunc_ptr_cast(&CHostageImprov::TraverseLadder_) },
{ 0x01D51150, "_ZN14CHostageImprov30GetSimpleGroundHeightWithFloorEPK6VectorPfPS0_", mfunc_ptr_cast(&CHostageImprov::GetSimpleGroundHeightWithFloor_) },
- //{ 0x0, "_ZN14CHostageImprov3RunEv", mfunc_ptr_cast(&CHostageImprov::Run_) },
- //{ 0x0, "_ZN14CHostageImprov4WalkEv", mfunc_ptr_cast(&CHostageImprov::Walk_) },
+ { 0x01D52350, "_ZN14CHostageImprov3RunEv", mfunc_ptr_cast(&CHostageImprov::Run_) },
+ { 0x01D52360, "_ZN14CHostageImprov4WalkEv", mfunc_ptr_cast(&CHostageImprov::Walk_) },
{ 0x01D52380, "_ZN14CHostageImprov4StopEv", mfunc_ptr_cast(&CHostageImprov::Stop_) },
//{ 0x0, "_ZNK14CHostageImprov12GetMoveAngleEv", mfunc_ptr_cast(&CHostageImprov::GetMoveAngle_) }, // DEFAULT
//{ 0x0, "_ZNK14CHostageImprov12GetFaceAngleEv", mfunc_ptr_cast(&CHostageImprov::GetFaceAngle_) }, // DEFAULT
@@ -5081,27 +5093,30 @@ FunctionHook g_FunctionHooks[] =
//{ 0x0, "_ZNK14CHostageImprov9IsRunningEv", mfunc_ptr_cast(&CHostageImprov::IsRunning_) }, // DEFAULT
//{ 0x0, "_ZNK14CHostageImprov9IsWalkingEv", mfunc_ptr_cast(&CHostageImprov::IsWalking_) }, // DEFAULT
//{ 0x01D56CC0, "_ZNK14CHostageImprov9IsStoppedEv", mfunc_ptr_cast(&CHostageImprov::IsStopped_) }, // DEFAULT
- //{ 0x0, "_ZNK14CHostageImprov11IsCrouchingEv", mfunc_ptr_cast(&CHostageImprov::IsCrouching_) }, // DEFAULT
- //{ 0x0, "_ZNK14CHostageImprov9IsJumpingEv", mfunc_ptr_cast(&CHostageImprov::IsJumping_) }, // DEFAULT
- //{ 0x0, "_ZNK14CHostageImprov13IsUsingLadderEv", mfunc_ptr_cast(&CHostageImprov::IsUsingLadder_) }, // DEFAULT
- //{ 0x0, "_ZNK14CHostageImprov10IsOnGroundEv", mfunc_ptr_cast(&CHostageImprov::IsOnGround_) },
- //{ 0x0, "_ZNK14CHostageImprov8IsMovingEv", mfunc_ptr_cast(&CHostageImprov::IsMoving_) },
+ //{ 0x01D56CD0, "_ZNK14CHostageImprov11IsCrouchingEv", mfunc_ptr_cast(&CHostageImprov::IsCrouching_) }, // DEFAULT
+ //{ 0x01D56CE0, "_ZNK14CHostageImprov9IsJumpingEv", mfunc_ptr_cast(&CHostageImprov::IsJumping_) }, // DEFAULT
+ //{ 0x01D56D20, "_ZNK14CHostageImprov13IsUsingLadderEv", mfunc_ptr_cast(&CHostageImprov::IsUsingLadder_) }, // DEFAULT
+ { 0x01D52460, "_ZNK14CHostageImprov10IsOnGroundEv", mfunc_ptr_cast(&CHostageImprov::IsOnGround_) },
+ { 0x01D52480, "_ZNK14CHostageImprov8IsMovingEv", mfunc_ptr_cast(&CHostageImprov::IsMoving_) },
//{ 0x0, "_ZNK14CHostageImprov6CanRunEv", mfunc_ptr_cast(&CHostageImprov::CanRun_) }, // DEFAULT
//{ 0x0, "_ZNK14CHostageImprov9CanCrouchEv", mfunc_ptr_cast(&CHostageImprov::CanCrouch_) }, // DEFAULT
//{ 0x0, "_ZNK14CHostageImprov7CanJumpEv", mfunc_ptr_cast(&CHostageImprov::CanJump_) }, // DEFAULT
{ 0x01D524C0, "_ZNK14CHostageImprov9IsVisibleERK6Vectorb", mfunc_ptr_cast(&CHostageImprov::IsVisible_) },
- //{ 0x0, "_ZNK14CHostageImprov19IsPlayerLookingAtMeEP11CBasePlayerf", mfunc_ptr_cast(&CHostageImprov::IsPlayerLookingAtMe_) },
- //{ 0x0, "_ZNK14CHostageImprov22IsAnyPlayerLookingAtMeEif", mfunc_ptr_cast(&CHostageImprov::IsAnyPlayerLookingAtMe_) },
- //{ 0x0, "_ZNK14CHostageImprov32GetClosestPlayerByTravelDistanceEiPf", mfunc_ptr_cast(&CHostageImprov::GetClosestPlayerByTravelDistance_) },
+ { 0x01D52530, "_ZNK14CHostageImprov19IsPlayerLookingAtMeEP11CBasePlayerf", mfunc_ptr_cast(&CHostageImprov::IsPlayerLookingAtMe_) },
+ { 0x01D526A0, "_ZNK14CHostageImprov22IsAnyPlayerLookingAtMeEif", mfunc_ptr_cast(&CHostageImprov::IsAnyPlayerLookingAtMe_) },
+ { 0x01D527B0, "_ZNK14CHostageImprov32GetClosestPlayerByTravelDistanceEiPf", mfunc_ptr_cast(&CHostageImprov::GetClosestPlayerByTravelDistance_) },
//{ 0x01D56D60, "_ZNK14CHostageImprov16GetLastKnownAreaEv", mfunc_ptr_cast(&CHostageImprov::GetLastKnownArea_) }, // DEFAULT
- //{ 0x0, "_ZN14CHostageImprov8OnUpdateEf", mfunc_ptr_cast(&CHostageImprov::OnUpdate_) },
- //{ 0x0, "_ZN14CHostageImprov8OnUpkeepEf", mfunc_ptr_cast(&CHostageImprov::OnUpkeep_) },
+ { 0x01D54500, "_ZN14CHostageImprov8OnUpdateEf", mfunc_ptr_cast(&CHostageImprov::OnUpdate_) },
+ { 0x01D53FF0, "_ZN14CHostageImprov8OnUpkeepEf", mfunc_ptr_cast(&CHostageImprov::OnUpkeep_) },
{ 0x01D52A60, "_ZN14CHostageImprov7OnResetEv", mfunc_ptr_cast(&CHostageImprov::OnReset_) },
{ 0x01D54C10, "_ZN14CHostageImprov11OnGameEventE13GameEventTypeP11CBaseEntityS2_", mfunc_ptr_cast(&CHostageImprov::OnGameEvent_) },
{ 0x01D55280, "_ZN14CHostageImprov7OnTouchEP11CBaseEntity", mfunc_ptr_cast(&CHostageImprov::OnTouch_) },
//non-virtual func
- //{ 0x01D51900, "_ZN14CHostageImprov12FaceOutwardsEv", mfunc_ptr_cast(&CHostageImprov::FaceOutwards) },
- //{ 0x0, "_ZNK14CHostageImprov16IsFriendInTheWayEv", mfunc_ptr_cast(&CHostageImprov::IsFriendInTheWay) },
+ { 0x01D51900, "_ZN14CHostageImprov12FaceOutwardsEv", mfunc_ptr_cast(&CHostageImprov::FaceOutwards) },
+ { 0x01D51F80, "_ZNK14CHostageImprov16IsFriendInTheWayEv", mfunc_ptr_cast(&CHostageImprov::IsFriendInTheWay) },
+ //{ 0x01D52150, "_ZN10CheckAheadclEP11CBaseEntity", mfunc_ptr_cast(&CheckAhead::operator()) },
+ //{ 0x0, "_ZN15CheckWayFunctorclEP8CHostage", mfunc_ptr_cast(&CheckWayFunctor::operator()) },
+ { 0x01D53E70, "_ZNK17KeepPersonalSpaceclEP11CBaseEntity", mfunc_ptr_cast(&KeepPersonalSpace::operator()) },
//{ 0x01D52EE0, "_ZN14CHostageImprov20SetKnownGoodPositionERK6Vector", mfunc_ptr_cast(&CHostageImprov::SetKnownGoodPosition) }, // NOXREF
//{ 0x0, "_ZNK14CHostageImprov20GetKnownGoodPositionEv", mfunc_ptr_cast(&CHostageImprov::GetKnownGoodPosition) },
{ 0x01D52F90, "_ZN14CHostageImprov24ResetToKnownGoodPositionEv", mfunc_ptr_cast(&CHostageImprov::ResetToKnownGoodPosition) },
@@ -5130,14 +5145,14 @@ FunctionHook g_FunctionHooks[] =
{ 0x01D54010, "_ZN14CHostageImprov17IsTerroristNearbyEv", mfunc_ptr_cast(&CHostageImprov::IsTerroristNearby) },
{ 0x01D55C20, "_ZN14CHostageImprov8FrightenENS_9ScareTypeE", mfunc_ptr_cast(&CHostageImprov::Frighten) },
{ 0x01D55BF0, "_ZNK14CHostageImprov8IsScaredEv", mfunc_ptr_cast(&CHostageImprov::IsScared) },
- //{ 0x0, "_ZNK14CHostageImprov17GetScareIntensityEv", mfunc_ptr_cast(&CHostageImprov::GetScareIntensity) },
- //{ 0x0, "_ZNK14CHostageImprov20IsIgnoringTerroristsEv", mfunc_ptr_cast(&CHostageImprov::IsIgnoringTerrorists) },
- //{ 0x0, "_ZNK14CHostageImprov13GetAggressionEv", mfunc_ptr_cast(&CHostageImprov::GetAggression) },
+ //{ 0x0, "_ZNK14CHostageImprov17GetScareIntensityEv", mfunc_ptr_cast(&CHostageImprov::GetScareIntensity) }, // DEFAULT
+ //{ 0x0, "_ZNK14CHostageImprov20IsIgnoringTerroristsEv", mfunc_ptr_cast(&CHostageImprov::IsIgnoringTerrorists) }, // DEFAULT
+ //{ 0x0, "_ZNK14CHostageImprov13GetAggressionEv", mfunc_ptr_cast(&CHostageImprov::GetAggression) }, // DEFAULT
{ 0x01D55ED0, "_ZN14CHostageImprov7ChatterE18HostageChatterTypeb", mfunc_ptr_cast(&CHostageImprov::Chatter) },
{ 0x01D55F80, "_ZN14CHostageImprov14DelayedChatterEf18HostageChatterTypeb", mfunc_ptr_cast(&CHostageImprov::DelayedChatter) },
//{ 0x01D55FE0, "_ZN14CHostageImprov20UpdateDelayedChatterEv", mfunc_ptr_cast(&CHostageImprov::UpdateDelayedChatter) }, // NOXREF
- //{ 0x0, "_ZNK14CHostageImprov9IsTalkingEv", mfunc_ptr_cast(&CHostageImprov::IsTalking) },
- //{ 0x0, "_ZN14CHostageImprov22UpdateGrenadeReactionsEv", mfunc_ptr_cast(&CHostageImprov::UpdateGrenadeReactions) },
+ //{ 0x0, "_ZNK14CHostageImprov9IsTalkingEv", mfunc_ptr_cast(&CHostageImprov::IsTalking) }, // DEFAULT
+ { 0x01D54150, "_ZN14CHostageImprov22UpdateGrenadeReactionsEv", mfunc_ptr_cast(&CHostageImprov::UpdateGrenadeReactions) },
{ 0x01D55D20, "_ZN14CHostageImprov6AfraidEv", mfunc_ptr_cast(&CHostageImprov::Afraid) },
{ 0x01D56290, "_ZN14CHostageImprov4WaveEv", mfunc_ptr_cast(&CHostageImprov::Wave) },
{ 0x01D56210, "_ZN14CHostageImprov5AgreeEv", mfunc_ptr_cast(&CHostageImprov::Agree) },
@@ -5148,25 +5163,27 @@ FunctionHook g_FunctionHooks[] =
//{ 0x01D56910, "_ZN14CHostageImprov25UpdateStationaryAnimationEv", mfunc_ptr_cast(&CHostageImprov::UpdateStationaryAnimation) }, // NOXREF
//{ 0x0, "_ZNK14CHostageImprov9GetEntityEv", mfunc_ptr_cast(&CHostageImprov::GetEntity) },
//{ 0x01D540C0, "_ZN14CHostageImprov24CheckForNearbyTerroristsEv", mfunc_ptr_cast(&CHostageImprov::CheckForNearbyTerrorists) }, // NOXREF
- //{ 0x01D534F0, "_ZN14CHostageImprov14UpdatePositionEf", mfunc_ptr_cast(&CHostageImprov::UpdatePosition) },
+ { 0x01D534F0, "_ZN14CHostageImprov14UpdatePositionEf", mfunc_ptr_cast(&CHostageImprov::UpdatePosition) },
{ 0x01D512C0, "_ZN14CHostageImprov11MoveTowardsERK6Vectorf", mfunc_ptr_cast(&CHostageImprov::MoveTowards) },
- //{ 0x01D517A0, "_ZN14CHostageImprov11FaceTowardsERK6Vectorf", mfunc_ptr_cast(&CHostageImprov::FaceTowards) },
- //{ 0x0, "_ZN14CHostageImprov8GetSpeedEv", mfunc_ptr_cast(&CHostageImprov::GetSpeed) },
+ { 0x01D517A0, "_ZN14CHostageImprov11FaceTowardsERK6Vectorf", mfunc_ptr_cast(&CHostageImprov::FaceTowards) },
+ //{ 0x01D52250, "_ZN14CHostageImprov8GetSpeedEv", mfunc_ptr_cast(&CHostageImprov::GetSpeed) }, // NOXREF
//{ 0x0, "_ZN14CHostageImprov12SetMoveAngleEf", mfunc_ptr_cast(&CHostageImprov::SetMoveAngle) },
{ 0x01D56300, "_ZN14CHostageImprov6WiggleEv", mfunc_ptr_cast(&CHostageImprov::Wiggle) },
{ 0x01D564E0, "_ZN14CHostageImprov9ClearPathEv", mfunc_ptr_cast(&CHostageImprov::ClearPath) },
+ { 0x01D4A890, "_Z16NavAreaBuildPathI15HostagePathCostEbP8CNavAreaS2_PK6VectorRT_PS2_", (size_t)&NavAreaBuildPath__HostagePathCost__wrapper },
+ { 0x01D15AD0, "_Z16NavAreaBuildPathI16ShortestPathCostEbP8CNavAreaS2_PK6VectorRT_PS2_", (size_t)&NavAreaBuildPath__ShortestPathCost__wrapper },
//{ 0x01D511C0, "_ZN14CHostageImprov17DiscontinuityJumpEfbb", mfunc_ptr_cast(&CHostageImprov::DiscontinuityJump) }, // NOXREF
- //{ 0x0, "_ZN14CHostageImprov12UpdateVisionEv", mfunc_ptr_cast(&CHostageImprov::UpdateVision) },
+ { 0x01D52C00, "_ZN14CHostageImprov12UpdateVisionEv", mfunc_ptr_cast(&CHostageImprov::UpdateVision) },
//HostageState
//virtual func
//{ 0x0, "_ZN12HostageStateD0Ev", mfunc_ptr_cast(&HostageState::~HostageState) },
//{ 0x0, "_ZN12HostageStateD2Ev", mfunc_ptr_cast(&HostageState::~HostageState) },
- //{ 0x0, "_ZN12HostageState25UpdateStationaryAnimationEP14CHostageImprov", mfunc_ptr_cast(&HostageState::UpdateStationaryAnimation) },
+ //{ 0x01D569C0, "_ZN12HostageState25UpdateStationaryAnimationEP14CHostageImprov", mfunc_ptr_cast(&HostageState::UpdateStationaryAnimation) },
//HostageIdleState
//virtual func
{ 0x01D4B3A0, "_ZN16HostageIdleState7OnEnterEP14CHostageImprov", mfunc_ptr_cast(&HostageIdleState::OnEnter_) },
- //{ 0x01D4B3C0, "_ZN16HostageIdleState8OnUpdateEP14CHostageImprov", mfunc_ptr_cast(&HostageIdleState::OnUpdate_) },
- //{ 0x0, "_ZN16HostageIdleState6OnExitEP14CHostageImprov", mfunc_ptr_cast(&HostageIdleState::OnExit_) },
+ { 0x01D4B3C0, "_ZN16HostageIdleState8OnUpdateEP14CHostageImprov", mfunc_ptr_cast(&HostageIdleState::OnUpdate_) },
+ { 0x01D4BBB0, "_ZN16HostageIdleState6OnExitEP14CHostageImprov", mfunc_ptr_cast(&HostageIdleState::OnExit_) },
//{ 0x0, "_ZNK16HostageIdleState7GetNameEv", mfunc_ptr_cast(&HostageIdleState::GetName_) }, // DEFAULT
{ 0x01D4BBD0, "_ZN16HostageIdleState25UpdateStationaryAnimationEP14CHostageImprov", mfunc_ptr_cast(&HostageIdleState::UpdateStationaryAnimation_) },
//{ 0x0, "_ZN16HostageIdleState15OnMoveToSuccessERK6Vector", mfunc_ptr_cast(&HostageIdleState::OnMoveToSuccess_) }, // DEFAULT
@@ -5181,42 +5198,42 @@ FunctionHook g_FunctionHooks[] =
//{ 0x0, "_ZN19HostageStateMachine25UpdateStationaryAnimationEP14CHostageImprov", mfunc_ptr_cast(&HostageStateMachine::UpdateStationaryAnimation) },
//HostageEscapeToCoverState
//virtual func
- //{ 0x0, "_ZN25HostageEscapeToCoverState7OnEnterEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeToCoverState::OnEnter) },
- //{ 0x0, "_ZN25HostageEscapeToCoverState8OnUpdateEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeToCoverState::OnUpdate) },
- //{ 0x0, "_ZN25HostageEscapeToCoverState6OnExitEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeToCoverState::OnExit) },
- //{ 0x0, "_ZNK25HostageEscapeToCoverState7GetNameEv", mfunc_ptr_cast(&HostageEscapeToCoverState::GetName) },
- //{ 0x0, "_ZN25HostageEscapeToCoverState15OnMoveToFailureERK6VectorN12IImprovEvent17MoveToFailureTypeE", mfunc_ptr_cast(&HostageEscapeToCoverState::OnMoveToFailure) },
+ { 0x01D4A200, "_ZN25HostageEscapeToCoverState7OnEnterEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeToCoverState::OnEnter_) },
+ { 0x01D4A4A0, "_ZN25HostageEscapeToCoverState8OnUpdateEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeToCoverState::OnUpdate_) },
+ //{ 0x01D4A590, "_ZN25HostageEscapeToCoverState6OnExitEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeToCoverState::OnExit_) }, // PURE
+ //{ 0x01D56B00, "_ZNK25HostageEscapeToCoverState7GetNameEv", mfunc_ptr_cast(&HostageEscapeToCoverState::GetName_) },
+ { 0x01D4A5A0, "_ZN25HostageEscapeToCoverState15OnMoveToFailureERK6VectorN12IImprovEvent17MoveToFailureTypeE", mfunc_ptr_cast(&HostageEscapeToCoverState::OnMoveToFailure_) },
//non-virtual func
//{ 0x0, "_ZN25HostageEscapeToCoverState13SetRescueGoalERK6Vector", mfunc_ptr_cast(&HostageEscapeToCoverState::SetRescueGoal) },
//HostageEscapeLookAroundState
//virtual func
- //{ 0x0, "_ZN28HostageEscapeLookAroundState7OnEnterEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeLookAroundState::OnEnter) },
- //{ 0x0, "_ZN28HostageEscapeLookAroundState8OnUpdateEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeLookAroundState::OnUpdate) },
- //{ 0x0, "_ZN28HostageEscapeLookAroundState6OnExitEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeLookAroundState::OnExit) },
- //{ 0x0, "_ZNK28HostageEscapeLookAroundState7GetNameEv", mfunc_ptr_cast(&HostageEscapeLookAroundState::GetName) },
+ { 0x01D4A5E0, "_ZN28HostageEscapeLookAroundState7OnEnterEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeLookAroundState::OnEnter_) },
+ { 0x01D4A620, "_ZN28HostageEscapeLookAroundState8OnUpdateEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeLookAroundState::OnUpdate_) },
+ { 0x01D4A680, "_ZN28HostageEscapeLookAroundState6OnExitEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeLookAroundState::OnExit_) },
+ //{ 0x0, "_ZNK28HostageEscapeLookAroundState7GetNameEv", mfunc_ptr_cast(&HostageEscapeLookAroundState::GetName_) },
//HostageEscapeState
//virtual func
- //{ 0x0, "_ZN18HostageEscapeState7OnEnterEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeState::OnEnter) },
- //{ 0x0, "_ZN18HostageEscapeState8OnUpdateEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeState::OnUpdate) },
- //{ 0x0, "_ZN18HostageEscapeState6OnExitEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeState::OnExit) },
- //{ 0x0, "_ZNK18HostageEscapeState7GetNameEv", mfunc_ptr_cast(&HostageEscapeState::GetName) },
- //{ 0x0, "_ZN18HostageEscapeState15OnMoveToFailureERK6VectorN12IImprovEvent17MoveToFailureTypeE", mfunc_ptr_cast(&HostageEscapeState::OnMoveToFailure) },
+ { 0x01D4A690, "_ZN18HostageEscapeState7OnEnterEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeState::OnEnter_) },
+ { 0x01D4A720, "_ZN18HostageEscapeState8OnUpdateEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeState::OnUpdate_) },
+ { 0x01D4A880, "_ZN18HostageEscapeState6OnExitEP14CHostageImprov", mfunc_ptr_cast(&HostageEscapeState::OnExit_) },
+ //{ 0x01D56A80, "_ZNK18HostageEscapeState7GetNameEv", mfunc_ptr_cast(&HostageEscapeState::GetName_) },
+ //{ 0x0, "_ZN18HostageEscapeState15OnMoveToFailureERK6VectorN12IImprovEvent17MoveToFailureTypeE", mfunc_ptr_cast(&HostageEscapeState::OnMoveToFailure_) }, // NOXREF
//non-virtual func
//{ 0x0, "_ZN18HostageEscapeState7ToCoverEv", mfunc_ptr_cast(&HostageEscapeState::ToCover) },
//{ 0x0, "_ZN18HostageEscapeState10LookAroundEv", mfunc_ptr_cast(&HostageEscapeState::LookAround) },
//HostageRetreatState
//virtual func
- //{ 0x01D4BC30, "_ZN19HostageRetreatState7OnEnterEP14CHostageImprov", mfunc_ptr_cast(&HostageRetreatState::OnEnter_) },
+ { 0x01D4BC30, "_ZN19HostageRetreatState7OnEnterEP14CHostageImprov", mfunc_ptr_cast(&HostageRetreatState::OnEnter_) },
{ 0x01D4BC50, "_ZN19HostageRetreatState8OnUpdateEP14CHostageImprov", mfunc_ptr_cast(&HostageRetreatState::OnUpdate_) },
- //{ 0x01D4BDB0, "_ZN19HostageRetreatState6OnExitEP14CHostageImprov", mfunc_ptr_cast(&HostageRetreatState::OnExit_) },
+ //{ 0x01D4BDB0, "_ZN19HostageRetreatState6OnExitEP14CHostageImprov", mfunc_ptr_cast(&HostageRetreatState::OnExit_) }, // PURE
//{ 0x01D56BD0, "_ZNK19HostageRetreatState7GetNameEv", mfunc_ptr_cast(&HostageRetreatState::GetName_) },
//HostageFollowState
//virtual func
- //{ 0x0, "_ZN18HostageFollowState7OnEnterEP14CHostageImprov", mfunc_ptr_cast(&HostageFollowState::OnEnter) },
- //{ 0x0, "_ZN18HostageFollowState8OnUpdateEP14CHostageImprov", mfunc_ptr_cast(&HostageFollowState::OnUpdate) },
- //{ 0x0, "_ZN18HostageFollowState6OnExitEP14CHostageImprov", mfunc_ptr_cast(&HostageFollowState::OnExit) },
- //{ 0x0, "_ZNK18HostageFollowState7GetNameEv", mfunc_ptr_cast(&HostageFollowState::GetName) },
- //{ 0x0, "_ZN18HostageFollowState25UpdateStationaryAnimationEP14CHostageImprov", mfunc_ptr_cast(&HostageFollowState::UpdateStationaryAnimation) },
+ { 0x01D4AC70, "_ZN18HostageFollowState7OnEnterEP14CHostageImprov", mfunc_ptr_cast(&HostageFollowState::OnEnter_) },
+ { 0x01D4ACF0, "_ZN18HostageFollowState8OnUpdateEP14CHostageImprov", mfunc_ptr_cast(&HostageFollowState::OnUpdate_) },
+ { 0x01D4B320, "_ZN18HostageFollowState6OnExitEP14CHostageImprov", mfunc_ptr_cast(&HostageFollowState::OnExit_) },
+ //{ 0x0, "_ZNK18HostageFollowState7GetNameEv", mfunc_ptr_cast(&HostageFollowState::GetName_) },
+ { 0x01D4B330, "_ZN18HostageFollowState25UpdateStationaryAnimationEP14CHostageImprov", mfunc_ptr_cast(&HostageFollowState::UpdateStationaryAnimation_) },
//non-virtual func
//{ 0x0, "_ZN18HostageFollowState9SetLeaderEP11CBaseEntity", mfunc_ptr_cast(&HostageFollowState::SetLeader) },
//{ 0x0, "_ZNK18HostageFollowState9GetLeaderEv", mfunc_ptr_cast(&HostageFollowState::GetLeader) },
@@ -5231,7 +5248,7 @@ FunctionHook g_FunctionHooks[] =
{ 0x01D49E10, "_ZN19HostageAnimateState11AddSequenceEP14CHostageImprovPKcff", mfunc_ptr_cast(&HostageAnimateState::AddSequence) },
{ 0x01D49F00, "_ZN19HostageAnimateState11AddSequenceEP14CHostageImproviff", mfunc_ptr_cast(&HostageAnimateState::AddSequence) },
//{ 0x0, "_ZNK19HostageAnimateState6IsBusyEv", mfunc_ptr_cast(&HostageAnimateState::IsBusy) },
- //{ 0x0, "_ZNK19HostageAnimateState9IsPlayingEP14CHostageImprovPKc", mfunc_ptr_cast(&HostageAnimateState::IsPlaying) },
+ //{ 0x01D4A1C0, "_ZNK19HostageAnimateState9IsPlayingEP14CHostageImprovPKc", mfunc_ptr_cast(&HostageAnimateState::IsPlaying) }, // NOXREF
//{ 0x0, "_ZN19HostageAnimateState20GetCurrentSequenceIDEv", mfunc_ptr_cast(&HostageAnimateState::GetCurrentSequenceID) }, // NOXREF
//{ 0x0, "_ZNK19HostageAnimateState14GetPerformanceEv", mfunc_ptr_cast(&HostageAnimateState::GetPerformance) },
//{ 0x0, "_ZN19HostageAnimateState14SetPerformanceENS_15PerformanceTypeE", mfunc_ptr_cast(&HostageAnimateState::SetPerformance) },
@@ -5248,7 +5265,6 @@ FunctionHook g_FunctionHooks[] =
//{ 0x01D50D90, "_ZN8CHostage10BloodColorEv", mfunc_ptr_cast(&CHostage::BloodColor_) },
{ 0x01D4DB10, "_ZN8CHostage5TouchEP11CBaseEntity", mfunc_ptr_cast(&CHostage::Touch_) },
{ 0x01D4D710, "_ZN8CHostage3UseEP11CBaseEntityS1_8USE_TYPEf", mfunc_ptr_cast(&CHostage::Use_) },
-
//non-virtual func
//!!{ 0x01D4C450, "_ZN8CHostage9IdleThinkEv", mfunc_ptr_cast(&CHostage::IdleThink) }, // export func
{ 0x01D4CBB0, "_ZN8CHostage6RemoveEv", mfunc_ptr_cast(&CHostage::Remove) },
@@ -5279,7 +5295,6 @@ FunctionHook g_FunctionHooks[] =
//{ 0x0, "_ZN8CHostage6IsDeadEv", mfunc_ptr_cast(&CHostage::IsDead) }, // NOXREF
//{ 0x0, "_ZNK8CHostage8IsAtHomeEv", mfunc_ptr_cast(&CHostage::IsAtHome) }, // NOXREF
//{ 0x0, "_ZNK8CHostage15GetHomePositionEv", mfunc_ptr_cast(&CHostage::GetHomePosition) }, // NOXREF
-
{ 0x01D4BDC0, "hostage_entity", (size_t)&hostage_entity },
{ 0x01D4BE10, "monster_scientist", (size_t)&monster_scientist },
//CHostageManager
@@ -5394,6 +5409,7 @@ VirtualTableRef g_TableRefs[] =
{ 0x01DF6FE4, "HostageStateMachine", 4 },
{ 0x01DF7180, "HostageEscapeToCoverState", 4 },
{ 0x01DF6F18, "HostageAnimateState", 4 },
+ { 0x01DF6F9C, "HostageEscapeState", 6 },
{ 0x01E00BBC, "CArmoury", CBASE_VIRTUAL_COUNT },
{ 0x01DFE4E4, "CSoundEnt", CBASE_VIRTUAL_COUNT },
@@ -5569,20 +5585,16 @@ AddressRef g_FunctionRefs[] =
{
#ifndef Function_References_Region
- { 0x01D3CA60, "_ZNK8CNavArea4GetZEPK6Vector", (size_t)&pGetZ__Vector },
- { 0x01D43860, "_ZNK12CNavAreaGrid17GetNearestNavAreaEPK6Vectorb", (size_t)&pGetNearestNavArea },
- { 0x01D43710, "_ZNK12CNavAreaGrid10GetNavAreaEPK6Vectorf", (size_t)&pGetNavArea },
+ //{ 0x01D3CA60, "_ZNK8CNavArea4GetZEPK6Vector", (size_t)&pGetZ__Vector },
+ //{ 0x01D43860, "_ZNK12CNavAreaGrid17GetNearestNavAreaEPK6Vectorb", (size_t)&pGetNearestNavArea },
+ //{ 0x01D43710, "_ZNK12CNavAreaGrid10GetNavAreaEPK6Vectorf", (size_t)&pGetNavArea },
{ 0x01D2EDD0, "_ZN6CCSBot16UpdateLookAnglesEv", (size_t)&pCCSBot__UpdateLookAngles },
{ 0x01D2D9B0, "_ZN6CCSBot6UpdateEv", (size_t)&pCCSBot__Update },
{ 0x01D20AE0, "_ZN6CCSBot11ResetValuesEv", (size_t)&pCCSBot__ResetValues },
-
- { 0x01D46310, "_Z17LoadNavigationMapv", (size_t)&pLoadNavigationMap },
{ 0x01D19C70, "_ZN9BotPhrase9RandomizeEv", (size_t)&pBotPhrase__Randomize },
-
{ 0x01D25270, "_ZN13CCSBotManager6AddBotEPK10BotProfile18BotProfileTeamType", (size_t)&pCCSBotManager__AddBot },
{ 0x01D80C90, "_Z16InstallGameRulesv", (size_t)&pInstallGameRules },
{ 0x01D4C450, "_ZN8CHostage9IdleThinkEv", (size_t)&pCHostage__IdleThink },
- { 0x01D517A0, "_ZN14CHostageImprov11FaceTowardsERK6Vectorf", (size_t)&pCHostageImprov__FaceTowards },
#endif // Function_References_Region
@@ -5595,7 +5607,8 @@ AddressRef g_DataRefs[] =
{ 0x01E61BD0, "g_engfuncs", (size_t)&pg_engfuncs },
{ 0x01E61E48, "gpGlobals", (size_t)&pgpGlobals },
-
+
+ { 0x01E10768, "GameEventName", (size_t)&pGameEventName },
{ 0x01E2A3F8, "_ZL14s_shared_token", (size_t)&ps_shared_token },
{ 0x01E13218, "_ZL14s_shared_quote", (size_t)&ps_shared_quote },
@@ -6024,7 +6037,7 @@ AddressRef g_DataRefs[] =
{ 0x01E23470, "cv_tutor_hint_interval_time", (size_t)&pcv_tutor_hint_interval_time },
{ 0x01E11EE4, "cv_hostage_debug", (size_t)&pcv_hostage_debug },
{ 0x01E11EF8, "cv_hostage_stop", (size_t)&pcv_hostage_stop },
- //{ 0x0, "_ZL14placeDirectory", (size_t)&pplaceDirectory },
+ //{ 0x0, "_ZL14placeDirectory", (size_t)&pplaceDirectory }, // DONT USE - NOXREF
{ 0x01E2A0E4, "TheNavLadderList", (size_t)&pTheNavLadderList },
{ 0x01E2A0F0, "TheHidingSpotList", (size_t)&pTheHidingSpotList },
{ 0x01E14C5C, "sPlayerModelFiles", (size_t)&psPlayerModelFiles },
@@ -6046,6 +6059,8 @@ AddressRef g_DataRefs[] =
{ 0x01E29888, "TheNavAreaGrid", (size_t)&pTheNavAreaGrid },
{ 0x01E2A250, "_ZN8CNavNode6m_listE", mfunc_ptr_cast(&CNavNode::pm_list) },
{ 0x01E2A254, "_ZN8CNavNode12m_listLengthE", mfunc_ptr_cast(&CNavNode::pm_listLength) },
+ { 0x01E11E88, "Opposite", (size_t)&pOpposite },
+
//{ 0x0, "_ZN8CNavArea8m_nextIDE", mfunc_ptr_cast(&CNavArea::m_nextID) },
{ 0x01E11584, "_ZN8CNavArea14m_masterMarkerE", mfunc_ptr_cast(&CNavArea::pm_masterMarker) },
{ 0x01E11588, "_ZN10HidingSpot8m_nextIDE", mfunc_ptr_cast(&HidingSpot::pm_nextID) },
diff --git a/regamedll/hookers/memory.cpp b/regamedll/hookers/memory.cpp
index 09da73b0..a172351f 100644
--- a/regamedll/hookers/memory.cpp
+++ b/regamedll/hookers/memory.cpp
@@ -740,7 +740,7 @@ bool HIDDEN HookFunction(Module *module, FunctionHook *hook)
//int seedad = pUTIL_SharedRandomLong(seed,low,high);
//memcpy(addr_orig,patchByte,5);
- if (strcmp(hook->symbolName,"_ZNK14CHostageImprov16IsFriendInTheWayEv")==0)
+ if (strcmp(hook->symbolName,"_ZN25HostageEscapeToCoverState15OnMoveToFailureERK6VectorN12IImprovEvent17MoveToFailureTypeE")==0)
{
addr_orig = (void *)hook->originalAddress;
diff --git a/regamedll/hookers/osconfig.h b/regamedll/hookers/osconfig.h
index 200a93e6..b5dff9f2 100644
--- a/regamedll/hookers/osconfig.h
+++ b/regamedll/hookers/osconfig.h
@@ -236,7 +236,7 @@
static const bool __isLinux = true;
#endif
-#define EXT_FUNC FORCE_STACK_ALIGN
+#define EXT_FUNC /*FORCE_STACK_ALIGN*/
extern void regamedll_log(const char *fmt, ...);
extern void __declspec(noreturn) regamedll_syserror(const char *fmt, ...);
diff --git a/regamedll/msvc/ReGameDLL.vcxproj b/regamedll/msvc/ReGameDLL.vcxproj
index 0ef36650..8c83121d 100644
--- a/regamedll/msvc/ReGameDLL.vcxproj
+++ b/regamedll/msvc/ReGameDLL.vcxproj
@@ -1132,7 +1132,7 @@
Level3
Disabled
true
- HOOK_GAMEDLL;REGAMEDLL_SELF;REGAMEDLL_CHECKS;CLIENT_WEAPONS;USE_BREAKPAD_HANDLER;DEDICATED;_CRT_SECURE_NO_WARNINGS;_DEBUG;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)
+ PLAY_GAMEDLL;HOOK_GAMEDLL;REGAMEDLL_SELF;REGAMEDLL_CHECKS;CLIENT_WEAPONS;USE_BREAKPAD_HANDLER;DEDICATED;_CRT_SECURE_NO_WARNINGS;_DEBUG;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)
Precise
/arch:IA32 %(AdditionalOptions)
MultiThreadedDebug
@@ -1204,7 +1204,7 @@
Level3
Disabled
true
- REGAMEDLL_SELF;REGAMEDLL_CHECKS;CLIENT_WEAPONS;USE_BREAKPAD_HANDLER;DEDICATED;_CRT_SECURE_NO_WARNINGS;_DEBUG;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)
+ REGAMEDLL_SELF;PLAY_GAMEDLL;REGAMEDLL_CHECKS;CLIENT_WEAPONS;USE_BREAKPAD_HANDLER;DEDICATED;_CRT_SECURE_NO_WARNINGS;_DEBUG;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)
Precise
/arch:IA32 %(AdditionalOptions)
MultiThreadedDebug
@@ -1317,7 +1317,7 @@
true
true
true
- REGAMEDLL_SELF;HOOK_GAMEDLL;REGAMEDLL_CHECKS;CLIENT_WEAPONS;USE_BREAKPAD_HANDLER;DEDICATED;_CRT_SECURE_NO_WARNINGS;NOMINMAX;%(PreprocessorDefinitions)
+ REGAMEDLL_SELF;PLAY_GAMEDLL;HOOK_GAMEDLL;REGAMEDLL_CHECKS;CLIENT_WEAPONS;USE_BREAKPAD_HANDLER;DEDICATED;_CRT_SECURE_NO_WARNINGS;NOMINMAX;%(PreprocessorDefinitions)
MultiThreaded
/arch:IA32 %(AdditionalOptions)
Use
diff --git a/regamedll/pm_shared/pm_math.h b/regamedll/pm_shared/pm_math.h
index 63d4be33..01f01e22 100644
--- a/regamedll/pm_shared/pm_math.h
+++ b/regamedll/pm_shared/pm_math.h
@@ -32,8 +32,8 @@
#pragma once
#endif
-#define PITCH 0 // up/down
-#define YAW 1 // left/right
+#define PITCH 0 // up/down
+#define YAW 1 // left/right
#define ROLL 2 // fall over
#ifdef HOOK_GAMEDLL
@@ -48,32 +48,32 @@ extern int nanmask;
#define IS_NAN(x) ((*reinterpret_cast(&(x)) & nanmask) == nanmask)
-NOBODY float anglemod(float a);
-void AngleVectors(const vec_t *angles, vec_t *forward, vec_t *right, vec_t *up);
-NOBODY void AngleVectorsTranspose(const vec_t *angles, vec_t *forward, vec_t *right, vec_t *up);
-void AngleMatrix(const vec_t *angles, float (*matrix)[4]);
-NOBODY void AngleIMatrix(const vec_t *angles, float (*matrix)[4]);
-NOBODY void NormalizeAngles(float *angles);
-NOBODY void InterpolateAngles(float *start, float *end, float *output, float frac);
-NOBODY float AngleBetweenVectors(const vec_t *v1, const vec_t *v2);
-NOBODY void VectorTransform(const vec_t *in1, float *in2, vec_t *out);
-int VectorCompare(const vec_t *v1, const vec_t *v2);
-void VectorMA(const vec_t *veca, float scale, const vec_t *vecb, vec_t *vecc);
-
-float_precision _DotProduct(vec_t *v1, vec_t *v2);
-void _VectorSubtract(vec_t *veca, vec_t *vecb, vec_t *out);
-void _VectorAdd(vec_t *veca, vec_t *vecb, vec_t *out);
-void _VectorCopy(vec_t *in, vec_t *out);
-void _CrossProduct(const vec_t *v1, const vec_t *v2, vec_t *cross);
-
-float_precision Length(const vec_t *v);
-NOBODY float Distance(const vec_t *v1, const vec_t *v2);
-float_precision VectorNormalize(vec_t *v);
-
-NOBODY void VectorInverse(vec_t *v);
-NOBODY void VectorScale(const vec_t *in, vec_t scale, vec_t *out);
-NOBODY int Q_log2(int val);
-NOBODY void VectorMatrix(vec_t *forward, vec_t *right, vec_t *up);
+NOBODY float anglemod(float a);
+void AngleVectors(const vec_t *angles, vec_t *forward, vec_t *right, vec_t *up);
+NOBODY void AngleVectorsTranspose(const vec_t *angles, vec_t *forward, vec_t *right, vec_t *up);
+void AngleMatrix(const vec_t *angles, float (*matrix)[4]);
+NOBODY void AngleIMatrix(const vec_t *angles, float (*matrix)[4]);
+NOBODY void NormalizeAngles(float *angles);
+NOBODY void InterpolateAngles(float *start, float *end, float *output, float frac);
+NOBODY float AngleBetweenVectors(const vec_t *v1, const vec_t *v2);
+NOBODY void VectorTransform(const vec_t *in1, float *in2, vec_t *out);
+int VectorCompare(const vec_t *v1, const vec_t *v2);
+void VectorMA(const vec_t *veca, float scale, const vec_t *vecb, vec_t *vecc);
+
+float_precision _DotProduct(vec_t *v1, vec_t *v2);
+void _VectorSubtract(vec_t *veca, vec_t *vecb, vec_t *out);
+void _VectorAdd(vec_t *veca, vec_t *vecb, vec_t *out);
+void _VectorCopy(vec_t *in, vec_t *out);
+void _CrossProduct(const vec_t *v1, const vec_t *v2, vec_t *cross);
+
+float_precision Length(const vec_t *v);
+NOBODY float Distance(const vec_t *v1, const vec_t *v2);
+float_precision VectorNormalize(vec_t *v);
+
+NOBODY void VectorInverse(vec_t *v);
+NOBODY void VectorScale(const vec_t *in, vec_t scale, vec_t *out);
+NOBODY int Q_log2(int val);
+NOBODY void VectorMatrix(vec_t *forward, vec_t *right, vec_t *up);
NOBODY void VectorAngles(const vec_t *forward, vec_t *angles);
#endif // PM_MATH_H
diff --git a/regamedll/pm_shared/pm_shared.cpp b/regamedll/pm_shared/pm_shared.cpp
index 83120358..e110c29d 100644
--- a/regamedll/pm_shared/pm_shared.cpp
+++ b/regamedll/pm_shared/pm_shared.cpp
@@ -2644,7 +2644,7 @@ void PM_DropPunchAngle(vec_t *punchangle)
len = VectorNormalize(punchangle);
len -= (10.0 + len * 0.5) * pmove->frametime;
-#ifdef HOOK_GAMEDLL
+#ifdef PLAY_GAMEDLL
len = Q_max(len, 0.0);
#else
len = Q_max(len, 0.0f);
diff --git a/regamedll/regamedll/dlls.h b/regamedll/regamedll/dlls.h
index 72f04568..b346ed0d 100644
--- a/regamedll/regamedll/dlls.h
+++ b/regamedll/regamedll/dlls.h
@@ -99,6 +99,7 @@
#include "buttons.h"
// CSBOT and Nav
+#include "game_shared/GameEvent.h" // Game event enum used by career mode, tutor system, and bots
#include "game_shared/bot/bot_util.h"
#include "game_shared/bot/simple_state_machine.h"